import { AsyncPipe, NgIf } from '@angular/common';
import { Component } from '@angular/core';
import { NgSelectModule } from '@ng-select/ng-select';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { catchError, concat, debounceTime, distinctUntilChanged, map, Observable, of, Subject, Subscription, switchMap, tap } from 'rxjs';
import { BusinessListingCriteria, CommercialPropertyListingCriteria, CountyResult, GeoResult, KeyValue, KeyValueStyle, UserListingCriteria } from '../../../../../bizmatch-server/src/models/main.model';
import { CriteriaChangeService } from '../../services/criteria-change.service';
import { GeoService } from '../../services/geo.service';
import { ListingsService } from '../../services/listings.service';
import { SelectOptionsService } from '../../services/select-options.service';
import { UserService } from '../../services/user.service';
import { SharedModule } from '../../shared/shared/shared.module';
import { ModalService } from './modal.service';
@UntilDestroy()
@Component({
  selector: 'app-search-modal',
  standalone: true,
  imports: [SharedModule, AsyncPipe, NgIf, NgSelectModule],
  templateUrl: './search-modal.component.html',
  styleUrl: './search-modal.component.scss',
})
export class SearchModalComponent {
  cities$: Observable<GeoResult[]>;
  counties$: Observable<CountyResult[]>;
  cityLoading = false;
  countyLoading = false;
  cityInput$ = new Subject<string>();
  countyInput$ = new Subject<string>();
  private criteriaChangeSubscription: Subscription;
  public criteria: BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria;
  numberOfResults$: Observable<number>;
  constructor(
    public selectOptions: SelectOptionsService,
    public modalService: ModalService,
    private geoService: GeoService,
    private criteriaChangeService: CriteriaChangeService,
    private listingService: ListingsService,
    private userService: UserService,
  ) {}
  ngOnInit() {
    this.setupCriteriaChangeListener();
    this.modalService.message$.pipe(untilDestroyed(this)).subscribe(msg => {
      this.criteria = msg;
      this.setTotalNumberOfResults();
    });
    this.modalService.modalVisible$.pipe(untilDestroyed(this)).subscribe(val => {
      if (val) {
        this.criteria.page = 1;
        this.criteria.start = 0;
      }
    });
    this.loadCities();
    this.loadCounties();
  }

  ngOnChanges() {}
  categoryClicked(checked: boolean, value: string) {
    if (checked) {
      this.criteria.types.push(value);
    } else {
      const index = this.criteria.types.findIndex(t => t === value);
      if (index > -1) {
        this.criteria.types.splice(index, 1);
      }
    }
  }
  private loadCities() {
    this.cities$ = concat(
      of([]), // default items
      this.cityInput$.pipe(
        distinctUntilChanged(),
        tap(() => (this.cityLoading = true)),
        switchMap(term =>
          this.geoService.findCitiesStartingWith(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.cityLoading = false)),
          ),
        ),
      ),
    );
  }
  private loadCounties() {
    this.counties$ = concat(
      of([]), // default items
      this.countyInput$.pipe(
        distinctUntilChanged(),
        tap(() => (this.countyLoading = true)),
        switchMap(term =>
          this.geoService.findCountiesStartingWith(term).pipe(
            catchError(() => of([])), // empty list on error
            map(counties => counties.map(county => county.name)), // transform the list of objects to a list of city names
            tap(() => (this.countyLoading = false)),
          ),
        ),
      ),
    );
  }
  setCity(city) {
    if (city) {
      this.criteria.city = city.city;
      this.criteria.state = city.state;
    } else {
      this.criteria.city = null;
      this.criteria.radius = null;
      this.criteria.searchType = 'exact';
    }
  }
  setState(state: string) {
    if (state) {
      this.criteria.state = state;
    } else {
      this.criteria.state = null;
      this.setCity(null);
    }
  }
  private setupCriteriaChangeListener() {
    this.criteriaChangeSubscription = this.criteriaChangeService.criteriaChange$.pipe(debounceTime(400)).subscribe(() => this.setTotalNumberOfResults());
  }
  trackByFn(item: GeoResult) {
    return item.id;
  }
  search() {
    console.log('Search criteria:', this.criteria);
  }
  getCounties() {
    this.geoService.findCountiesStartingWith('');
  }
  closeModal() {
    console.log('Closing modal');
  }
  isTypeOfBusinessClicked(v: KeyValueStyle) {
    return this.criteria.types.find(t => t === v.value);
  }
  isTypeOfProfessionalClicked(v: KeyValue) {
    return this.criteria.types.find(t => t === v.value);
  }
  setTotalNumberOfResults() {
    if (this.criteria) {
      console.log(`Getting total number of results for ${this.criteria.criteriaType}`);
      if (this.criteria.criteriaType === 'businessListings' || this.criteria.criteriaType === 'commercialPropertyListings') {
        this.numberOfResults$ = this.listingService.getNumberOfListings(this.criteria, this.criteria.criteriaType === 'businessListings' ? 'business' : 'commercialProperty');
      } else if (this.criteria.criteriaType === 'brokerListings') {
        this.numberOfResults$ = this.userService.getNumberOfBroker(this.criteria);
      } else {
        this.numberOfResults$ = of();
      }
    }
  }
}
