import { CommonModule } from '@angular/common';
import {
  AfterViewInit,
  Component,
  Input,
  OnDestroy,
  OnInit,
} from '@angular/core';
import {
  FormBuilder,
  FormControl,
  FormGroup,
  ReactiveFormsModule,
} from '@angular/forms';
import { NavigationEnd, Router } from '@angular/router';
import { of, Subscription } from 'rxjs';
import {
  catchError,
  debounceTime,
  distinctUntilChanged,
  filter,
  switchMap,
  take,
} from 'rxjs/operators';
import { Pin } from '../../model/Pin';
import { AutocompleteService } from '../../services/auto-complete/auto-complete.service';
import { ExifService } from '../../services/exif/exif.service';
import { MapReloadService } from '../../services/map-reload/map-reload.service';
import { ModalService } from '../../services/modal/modal.service';
import { PinService } from '../../services/pin/pin.service';
import { DragDropComponent } from '../drag-drop/drag-drop.component';

@Component({
  selector: 'app-edit-pin-popup',
  standalone: true,
  imports: [ReactiveFormsModule, CommonModule, DragDropComponent],
  templateUrl: './edit-pin-popup.component.html',
})
export class EditPinPopupComponent implements OnInit, AfterViewInit, OnDestroy {
  @Input() isHomePage: boolean = false;
  @Input() pin!: Pin;

  form!: FormGroup;
  suggestions: any[] = [];
  inputFocused: boolean = false;
  files: any[] = [];
  isPinModalOpen: boolean = false;
  @Input() modalId!: string;

  private modalOpenSubscription!: Subscription;
  private routerSubscription!: Subscription;
  private locationSubscription!: Subscription;

  constructor(
    private fb: FormBuilder,
    private autocompleteService: AutocompleteService,
    private pinService: PinService,
    private exifService: ExifService,
    private modalService: ModalService,
    private router: Router,
    private mapReloadService: MapReloadService
  ) {
    // Initialiser le formulaire avec des valeurs par défaut
    this.form = this.fb.group({
      title: new FormControl(''),
      description: new FormControl(''),
      location: new FormControl(''),
      files: new FormControl(null),
    });
  }

  onFocus(): void {
    this.inputFocused = true;
  }

  onBlur(): void {
    setTimeout(() => {
      this.inputFocused = false; // Désactiver le focus après un petit délai pour permettre un clic sur la liste
    }, 200);
  }

  ngOnInit(): void {
    // Initialiser le formulaire avec les valeurs de base
    this.form.patchValue({
      title: this.pin?.title || '',
      description: this.pin?.description || '',
      location: "Chargement de l'adresse...",
    });

    // Vérifier si nous avons des coordonnées valides dans pin.location
    if (
      this.pin?.location &&
      Array.isArray(this.pin.location) &&
      this.pin.location.length >= 2
    ) {
      const lat = this.pin.location[0];
      const lon = this.pin.location[1];

      if (lat !== undefined && lon !== undefined) {
        // Récupérer l'adresse à partir des coordonnées
        this.locationSubscription = this.autocompleteService
          .getAddressFromCoordinates(lat, lon)
          .pipe(take(1))
          .subscribe(
            (address) => {
              if (address && address.display_name) {
                this.form.patchValue({ location: address.display_name });
              } else {
                this.form.patchValue({ location: `${lat}, ${lon}` });
              }
            },
            (error) => {
              console.error(
                "Erreur lors de la récupération de l'adresse:",
                error
              );
              this.form.patchValue({ location: `${lat}, ${lon}` });
            }
          );
      }
    }

    // S'abonner aux changements d'état du modal
    this.modalOpenSubscription = this.modalService
      .getModalState(this.modalId)
      .subscribe((state) => {
        this.isPinModalOpen = state;
        if (state) {
          setTimeout(() => this.moveModalToBody(), 0);
        }
      });

    // S'abonner aux événements de navigation du router
    this.routerSubscription = this.router.events
      .pipe(filter((event) => event instanceof NavigationEnd))
      .subscribe(() => {
        // Attendre que le DOM soit mis à jour après la navigation
        setTimeout(() => this.moveModalToBody(), 0);
      });

    // Configuration de l'autocomplétion pour le champ d'adresse
    this.form
      .get('location')
      ?.valueChanges.pipe(
        debounceTime(300), // Attendre 300ms après la dernière frappe
        distinctUntilChanged(), // Ignorer si la nouvelle valeur est la même que la précédente
        switchMap((query) => {
          // Vérifier que query est une chaîne de caractères
          if (typeof query !== 'string') {
            return of([]);
          }

          const trimmedQuery = query.trim();
          if (trimmedQuery.length > 2) {
            return this.autocompleteService.getAddressSuggestions(trimmedQuery);
          }
          return of([]);
        }),
        catchError((error) => {
          console.error('Error fetching suggestions:', error);
          return of([]);
        })
      )
      .subscribe((data) => {
        this.suggestions = data;
      });
  }

