import { Component, Input, Output, EventEmitter, OnInit, Renderer2, ElementRef } from '@angular/core';
import { FormGroup } from '@angular/forms';

// Interface pour les messages d'erreur i18n
export interface ErrorMessages {
  required?: string;
  email?: string;
  minlength?: string;
  maxlength?: string;
  min?: string;
  max?: string;
  pattern?: string;
  [key: string]: string | undefined;
}

// Interface pour le thème personnalisable
export interface FieldRendererTheme {
  primaryColor?: string;
  accentColor?: string;
  errorColor?: string;
  backgroundColor?: string;
  borderColor?: string;
  borderRadius?: string;
  fontSize?: string;
  fontFamily?: string;
}

@Component({
  selector: 'app-field-renderer',
  templateUrl: './field-renderer.component.html',
  styleUrls: ['./field-renderer.component.scss']
})
export class FieldRendererComponent implements OnInit {
  @Input() field!: any;
  @Input() form!: FormGroup;
  @Input() submitted: boolean = false; // Pour l'affichage des erreurs
  @Input() isEditMultiple: boolean = false; // Pour les modifications multiples

  // i18n pour les messages d'erreur
  @Input() errorMessages?: ErrorMessages;
  @Input() locale: string = 'fr';

  // Thème personnalisable
  @Input() theme?: FieldRendererTheme;

  // Mode read-only global
  @Input() readonly: boolean = false;

  // Outputs pour les événements d'autocomplétion (type reference)
  @Output() autocompleteInput = new EventEmitter<{value: string, module: string}>();
  @Output() autocompleteSelected = new EventEmitter<{event: any, fieldName: string}>();
  @Output() autocompleteFocused = new EventEmitter<{event: any, displayName: string}>();
  @Output() autocompleteCleared = new EventEmitter<void>();

  // Output pour le file upload
  @Output() fileSelected = new EventEmitter<{file: File, fieldName: string}>();

  // Output pour la navigation vers une référence
  @Output() referenceClicked = new EventEmitter<{ module: string, id: string, uuid?: string, label: string }>();

  // Données pour l'autocomplétion (passées par le parent)
  @Input() autocompleteData: any[] = [];
  @Input() isLoadingAutocomplete: boolean = false;
  @Input() displayFn?: (item: any) => string;

  // Configuration pour file upload
  @Input() acceptedFileTypes?: string; // Ex: "image/*,.pdf"
  @Input() maxFileSize?: number; // En bytes (ex: 5MB = 5 * 1024 * 1024)

  constructor(private renderer: Renderer2, private el: ElementRef) {}

  ngOnInit(): void {
    // 🔍 Debug: vérifier si le form est bien transmis
    console.log('🔍 Field-renderer ngOnInit:', {
      fieldName: this.field?.name,
      hasForm: !!this.form,
      formControls: this.form ? Object.keys(this.form.controls) : [],
      controlExists: this.form ? this.form.get(this.field?.name) : null
    });

    this.applyTheme();
  }

  /**
   * Vérifie si le champ a des erreurs et a été touché
   */
  hasError(): boolean {
    const control = this.form.get(this.field?.controlName || this.field?.name);
    return !!control && control.invalid && (control.dirty || control.touched);
  }

  /**
   * Récupère le control du formulaire
   */
  getControl() {
    return this.form.get(this.field?.controlName || this.field?.name);
  }

  /**
   * Vérifie si une erreur spécifique existe
   */
  hasSpecificError(errorType: string): boolean {
    const control = this.getControl();
    return !!control && !!control.errors?.[errorType];
  }

  /**
   * Récupère le nom du control (compatible avec différents formats de field)
   */
  getControlName(): string {
    return this.field?.controlName || this.field?.name;
  }

  /**
   * Vérifie si le champ est requis
   */
  isRequired(): boolean {
    // Support pour harmonized-create-view (validators.required)
    if (this.field?.validators?.required) {
      return true;
    }
    // Support pour projects.component (mandatory)
    if (this.field?.mandatory == 1 && !this.isEditMultiple) {
      return true;
    }
    return false;
  }

  /**
   * Récupère le label du champ
   */
  getLabel(): string {
    return this.field?.placeholder || this.field?.displayName || '';
  }

  /**
   * Récupère la valeur actuelle du champ
   */
  getCurrentValue(): any {
    return this.field?.currentValue || this.field?.value || '';
  }

  /**
   * Gère l'input de l'autocomplétion
   */
  onAutocompleteInput(value: string): void {
    if (this.field?.module) {
      this.autocompleteInput.emit({ value, module: this.field.module });
    }
  }

