import { Component, inject, NgZone, TemplateRef, viewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { GoogleMap } from '@angular/google-maps';

import { ModalDismissReasons, NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { TranslatePipe } from '@ngx-translate/core';
import { Store } from '@ngxs/store';
import { Observable } from 'rxjs';

import { ClearZoneAction, GetZoneAction, SaveLocationAction } from '../../../../action/zone.action';
import { LocationService } from '../../../../services/location.service';
import { ZoneState } from '../../../../state/zone.state';
import { Button } from '../../button/button';

@Component({
  selector: 'app-location-modal',
  imports: [Button, TranslatePipe, FormsModule, GoogleMap],
  templateUrl: './location-modal.html',
  styleUrl: './location-modal.scss',
})
export class LocationModal {
  private modalService = inject(NgbModal);
  private store = inject(Store);
  private ngZone = inject(NgZone);
  public locationService = inject(LocationService);

  readonly locationModal = viewChild<TemplateRef<unknown>>('locationModal');
  location$: Observable<string> = inject(Store).select(ZoneState.location) as Observable<string>;

  public closeResult: string;
  public modalOpen: boolean = false;
  public term: string;
  public suggestions: any[] = [];
  public selectedPlaceId: string | null = null;
  public cityName: string | null = null;
  public openSuggestions: boolean = false;
  public show: boolean = true;
  public selectedIndex: number = -1;
  public location: string;

  ngOnInit() {
    this.location$.subscribe(res => (this.location = res));
    this.locationService.term = this.store.selectSnapshot(state => state.zone.location);
  }

  async openModal() {
    this.modalOpen = true;
    this.modalService
      .open(this.locationModal(), {
        ariaLabelledBy: 'Location-Modal',
        centered: true,
        windowClass: 'theme-modal location-modal',
      })
      .result.then(
        result => {
          `Result ${result}`;
        },
        reason => {
          this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
        },
      );
  }

  private getDismissReason(reason: ModalDismissReasons): string {
    if (reason === ModalDismissReasons.ESC) {
      return 'by pressing ESC';
    } else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
      return 'by clicking on a backdrop';
    } else {
      return `with: ${reason}`;
    }
  }

  onCityInput(target: any): void {
    this.locationService.term = target.value; // Update the input value
    if (this.locationService.term.length > 0) {
      this.openSuggestions = true;
      this.getSuggestions(this.locationService.term);
    } else {
      this.suggestions = []; // Clear suggestions if input is empty
    }
  }

  getSuggestions(query: string): void {
    this.locationService
      .loadGoogleMapApi()
      .then(() => {
        const service = new google.maps.places.AutocompleteService();
        const request = {
          input: query,
          types: ['geocode'], // Includes all types of geographic data
        };

        void service.getPlacePredictions(request, (predictions, status) => {
          if (status === google.maps.places.PlacesServiceStatus.OK) {
            // Directly use the predictions without filtering by term or value
            this.suggestions = predictions || [];
          } else {
            console.error('Error fetching suggestions:', status);
            this.suggestions = [];
          }
        });
      })
      .catch(() => {
        alert('Failed to load Google Maps API. Please check your API key.');
      });
  }

  selectCity(city: google.maps.places.AutocompletePrediction): void {
    const placeId = city.place_id;
    const service = new google.maps.places.PlacesService(document.createElement('div'));

    service.getDetails({ placeId }, (place, status) => {
      if (status === google.maps.places.PlacesServiceStatus.OK && place) {
        this.selectedPlaceId = placeId;
        this.cityName = city.description.split(',')[0];

        if (place.geometry?.location) {
          this.ngZone.run(() => {
            this.locationService.term = String(place.formatted_address);
            this.store.dispatch(new SaveLocationAction(String(place.formatted_address)));
          });
          const lat = place.geometry.location.lat();
          const lng = place.geometry.location.lng();
          this.store.dispatch(new GetZoneAction({ lat: lat, lng: lng }));
          this.modalService.dismissAll();
        }
      } else {
        console.error('Failed to get place details:', status);
      }
    });

    // Clear suggestions
    this.suggestions = [];
    this.openSuggestions = false;
  }

  getCurrentLocation(): void {
    this.locationService.getCurrentLocation(true);
  }

  clearZone() {
    this.store.dispatch(new ClearZoneAction());
    this.locationService.term = '';
  }

  closeModal() {
    this.modalService.dismissAll();
  }
}