  ngAfterViewInit() {
    // Appel initial pour déplacer le modal
    this.moveModalToBody();
  }

  ngOnDestroy() {
    // Nettoyage des abonnements pour éviter les fuites de mémoire
    if (this.modalOpenSubscription) {
      this.modalOpenSubscription.unsubscribe();
    }

    if (this.routerSubscription) {
      this.routerSubscription.unsubscribe();
    }

    if (this.locationSubscription) {
      this.locationSubscription.unsubscribe();
    }
  }

  // Méthode dédiée pour déplacer le modal vers le body
  private moveModalToBody(): void {
    const modal = document.getElementById('pin-modal');
    if (modal && modal.parentElement !== document.body) {
      document.body.appendChild(modal);
    }
    const bg = document.getElementById('pin-modal-background');
    if (bg && bg.parentElement !== document.body) {
      document.body.appendChild(bg);
    }
  }

  selectSuggestion(suggestion: any): void {
    const locationControl = this.form.get('location');
    if (locationControl instanceof FormControl) {
      locationControl.setValue(suggestion.display_name);
    }
    this.suggestions = [];
  }

  async onFilesReceived(files: FileList): Promise<void> {
    this.files = Array.from(files);

    for (let i = 0; i < this.files.length; i++) {
      try {
        const data = await this.exifService.getLocation(this.files[i]);
        if (data.latitude !== undefined && data.longitude !== undefined) {
          try {
            // Utiliser pipe(take(1)) pour s'assurer que l'observable se termine
            const address = await this.autocompleteService
              .getAddressFromCoordinates(data.latitude, data.longitude)
              .pipe(take(1))
              .toPromise();

            if (address) {
              this.form.get('location')?.setValue(address.display_name);
              break;
            }
          } catch (addressError) {
            console.error(
              "Erreur lors de la récupération de l'adresse:",
              addressError
            );
            // Utiliser les coordonnées brutes en cas d'échec
            this.form
              .get('location')
              ?.setValue(`${data.latitude}, ${data.longitude}`);
          }
        }
      } catch (error) {
        console.error('Erreur :', error);
      }
    }
  }

  submitForm(): void {
    if (this.form.valid) {
      this.files = this.files.map((file) => {
        return file.name; //TODO: Mettre le hash du fichier
      });

      const pinData = {
        ...this.form.value,
        files: this.files,
        user_id: this.pin.user_id,
      };

      this.pinService.updatePin(this.pin.id, pinData).subscribe(() => {
        this.mapReloadService.requestReload(); // Demander le rechargement de la carte
        this.closePinModal();
      });
    } else {
      console.error('Le formulaire est invalide');
    }
  }

  openPinModal() {
    this.modalService.openModal(this.modalId);
  }

  closePinModal() {
    this.modalService.closeModal(this.modalId);
  }
}
