import { CommonModule } from '@angular/common';
import { Component, forwardRef, Input } from '@angular/core';
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';
import { catchError, concat, debounceTime, distinctUntilChanged, Observable, of, Subject, switchMap, tap } from 'rxjs';
import { GeoResult } from '../../../../../bizmatch-server/src/models/main.model';
import { Place } from '../../../../../bizmatch-server/src/models/server.model';
import { GeoService } from '../../services/geo.service';
import { SelectOptionsService } from '../../services/select-options.service';
import { BaseInputComponent } from '../base-input/base-input.component';
import { TooltipComponent } from '../tooltip/tooltip.component';
import { ValidationMessagesService } from '../validation-messages.service';

@Component({
  selector: 'app-validated-location',
  standalone: true,
  imports: [CommonModule, FormsModule, NgSelectModule, TooltipComponent],
  templateUrl: './validated-location.component.html',
  styleUrl: './validated-location.component.scss',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => ValidatedLocationComponent),
      multi: true,
    },
  ],
})
export class ValidatedLocationComponent extends BaseInputComponent {
  @Input() items;
  @Input() labelClasses: string;
  places$: Observable<Place[]>;
  placeInput$ = new Subject<string>();
  placeLoading = false;
  constructor(validationMessagesService: ValidationMessagesService, private geoService: GeoService, public selectOptions: SelectOptionsService) {
    super(validationMessagesService);
  }

  override ngOnInit() {
    super.ngOnInit();
    this.loadCities();
  }
  onInputChange(event: Place): void {
    this.value = event; //{ ...event, longitude: parseFloat(event.longitude), latitude: parseFloat(event.latitude) };
    if (event) {
      this.value = {
        id: event?.place_id,
        name: event?.address.city,
        county: event?.address.county,
        street: event?.address.road,
        housenumber: event?.address.house_number,
        state: event?.address['ISO3166-2-lvl4'].substr(3),
        latitude: event ? parseFloat(event?.lat) : undefined,
        longitude: event ? parseFloat(event?.lon) : undefined,
      };
    }
    this.onChange(this.value);
  }
  private loadCities() {
    this.places$ = concat(
      of([]), // default items
      this.placeInput$.pipe(
        debounceTime(300),
        distinctUntilChanged(),
        tap(() => (this.placeLoading = true)),
        switchMap(term =>
          this.geoService.findLocationStartingWith(term).pipe(
            catchError(() => of([])), // empty list on error
            // map(cities => cities.map(city => city.city)), // transform the list of objects to a list of city names
            tap(() => (this.placeLoading = false)),
          ),
        ),
      ),
    );
  }
  trackByFn(item: GeoResult) {
    return item.id;
  }
  compareFn = (item, selected) => {
    return item.id === selected.id;
  };
  formatGeoAddress(geoResult: GeoResult | null | undefined): string {
    // Überprüfen, ob geoResult null oder undefined ist
    if (!geoResult) {
      return '';
    }

    let addressParts: string[] = [];

    // Füge Hausnummer hinzu, wenn vorhanden
    if (geoResult.housenumber) {
      addressParts.push(geoResult.housenumber);
    }

    // Füge Straße hinzu, wenn vorhanden
    if (geoResult.street) {
      addressParts.push(geoResult.street);
    }

    // Kombiniere Hausnummer und Straße
    let address = addressParts.join(' ');

    // Füge Namen hinzu, wenn vorhanden
    if (geoResult.name) {
      address = address ? `${address}, ${geoResult.name}` : geoResult.name;
    }

    // Füge County hinzu, wenn vorhanden
    if (geoResult.county) {
      address = address ? `${address}, ${geoResult.county}` : geoResult.county;
    }

    // Füge Bundesland hinzu, wenn vorhanden
    if (geoResult.state) {
      address = address ? `${address} - ${geoResult.state}` : geoResult.state;
    }

    return address;
  }
  formatPlaceAddress(place: Place | null | undefined): string {
    // Überprüfen, ob place null oder undefined ist
    if (!place) {
      return '';
    }

    const { house_number, road, city, county, state } = place.address;

    let addressParts: string[] = [];

    // Füge Hausnummer hinzu, wenn vorhanden
    if (house_number) {
      addressParts.push(house_number);
    }

    // Füge Straße hinzu, wenn vorhanden
    if (road) {
      addressParts.push(road);
    }

    // Kombiniere Hausnummer und Straße
    let address = addressParts.join(' ');

    // Füge Stadt hinzu, wenn vorhanden
    if (city) {
      address = address ? `${address}, ${city}` : city;
    }

    // Füge County hinzu, wenn vorhanden
    if (county) {
      address = address ? `${address}, ${county}` : county;
    }

    // Füge Bundesland hinzu, wenn vorhanden
    if (state) {
      address = address ? `${address} - ${state}` : state;
    }

    return address;
  }
}
