import {
  Injectable,
  Logger,
  BadRequestException,
  InternalServerErrorException,
} from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { UpdatePdfSettingsDto } from './dto/update-pdf-settings.dto';
import { PdfSettings } from '@prisma/client';

@Injectable()
export class SettingsService {
  private readonly logger = new Logger(SettingsService.name);
  private readonly MAX_LOGO_SIZE = 2 * 1024 * 1024; // 2MB in bytes
  private readonly ALLOWED_MIME_TYPES = ['image/png', 'image/jpeg', 'image/svg+xml'];

  constructor(private prisma: PrismaService) {}

  /**
   * Get PDF settings - creates default if none exist (singleton pattern)
   */
  async getPdfSettings(): Promise<PdfSettings> {
    this.logger.log('Fetching PDF settings');

    let settings = await this.prisma.pdfSettings.findFirst();

    if (!settings) {
      this.logger.log('No settings found, creating defaults');
      settings = await this.prisma.pdfSettings.create({
        data: {
          organizationName: 'VIP Coordinator',
          accentColor: '#2c3e50',
          contactEmail: 'contact@example.com',
          contactPhone: '555-0100',
          contactLabel: 'Questions or Changes?',
          pageSize: 'LETTER',
          timezone: 'America/New_York',
          showDraftWatermark: false,
          showConfidentialWatermark: false,
          showTimestamp: true,
          showAppUrl: false,
          showFlightInfo: true,
          showDriverNames: true,
          showVehicleNames: true,
          showVipNotes: true,
          showEventDescriptions: true,
        },
      });
      this.logger.log(`Created default settings: ${settings.id}`);
    }

    return settings;
  }

  /**
   * Update PDF settings
   */
  async updatePdfSettings(dto: UpdatePdfSettingsDto): Promise<PdfSettings> {
    this.logger.log('Updating PDF settings');

    // Get existing settings (or create if none exist)
    const existing = await this.getPdfSettings();

    try {
      const updated = await this.prisma.pdfSettings.update({
        where: { id: existing.id },
        data: dto,
      });

      this.logger.log(`Settings updated: ${updated.id}`);
      return updated;
    } catch (error) {
      this.logger.error(`Failed to update settings: ${error.message}`);
      throw new InternalServerErrorException('Failed to update PDF settings');
    }
  }

  /**
   * Upload logo as base64 data URL
   */
  async uploadLogo(file: Express.Multer.File): Promise<PdfSettings> {
    this.logger.log(`Uploading logo: ${file.originalname} (${file.size} bytes)`);

    // Validate file size
    if (file.size > this.MAX_LOGO_SIZE) {
      throw new BadRequestException(
        `Logo file too large. Maximum size is ${this.MAX_LOGO_SIZE / 1024 / 1024}MB`,
      );
    }

    // Validate MIME type
    if (!this.ALLOWED_MIME_TYPES.includes(file.mimetype)) {
      throw new BadRequestException(
        `Invalid file type. Allowed types: PNG, JPG, SVG`,
      );
    }

    // Convert to base64 data URL
    const base64 = file.buffer.toString('base64');
    const dataUrl = `data:${file.mimetype};base64,${base64}`;

    // Get existing settings
    const existing = await this.getPdfSettings();

    try {
      const updated = await this.prisma.pdfSettings.update({
        where: { id: existing.id },
        data: { logoUrl: dataUrl },
      });

      this.logger.log(`Logo uploaded: ${file.originalname}`);
      return updated;
    } catch (error) {
      this.logger.error(`Failed to upload logo: ${error.message}`);
      throw new InternalServerErrorException('Failed to upload logo');
    }
  }

  /**
   * Delete logo
   */
  async deleteLogo(): Promise<PdfSettings> {
    this.logger.log('Deleting logo');

    const existing = await this.getPdfSettings();

    try {
      const updated = await this.prisma.pdfSettings.update({
        where: { id: existing.id },
        data: { logoUrl: null },
      });

      this.logger.log('Logo deleted');
      return updated;
    } catch (error) {
      this.logger.error(`Failed to delete logo: ${error.message}`);
      throw new InternalServerErrorException('Failed to delete logo');
    }
  }
}
