import { Injectable, signal } from '@angular/core';
import imageCompression from 'browser-image-compression';

@Injectable({ providedIn: 'root' })
export class FileManagerService {
  file = signal<File | null>(null);
  imagePreviewUrl = signal<string | null>(null);
  fileError = signal<string | null>(null);
  isCompressing = signal<boolean>(false);

  private readonly MAX_FILE_SIZE = 5 * 1024 * 1024; // 5Mo en bytes
  private readonly ALLOWED_IMAGE_TYPES = ['image/jpeg', 'image/png', 'image/webp'];
  private readonly ALLOWED_EXTENSIONS = ['jpg', 'jpeg', 'png', 'webp'];

  formatFileSize(bytes: number): string {
    if (bytes === 0) return '0 Octets';

    const k = 1024;
    const sizes = ['Octets', 'Ko', 'Mo', 'Go'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));

    return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
  }

  async onPictureChange($event: Event): Promise<void> {
    const target = $event.target as HTMLInputElement;
    const selectedFile = target?.files?.[0];

    if (!selectedFile) {
      return;
    }

    // Réinitialiser l'erreur
    this.fileError.set(null);

    // Vérifier le type de fichier
    if (!this.ALLOWED_IMAGE_TYPES.includes(selectedFile.type)) {
      this.resetFile();
      this.fileError.set('Le fichier doit être une image (JPEG, PNG ou WebP)');
      target.value = '';
      return;
    }

    // Vérifier l'extension du fichier (sécurité supplémentaire)
    const fileExtension = selectedFile.name.split('.').pop()?.toLowerCase();
    if (!fileExtension || !this.ALLOWED_EXTENSIONS.includes(fileExtension)) {
      this.resetFile();
      this.fileError.set('Extension de fichier non autorisée');
      target.value = '';
      return;
    }

    // Vérifier la taille du fichier
    if (selectedFile.size > this.MAX_FILE_SIZE) {
      this.resetFile();
      this.fileError.set(
        `L'image est trop volumineuse (${this.formatFileSize(selectedFile.size)}). Taille maximale autorisée : 5 Mo`
      );
      target.value = '';
      return;
    }

    // Configuration de la compression
    const options = {
      maxSizeMB: 1, // On vise une taille max de 1MB
      maxWidthOrHeight: 1920, // On redimensionne si l'image est immense (4K+)
      useWebWorker: true, // Ne pas bloquer l'interface
      fileType: 'image/webp', // (Optionnel) Convertir en WebP pour le web (plus léger)
    };

    try {
      this.isCompressing.set(true);

      // Compression
      const compressedFile = await imageCompression(selectedFile, options);

      // Mise à jour des signaux avec le fichier optimisé
      this.file.set(compressedFile);
      this.readFile(compressedFile);
    } catch (error) {
      this.fileError.set("Impossible de compresser l'image.");
      this.resetFile();
    } finally {
      this.isCompressing.set(false);
      target.value = '';
    }
  }

  onFileChange($event: Event): void {
    const target = $event.target as HTMLInputElement;
    const selectedFile = target?.files?.[0];

    if (!selectedFile) {
      return;
    }

    // Réinitialiser l'erreur
    this.fileError.set(null);

    // Vérifier le type de fichier
    if (selectedFile.type !== 'application/pdf') {
      this.fileError.set('Le fichier doit être au format PDF');
      this.file.set(null);
      target.value = ''; // Réinitialiser l'input
      return;
    }

    // Vérifier la taille du fichier
    if (selectedFile.size > this.MAX_FILE_SIZE) {
      this.fileError.set(
        `Le fichier est trop volumineux (${this.formatFileSize(selectedFile.size)}). Taille maximale autorisée : 5 Mo`
      );
      this.file.set(null);
      target.value = ''; // Réinitialiser l'input
      return;
    }

    this.file.set(selectedFile);
  }

  removeFile(): void {
    this.resetFile();
  }

  resetFile(): void {
    this.file.set(null);
    this.imagePreviewUrl.set(null);
    this.fileError.set(null);
  }

  private readFile(file: File): void {
    const reader = new FileReader();
    reader.onload = (e) => {
      this.imagePreviewUrl.set(e.target?.result as string);
    };
    reader.onerror = () => {
      this.fileError.set('Erreur lors de la lecture du fichier');
      this.resetFile();
    };
    reader.readAsDataURL(file);
  }
}