  /**
   * Gère la sélection d'une option d'autocomplétion
   */
  onAutocompleteSelected(event: any): void {
    console.log('🎯 field-renderer.onAutocompleteSelected:', {
      fieldName: this.getControlName(),
      selectedValue: event.option.value,
      event
    });
    this.autocompleteSelected.emit({ event, fieldName: this.getControlName() });
  }

  /**
   * Gère le focus de l'autocomplétion
   */
  onAutocompleteFocused(event: any): void {
    this.autocompleteFocused.emit({ event, displayName: this.getLabel() });
  }

  /**
   * Gère le clear de l'autocomplétion
   */
  onAutocompleteCleared(): void {
    this.autocompleteCleared.emit();
  }

  /**
   * Fonction d'affichage par défaut pour l'autocomplétion
   */
  defaultDisplayFn(item: any): string {
    return item?.name || '';
  }

  /**
   * Gère la sélection d'un fichier
   */
  onFileSelected(event: Event): void {
    const input = event.target as HTMLInputElement;
    if (input.files && input.files.length > 0) {
      const file = input.files[0];

      // Validation de la taille si configurée
      if (this.maxFileSize && file.size > this.maxFileSize) {
        const maxSizeMB = (this.maxFileSize / (1024 * 1024)).toFixed(2);
        alert(`Le fichier est trop volumineux. Taille maximale: ${maxSizeMB}MB`);
        input.value = ''; // Reset input
        return;
      }

      // Émettre l'événement avec le fichier
      this.fileSelected.emit({ file, fieldName: this.getControlName() });

      // Mettre à jour le FormControl avec le nom du fichier
      const control = this.getControl();
      if (control) {
        control.setValue(file.name);
        control.markAsTouched();
      }
    }
  }

  /**
   * Récupère les types de fichiers acceptés
   */
  getAcceptedTypes(): string {
    return this.field?.acceptedTypes || this.acceptedFileTypes || '*';
  }

  /**
   * Vérifie si un champ checkbox est coché
   */
  isChecked(): boolean {
    const control = this.getControl();
    return !!control?.value;
  }

  /**
   * Vérifie si le champ est en lecture seule
   */
  isReadOnly(): boolean {
    return this.readonly || this.field?.readonly || false;
  }

  /**
   * Récupère la valeur affichée en mode read-only
   */
  getReadOnlyValue(): string {
    const value = this.getCurrentValue();

    // Gestion des différents types
    switch (this.field.controlType || this.field.type) {
      case 'checkbox':
      case 'boolean':
        return value ? 'Oui' : 'Non';

      case 'select':
      case 'picklist':
        const option = this.field?.options?.find((opt: any) => opt.value === value);
        return option?.optionName || option?.value || value || '-';

      case 'multiselect':
        if (Array.isArray(value)) {
          return value.map(v => {
            const opt = this.field?.options?.find((o: any) => o.value === v);
            return opt?.optionName || opt?.value || v;
          }).join(', ');
        }
        return value || '-';

      case 'reference':
        return value?.name || value || '-';

      case 'currency':
        return value ? `${value} €` : '-';

      case 'float':
      case 'double':
        return value !== null && value !== undefined ? value.toString() : '-';

      case 'date':
        return value ? new Date(value).toLocaleDateString() : '-';

      case 'datetime':
        return value ? new Date(value).toLocaleString() : '-';

      case 'file':
        return value || 'Aucun fichier';

      default:
        return value || '-';
    }
  }

  /**
   * Vérifie si le champ est une référence avec un identifiant navigable
   */
  isReferenceWithId(): boolean {
    if ((this.field?.controlType || this.field?.type) !== 'reference') return false;
    if (!this.field?.reference) return false;
    const value = this.getCurrentValue();
    return value && typeof value === 'object' && (value.id || value.uuid);
  }

  /**
   * Émet un événement pour naviguer vers la référence
   */
  onReferenceClick(): void {
    const value = this.getCurrentValue();
    if (!value || typeof value !== 'object') return;

    const id = value.id || value.uuid;
    if (!id || !this.field?.reference) return;

    this.referenceClicked.emit({
      module: this.field.reference,
      id: String(id),
      uuid: value.uuid,
      label: value.name || value.label || String(id)
    });
  }

