import { Inject, Injectable } from '@nestjs/common';
import fs from 'fs-extra';
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
import sharp from 'sharp';
import { Logger } from 'winston';

@Injectable()
export class FileService {
  constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) {
    fs.ensureDirSync(`./pictures`);
    fs.ensureDirSync(`./pictures/profile`);
    fs.ensureDirSync(`./pictures/logo`);
    fs.ensureDirSync(`./pictures/property`);
  }
  // ############
  // Profile
  // ############
  async storeProfilePicture(file: Express.Multer.File, adjustedEmail: string) {
    const quality = 50;
    const output = await sharp(file.buffer)
      .resize({ width: 300 })
      .avif({ quality }) // Verwende AVIF
      //.webp({ quality }) // Verwende Webp
      .toBuffer();
    await sharp(output).toFile(`./pictures/profile/${adjustedEmail}.avif`);
  }
  hasProfile(adjustedEmail: string) {
    return fs.existsSync(`./pictures/profile/${adjustedEmail}.avif`);
  }
  // ############
  // Logo
  // ############
  async storeCompanyLogo(file: Express.Multer.File, adjustedEmail: string) {
    const quality = 50;
    const output = await sharp(file.buffer)
      .resize({ width: 300 })
      .avif({ quality }) // Verwende AVIF
      //.webp({ quality }) // Verwende Webp
      .toBuffer();
    await sharp(output).toFile(`./pictures/logo/${adjustedEmail}.avif`); // Ersetze Dateierweiterung
    // await fs.outputFile(`./pictures/logo/${userId}`, file.buffer);
  }
  hasCompanyLogo(adjustedEmail: string) {
    return fs.existsSync(`./pictures/logo/${adjustedEmail}.avif`) ? true : false;
  }
  // ############
  // Property
  // ############
  async getPropertyImages(imagePath: string, serial: string): Promise<string[]> {
    const result: string[] = [];
    const directory = `./pictures/property/${imagePath}/${serial}`;
    if (fs.existsSync(directory)) {
      const files = await fs.readdir(directory);
      files.forEach(f => {
        result.push(f);
      });
      return result;
    } else {
      return [];
    }
  }
  async hasPropertyImages(imagePath: string, serial: string): Promise<boolean> {
    const directory = `./pictures/property/${imagePath}/${serial}`;
    if (fs.existsSync(directory)) {
      const files = await fs.readdir(directory);
      return files.length > 0;
    } else {
      return false;
    }
  }
  async storePropertyPicture(file: Express.Multer.File, imagePath: string, serial: string): Promise<string> {
    const directory = `./pictures/property/${imagePath}/${serial}`;
    fs.ensureDirSync(`${directory}`);
    const imageName = await this.getNextImageName(directory);
    //await fs.outputFile(`${directory}/${imageName}`, file.buffer);
    await this.resizeImageToAVIF(file.buffer, 150 * 1024, imageName, directory);
    return `${imageName}.avif`;
  }
  // ############
  // utils
  // ############
  async getNextImageName(directory) {
    try {
      const files = await fs.readdir(directory);
      const imageNumbers = files
        .map(file => parseInt(file, 10)) // Dateinamen direkt in Zahlen umwandeln
        .filter(number => !isNaN(number)) // Sicherstellen, dass die Konvertierung gültig ist
        .sort((a, b) => a - b); // Aufsteigend sortieren

      const nextNumber = imageNumbers.length > 0 ? Math.max(...imageNumbers) + 1 : 1;
      return `${nextNumber}`; // Keine Endung für den Dateinamen
    } catch (error) {
      console.error('Fehler beim Lesen des Verzeichnisses:', error);
      return null;
    }
  }
  async resizeImageToAVIF(buffer: Buffer, maxSize: number, imageName: string, directory: string) {
    const quality = 50; // AVIF kann mit niedrigeren Qualitätsstufen gute Ergebnisse erzielen
    const start = Date.now();
    const output = await sharp(buffer)
      .resize({ width: 1500 })
      .avif({ quality }) // Verwende AVIF
      //.webp({ quality }) // Verwende Webp
      .toBuffer();
    await sharp(output).toFile(`${directory}/${imageName}.avif`); // Ersetze Dateierweiterung
    const timeTaken = Date.now() - start;
    this.logger.info(`Quality: ${quality} - Time: ${timeTaken} milliseconds`);
  }
  deleteImage(path: string) {
    fs.unlinkSync(path);
  }

  deleteDirectoryIfExists(imagePath) {
    const dirPath = `pictures/property/${imagePath}`;
    try {
      const exists = fs.pathExistsSync();
      if (exists) {
        fs.removeSync(dirPath);
        console.log(`Directory ${dirPath} was deleted.`);
      } else {
        console.log(`Directory ${dirPath} does not exist.`);
      }
    } catch (error) {
      console.error(`Error while deleting ${dirPath}:`, error);
    }
  }
}
