import { Injectable } from '@angular/core';
import { AttachedFile } from '../models/data.model';
import {DomSanitizer, SafeHtml} from '@angular/platform-browser';

export interface FileValidationResult {
  isValid: boolean;
  error?: string;
}

export interface FileHandlerConfig {
  maxFileSize: number;
  maxFiles: number;
  acceptedTypes: string[];
}

@Injectable({
  providedIn: 'root'
})
export class FileHandlerService {
  private defaultConfig: FileHandlerConfig = {
    maxFileSize: 10 * 1024 * 1024, // 10MB
    maxFiles: 10,
    acceptedTypes: [
      'image/*',
      'application/pdf',
      'application/msword',
      'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
      'application/vnd.ms-excel',
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      'text/*'
    ]
  };
  constructor(private sanitizer: DomSanitizer) {
  }

  get getAcceptedTypes(){
    return this.defaultConfig.acceptedTypes
  }
  validateFile(file: File, config: Partial<FileHandlerConfig> = {}): FileValidationResult {
    const finalConfig = { ...this.defaultConfig, ...config };

    if (file.size > finalConfig.maxFileSize) {
      return {
        isValid: false,
        error: `Le fichier "${file.name}" dépasse la taille maximale de ${this.formatFileSize(finalConfig.maxFileSize)}.`
      };
    }
    const isTypeAccepted = finalConfig.acceptedTypes.some(acceptedType => {
      if (acceptedType.endsWith('/*')) {
        const category = acceptedType.split('/')[0];
        return file.type.startsWith(category + '/');
      }
      return file.type === acceptedType;
    });

    if (!isTypeAccepted) {
      return {
        isValid: false,
        error: `Le type de fichier "${file.type}" n'est pas accepté.`
      };
    }

    return { isValid: true };
  }

  validateFiles(
    files: File[],
    existingFilesCount: number = 0,
    config: Partial<FileHandlerConfig> = {}
  ): FileValidationResult {
    const finalConfig = { ...this.defaultConfig, ...config };

    if (existingFilesCount + files.length > finalConfig.maxFiles) {
      return {
        isValid: false,
        error: `Vous ne pouvez joindre que ${finalConfig.maxFiles} fichiers maximum.`
      };
    }

    for (const file of files) {
      const result = this.validateFile(file, config);
      if (!result.isValid) {
        return result;
      }
    }

    return { isValid: true };
  }

  async processFiles(files: File[]): Promise<AttachedFile[]> {
    const processedFiles: AttachedFile[] = [];

    for (const file of files) {
      const attachedFile = await this.processFile(file);
      processedFiles.push(attachedFile);
    }

    return processedFiles;
  }


  async processFile(file: File): Promise<AttachedFile> {
    const id = this.generateFileId();
    const url = URL.createObjectURL(file);

    const attachedFile: AttachedFile = {
      id,
      file,
      url
    };

    if (this.isImage(file)) {
      try {
        attachedFile.preview = await this.generateImagePreview(file);
      } catch (error) {
        console.error('Erreur lors de la génération de la preview:', error);
      }
    }

    return attachedFile;
  }

  private generateImagePreview(file: File): Promise<string> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();