  /**
   * Messages d'erreur par défaut selon la locale
   */
  private defaultErrorMessages: { [locale: string]: ErrorMessages } = {
    fr: {
      required: 'Ce champ est requis',
      email: 'Email invalide',
      minlength: 'Longueur minimale non respectée',
      maxlength: 'Longueur maximale dépassée',
      min: 'Valeur minimale non respectée',
      max: 'Valeur maximale dépassée',
      pattern: 'Format invalide'
    },
    en: {
      required: 'This field is required',
      email: 'Invalid email',
      minlength: 'Minimum length not met',
      maxlength: 'Maximum length exceeded',
      min: 'Minimum value not met',
      max: 'Maximum value exceeded',
      pattern: 'Invalid format'
    },
    es: {
      required: 'Este campo es obligatorio',
      email: 'Email inválido',
      minlength: 'Longitud mínima no alcanzada',
      maxlength: 'Longitud máxima excedida',
      min: 'Valor mínimo no alcanzado',
      max: 'Valor máximo excedido',
      pattern: 'Formato inválido'
    }
  };

  /**
   * Récupère le message d'erreur internationalisé
   */
  getErrorMessage(): string {
    const control = this.getControl();
    if (!control || !control.errors) {
      return '';
    }

    const errors = control.errors;
    const messages = this.errorMessages || this.defaultErrorMessages[this.locale] || this.defaultErrorMessages['fr'];

    // Ordre de priorité des erreurs
    const errorTypes = ['required', 'email', 'minlength', 'maxlength', 'min', 'max', 'pattern'];

    for (const errorType of errorTypes) {
      if (errors[errorType]) {
        let message = messages[errorType] || this.defaultErrorMessages['fr'][errorType] || '';

        // Remplacer les paramètres dynamiques
        if (errorType === 'minlength' && errors[errorType].requiredLength) {
          message = message.replace('{min}', errors[errorType].requiredLength);
        }
        if (errorType === 'maxlength' && errors[errorType].requiredLength) {
          message = message.replace('{max}', errors[errorType].requiredLength);
        }
        if (errorType === 'min' && errors[errorType].min !== undefined) {
          message = message.replace('{min}', errors[errorType].min);
        }
        if (errorType === 'max' && errors[errorType].max !== undefined) {
          message = message.replace('{max}', errors[errorType].max);
        }

        return message;
      }
    }

    // Erreur personnalisée
    const customErrorKey = Object.keys(errors)[0];
    return messages[customErrorKey] || this.defaultErrorMessages['fr']['pattern'] || '';
  }

  /**
   * Applique le thème personnalisé au composant
   */
  private applyTheme(): void {
    if (!this.theme) {
      return;
    }

    const element = this.el.nativeElement;

    if (this.theme.primaryColor) {
      this.renderer.setStyle(element, '--field-renderer-primary', this.theme.primaryColor);
    }
    if (this.theme.accentColor) {
      this.renderer.setStyle(element, '--field-renderer-accent', this.theme.accentColor);
    }
    if (this.theme.errorColor) {
      this.renderer.setStyle(element, '--field-renderer-error', this.theme.errorColor);
    }
    if (this.theme.backgroundColor) {
      this.renderer.setStyle(element, '--field-renderer-bg', this.theme.backgroundColor);
    }
    if (this.theme.borderColor) {
      this.renderer.setStyle(element, '--field-renderer-border', this.theme.borderColor);
    }
    if (this.theme.borderRadius) {
      this.renderer.setStyle(element, '--field-renderer-radius', this.theme.borderRadius);
    }
    if (this.theme.fontSize) {
      this.renderer.setStyle(element, '--field-renderer-font-size', this.theme.fontSize);
    }
    if (this.theme.fontFamily) {
      this.renderer.setStyle(element, '--field-renderer-font-family', this.theme.fontFamily);
    }
  }

  /**
   * Récupère les styles CSS personnalisés pour le thème
   */
  getThemeStyles(): { [key: string]: string } {
    const styles: { [key: string]: string } = {};

    if (this.theme) {
      if (this.theme.primaryColor) styles['--field-renderer-primary'] = this.theme.primaryColor;
      if (this.theme.accentColor) styles['--field-renderer-accent'] = this.theme.accentColor;
      if (this.theme.errorColor) styles['--field-renderer-error'] = this.theme.errorColor;
      if (this.theme.backgroundColor) styles['--field-renderer-bg'] = this.theme.backgroundColor;
      if (this.theme.borderColor) styles['--field-renderer-border'] = this.theme.borderColor;
      if (this.theme.borderRadius) styles['--field-renderer-radius'] = this.theme.borderRadius;
      if (this.theme.fontSize) styles['--field-renderer-font-size'] = this.theme.fontSize;
      if (this.theme.fontFamily) styles['--field-renderer-font-family'] = this.theme.fontFamily;
    }

    return styles;
  }
}
