import { BadRequestException, Injectable, Logger } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { existsSync, mkdirSync } from "fs";
import { join } from "path";
import * as sharp from "sharp";

@Injectable()
export class UploadsService {
  private readonly logger = new Logger(UploadsService.name);
  private readonly uploadDir: string;

  constructor(private configService: ConfigService) {
    this.uploadDir =
      this.configService.get("UPLOAD_DIR") || join(process.cwd(), "uploads");
    this.ensureUploadDir();
  }

  private ensureUploadDir() {
    const dirs = [
      this.uploadDir,
      join(this.uploadDir, "fotos"),
      join(this.uploadDir, "fotos", "thumbnails"),
      join(this.uploadDir, "firmas"),
      join(this.uploadDir, "pdfs"),
    ];

    dirs.forEach((dir) => {
      if (!existsSync(dir)) {
        mkdirSync(dir, { recursive: true });
      }
    });
  }

  /**
   * Upload and compress a photo
   * Converts to WebP, max 1920px width, quality 80%
   * Also generates a thumbnail (300px)
   */
  async uploadFoto(
    file: Express.Multer.File,
  ): Promise<{ url: string; thumbnail: string }> {
    const timestamp = Date.now();
    const filename = `foto-${timestamp}.webp`;
    const thumbnailFilename = `foto-${timestamp}-thumb.webp`;

    const fotoPath = join(this.uploadDir, "fotos", filename);
    const thumbnailPath = join(
      this.uploadDir,
      "fotos",
      "thumbnails",
      thumbnailFilename,
    );

    try {
      await sharp(file.buffer)
        .resize(1920, null, { withoutEnlargement: true, fit: "inside" })
        .webp({ quality: 80 })
        .toFile(fotoPath);

      await sharp(file.buffer)
        .resize(300, 300, { fit: "cover" })
        .webp({ quality: 70 })
        .toFile(thumbnailPath);
    } catch {
      throw new BadRequestException(
        "La foto no pudo procesarse. Verifica que sea una imagen valida.",
      );
    }

    return {
      url: `/uploads/fotos/${filename}`,
      thumbnail: `/uploads/fotos/thumbnails/${thumbnailFilename}`,
    };
  }

  /**
   * Upload and compress a signature
   * Converts to WebP, quality 85%
   */
  async uploadFirma(file: Express.Multer.File): Promise<{ url: string }> {
    const timestamp = Date.now();
    const filename = `firma-${timestamp}.webp`;
    const firmaPath = join(this.uploadDir, "firmas", filename);

    try {
      await sharp(file.buffer)
        .resize(800, null, { withoutEnlargement: true, fit: "inside" })
        .webp({ quality: 85 })
        .toFile(firmaPath);
    } catch {
      throw new BadRequestException(
        "La firma no pudo procesarse. Capturala de nuevo.",
      );
    }

    return {
      url: `/uploads/firmas/${filename}`,
    };
  }

  /**
   * Upload a PDF (no compression)
   */
  async uploadPdf(file: Express.Multer.File): Promise<{ url: string }> {
    const timestamp = Date.now();
    const filename = `pdf-${timestamp}.pdf`;
    const pdfPath = join(this.uploadDir, "pdfs", filename);

    // For PDFs, just save the buffer directly
    const fs = await import("fs/promises");
    await fs.writeFile(pdfPath, file.buffer);

    return {
      url: `/uploads/pdfs/${filename}`,
    };
  }

  /**
   * Delete a file by URL
   */
  async deleteFile(url: string): Promise<void> {
    try {
      const filePath = join(process.cwd(), url);
      const fs = await import("fs/promises");
      await fs.unlink(filePath);
    } catch (error) {
      this.logger.error(`Error deleting file ${url}:`, error);
    }
  }
}