      reader.onload = (e: ProgressEvent<FileReader>) => {
        if (e.target?.result) {
          resolve(e.target.result as string);
        } else {
          reject(new Error('Impossible de lire le fichier'));
        }
      };
      reader.onerror = () => reject(new Error('Erreur de lecture du fichier'));
      reader.readAsDataURL(file);
    });
  }



  cleanupFiles(files: AttachedFile[]): void {
    files.forEach(file => {
      if (file.url) {
        URL.revokeObjectURL(file.url);
      }
    });
  }


  cleanupFile(file: AttachedFile): void {
    if (file.url) {
      URL.revokeObjectURL(file.url);
    }
  }


  private generateFileId(): string {
    return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  }


  isImage(file: File): boolean {
    return file.type.startsWith('image/');
  }


  isPdf(file: File): boolean {
    return file.type === 'application/pdf' || file.type.includes('pdf');
  }

  isWordDocument(file: File): boolean {
    return file.type.includes('word') ||
      file.type.includes('document') ||
      file.type === 'application/msword' ||
      file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
  }


  isExcelDocument(file: File): boolean {
    return file.type.includes('excel') ||
      file.type.includes('sheet') ||
      file.type.includes('spreadsheet') ||
      file.type === 'application/vnd.ms-excel' ||
      file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
  }

  isTextFile(file: File): boolean {
    return file.type.startsWith('text/');
  }


  formatFileSize(bytes: number): string {
    if (bytes === 0) return '0 Bytes';
    const k = 1024;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
  }

  cloneAttachedFile(attachedFile: AttachedFile): AttachedFile {
    return {
      ...attachedFile,
      file: attachedFile.file,
      url: attachedFile.url,
      preview: attachedFile.preview
    };
  }


  cloneAttachedFiles(attachedFiles: AttachedFile[]): AttachedFile[] {
    return attachedFiles.map(file => this.cloneAttachedFile(file));
  }


  getFileIcon(file: File): SafeHtml {
    let svgIcon = '';

    if (this.isImage(file)) {
      svgIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-file-image" viewBox="0 0 16 16">
        <path d="M8.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0"/>
        <path d="M12 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2M3 2a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v8l-2.083-2.083a.5.5 0 0 0-.76.063L8 11 5.835 9.7a.5.5 0 0 0-.611.076L3 12z"/>
      </svg>`;
    } else if (this.isPdf(file)) {
      svgIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-filetype-pdf" viewBox="0 0 16 16">
        <path fill-rule="evenodd" d="M14 4.5V14a2 2 0 0 1-2 2h-1v-1h1a1 1 0 0 0 1-1V4.5h-2A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v9H2V2a2 2 0 0 1 2-2h5.5zM1.6 11.85H0v3.999h.791v-1.342h.803q.43 0 .732-.173.305-.175.463-.474a1.4 1.4 0 0 0 .161-.677q0-.375-.158-.677a1.2 1.2 0 0 0-.46-.477q-.3-.18-.732-.179m.545 1.333a.8.8 0 0 1-.085.38.57.57 0 0 1-.238.241.8.8 0 0 1-.375.082H.788V12.48h.66q.327 0 .512.181.185.183.185.522m1.217-1.333v3.999h1.46q.602 0 .998-.237a1.45 1.45 0 0 0 .595-.689q.196-.45.196-1.084 0-.63-.196-1.075a1.43 1.43 0 0 0-.589-.68q-.396-.234-1.005-.234zm.791.645h.563q.371 0 .609.152a.9.9 0 0 1 .354.454q.118.302.118.753a2.3 2.3 0 0 1-.068.592 1.1 1.1 0 0 1-.196.422.8.8 0 0 1-.334.252 1.3 1.3 0 0 1-.483.082h-.563zm3.743 1.763v1.591h-.79V11.85h2.548v.653H7.896v1.117h1.606v.638z"/>
      </svg>`;
    } else if (this.isWordDocument(file)) {
      svgIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-filetype-doc" viewBox="0 0 16 16">
        <path fill-rule="evenodd" d="M14 4.5V14a2 2 0 0 1-2 2v-1a1 1 0 0 0 1-1V4.5h-2A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v9H2V2a2 2 0 0 1 2-2h5.5zM.5 11.85h1.6q.434 0 .732.179.302.175.46.477.158.302.158.677t-.158.677q-.159.3-.464.474a1.45 1.45 0 0 1-.732.173H.5zm.791 1.984v1.328H.5v-3.999h1.915q.493 0 .729.174.237.173.377.472.14.3.14.677 0 .374-.14.677-.137.299-.375.472-.236.173-.728.173zm4.035-3.306h1.6q.434 0 .732.179.302.175.46.477.158.302.158.677t-.158.677q-.159.3-.464.474a1.45 1.45 0 0 1-.732.173h-1.6zm.791 1.984v1.328h-.791v-3.999h1.915q.493 0 .729.174.237.173.377.472.14.3.14.677 0 .374-.14.677-.137.299-.375.472-.236.173-.728.173z"/>
      </svg>`;
    } else if (this.isExcelDocument(file)) {
      svgIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-filetype-xls" viewBox="0 0 16 16">
  <path fill-rule="evenodd" d="M14 4.5V14a2 2 0 0 1-2 2h-1v-1h1a1 1 0 0 0 1-1V4.5h-2A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v9H2V2a2 2 0 0 1 2-2h5.5zM6.472 15.29a1.2 1.2 0 0 1-.111-.449h.765a.58.58 0 0 0 .254.384q.106.073.25.114.143.041.319.041.246 0 .413-.07a.56.56 0 0 0 .255-.193.5.5 0 0 0 .085-.29.39.39 0 0 0-.153-.326q-.152-.12-.462-.193l-.619-.143a1.7 1.7 0 0 1-.539-.214 1 1 0 0 1-.351-.367 1.1 1.1 0 0 1-.123-.524q0-.366.19-.639.19-.272.527-.422.338-.15.777-.149.457 0 .78.152.324.153.5.41.18.255.2.566h-.75a.56.56 0 0 0-.12-.258.6.6 0 0 0-.247-.181.9.9 0 0 0-.369-.068q-.325 0-.513.152a.47.47 0 0 0-.184.384q0 .18.143.3a1 1 0 0 0 .405.175l.62.143q.326.075.566.211a1 1 0 0 1 .375.358q.135.222.135.56 0 .37-.188.656a1.2 1.2 0 0 1-.539.439q-.351.158-.858.158-.381 0-.665-.09a1.4 1.4 0 0 1-.478-.252 1.1 1.1 0 0 1-.29-.375m-2.945-3.358h-.893L1.81 13.37h-.036l-.832-1.438h-.93l1.227 1.983L0 15.931h.861l.853-1.415h.035l.85 1.415h.908L2.253 13.94zm2.727 3.325H4.557v-3.325h-.79v4h2.487z"/>
</svg>`;
    } else if (this.isTextFile(file)) {
      svgIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-file-earmark-text" viewBox="0 0 16 16">
        <path d="M5.5 7a.5.5 0 0 0 0 1h5a.5.5 0 0 0 0-1zM5 9.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5m0 2a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5"/>
        <path d="M9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V4.5zm0 1v2A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1z"/>
      </svg>`;
    } else {
      svgIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-file-earmark" viewBox="0 0 16 16">
        <path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z"/>
      </svg>`;
    }

    return this.sanitizer.bypassSecurityTrustHtml(svgIcon);
  }
}
