import { AsyncPipe, NgIf } from '@angular/common';
import { Component, Input, OnDestroy, OnInit } 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, switchMap, takeUntil, tap } from 'rxjs';
import { BusinessListingCriteria, CountyResult, GeoResult, KeyValue, KeyValueStyle } from '../../../../../bizmatch-server/src/models/main.model';
import { FilterStateService } from '../../services/filter-state.service';
import { GeoService } from '../../services/geo.service';
import { ListingsService } from '../../services/listings.service';
import { SearchService } from '../../services/search.service';
import { SelectOptionsService } from '../../services/select-options.service';
import { UserService } from '../../services/user.service';
import { SharedModule } from '../../shared/shared/shared.module';
import { ValidatedCityComponent } from '../validated-city/validated-city.component';
import { ValidatedPriceComponent } from '../validated-price/validated-price.component';
import { ModalService } from './modal.service';

@UntilDestroy()
@Component({
  selector: 'app-search-modal',
  standalone: true,
  imports: [SharedModule, AsyncPipe, NgIf, NgSelectModule, ValidatedCityComponent, ValidatedPriceComponent],
  templateUrl: './search-modal.component.html',
  styleUrl: './search-modal.component.scss',
})
export class SearchModalComponent implements OnInit, OnDestroy {
  @Input() isModal: boolean = true;

  private destroy$ = new Subject<void>();
  private searchDebounce$ = new Subject<void>();

  // State
  criteria: BusinessListingCriteria;
  backupCriteria: any;
  currentListingType: 'businessListings' | 'commercialPropertyListings' | 'brokerListings';

  // Geo search
  counties$: Observable<CountyResult[]>;
  countyLoading = false;
  countyInput$ = new Subject<string>();

  // Property type for business listings
  selectedPropertyType: string | null = null;
  propertyTypeOptions = [
    { name: 'Real Estate', value: 'realEstateChecked' },
    { name: 'Leased Location', value: 'leasedLocation' },
    { name: 'Franchise', value: 'franchiseResale' },
  ];

  // Results count
  numberOfResults$: Observable<number>;

  constructor(
    public selectOptions: SelectOptionsService,
    public modalService: ModalService,
    private geoService: GeoService,
    private filterStateService: FilterStateService,
    private listingService: ListingsService,
    private userService: UserService,
    private searchService: SearchService,
  ) {}

  ngOnInit(): void {
    // Load counties
    this.loadCounties();

    if (this.isModal) {
      // Modal mode: Wait for messages from ModalService
      this.modalService.message$.pipe(untilDestroyed(this)).subscribe(criteria => {
        this.initializeWithCriteria(criteria);
      });

      this.modalService.modalVisible$.pipe(untilDestroyed(this)).subscribe(val => {
        if (val.visible) {
          // Reset pagination when modal opens
          if (this.criteria) {
            this.criteria.page = 1;
            this.criteria.start = 0;
          }
        }
      });
    } else {
      // Embedded mode: Determine type from route and subscribe to state
      this.determineListingType();
      this.subscribeToStateChanges();
    }

    // Setup debounced search
    this.searchDebounce$.pipe(debounceTime(400), takeUntil(this.destroy$)).subscribe(() => this.triggerSearch());
  }

  private initializeWithCriteria(criteria: any): void {
    this.criteria = criteria;
    this.currentListingType = criteria?.criteriaType;
    this.backupCriteria = JSON.parse(JSON.stringify(criteria));
    this.updateSelectedPropertyType();
    this.setTotalNumberOfResults();
  }

  private determineListingType(): void {
    const url = window.location.pathname;
    if (url.includes('businessListings')) {
      this.currentListingType = 'businessListings';
    } else if (url.includes('commercialPropertyListings')) {
      this.currentListingType = 'commercialPropertyListings';
    } else if (url.includes('brokerListings')) {
      this.currentListingType = 'brokerListings';
    }
  }

  private subscribeToStateChanges(): void {
    if (!this.isModal && this.currentListingType) {
      this.filterStateService
        .getState$(this.currentListingType)
        .pipe(takeUntil(this.destroy$))
        .subscribe(state => {
          this.criteria = { ...state.criteria };
          this.updateSelectedPropertyType();
          this.setTotalNumberOfResults();
        });
    }
  }

  private loadCounties(): void {
    this.counties$ = concat(
      of([]), // default items
      this.countyInput$.pipe(
        distinctUntilChanged(),
        tap(() => (this.countyLoading = true)),
        switchMap(term =>
          this.geoService.findCountiesStartingWith(term).pipe(
            catchError(() => of([])),
            map(counties => counties.map(county => county.name)),
            tap(() => (this.countyLoading = false)),
          ),
        ),
      ),
    );
  }

  // Filter removal methods
  removeFilter(filterType: string): void {
    const updates: any = {};

    switch (filterType) {
      case 'state':
        updates.state = null;
        updates.city = null;
        updates.radius = null;
        updates.searchType = 'exact';
        break;
      case 'city':
        updates.city = null;
        updates.radius = null;
        updates.searchType = 'exact';
        break;
      case 'price':
        updates.minPrice = null;
        updates.maxPrice = null;
        break;
      case 'revenue':
        updates.minRevenue = null;
        updates.maxRevenue = null;
        break;
      case 'cashflow':
        updates.minCashFlow = null;
        updates.maxCashFlow = null;
        break;
      case 'types':
        updates.types = [];
        break;
      case 'propertyType':
        updates.realEstateChecked = false;
        updates.leasedLocation = false;
        updates.franchiseResale = false;
        this.selectedPropertyType = null;
        break;
      case 'employees':
        updates.minNumberEmployees = null;
        updates.maxNumberEmployees = null;
        break;
      case 'established':
        updates.establishedMin = null;
        break;
      case 'brokerName':
        updates.brokerName = null;
        break;
      case 'title':
        updates.title = null;
        break;
    }

    this.updateCriteria(updates);
  }

  // Category handling
  onCategoryChange(selectedCategories: string[]): void {
    this.updateCriteria({ types: selectedCategories });
  }

  categoryClicked(checked: boolean, value: string): void {
    const types = [...(this.criteria.types || [])];
    if (checked) {
      if (!types.includes(value)) {
        types.push(value);
      }
    } else {
      const index = types.indexOf(value);
      if (index > -1) {
        types.splice(index, 1);
      }
    }
    this.updateCriteria({ types });
  }

  // Property type handling (Business listings only)
  onPropertyTypeChange(value: string): void {
    const updates: any = {
      realEstateChecked: false,
      leasedLocation: false,
      franchiseResale: false,
    };

    if (value) {
      updates[value] = true;
    }

    this.selectedPropertyType = value;
    this.updateCriteria(updates);
  }

  onCheckboxChange(checkbox: string, value: boolean): void {
    const updates: any = {
      realEstateChecked: false,
      leasedLocation: false,
      franchiseResale: false,
    };

    updates[checkbox] = value;
    this.selectedPropertyType = value ? checkbox : null;
    this.updateCriteria(updates);
  }

  // Location handling
  setState(state: string): void {
    const updates: any = { state };
    if (!state) {
      updates.city = null;
      updates.radius = null;
      updates.searchType = 'exact';
    }
    this.updateCriteria(updates);
  }

  setCity(city: any): void {
    const updates: any = {};
    if (city) {
      updates.city = city;
      updates.state = city.state;
      // Automatically set radius to 50 miles and enable radius search
      updates.searchType = 'radius';
      updates.radius = 50;
    } else {
      updates.city = null;
      updates.radius = null;
      updates.searchType = 'exact';
    }
    this.updateCriteria(updates);
  }

  setRadius(radius: number): void {
    this.updateCriteria({ radius });
  }

  onCriteriaChange(): void {
    this.triggerSearch();
  }

  // Debounced search for text inputs
  debouncedSearch(): void {
    this.searchDebounce$.next();
  }

  // Clear all filters
  clearFilter(): void {
    if (this.isModal) {
      // In modal: Reset locally
      const defaultCriteria = this.getDefaultCriteria();
      this.criteria = defaultCriteria;
      this.updateSelectedPropertyType();
      this.setTotalNumberOfResults();
    } else {
      // Embedded: Use state service
      this.filterStateService.clearFilters(this.currentListingType);
    }
  }

  // Modal-specific methods
  closeAndSearch(): void {
    if (this.isModal) {
      // Save changes to state
      this.filterStateService.setCriteria(this.currentListingType, this.criteria);
      this.modalService.accept();
      this.searchService.search(this.currentListingType);
    }
  }

  close(): void {
    if (this.isModal) {
      // Discard changes
      this.modalService.reject(this.backupCriteria);
    }
  }

  // Helper methods
  public updateCriteria(updates: any): void {
    if (this.isModal) {
      // In modal: Update locally only
      this.criteria = { ...this.criteria, ...updates };
      this.setTotalNumberOfResults();
    } else {
      // Embedded: Update through state service
      this.filterStateService.updateCriteria(this.currentListingType, updates);
    }

    // Trigger search after update
    this.debouncedSearch();
  }

  private triggerSearch(): void {
    if (this.isModal) {
      // In modal: Only update count
      this.setTotalNumberOfResults();
    } else {
      // Embedded: Full search
      this.searchService.search(this.currentListingType);
    }
  }

  private updateSelectedPropertyType(): void {
    if (this.currentListingType === 'businessListings') {
      const businessCriteria = this.criteria as BusinessListingCriteria;
      if (businessCriteria.realEstateChecked) {
        this.selectedPropertyType = 'realEstateChecked';
      } else if (businessCriteria.leasedLocation) {
        this.selectedPropertyType = 'leasedLocation';
      } else if (businessCriteria.franchiseResale) {
        this.selectedPropertyType = 'franchiseResale';
      } else {
        this.selectedPropertyType = null;
      }
    }
  }

  private setTotalNumberOfResults(): void {
    if (!this.criteria) return;

    switch (this.currentListingType) {
      case 'businessListings':
        this.numberOfResults$ = this.listingService.getNumberOfListings('business', this.criteria);
        break;
      case 'commercialPropertyListings':
        this.numberOfResults$ = this.listingService.getNumberOfListings('commercialProperty', this.criteria);
        break;
      case 'brokerListings':
        this.numberOfResults$ = this.userService.getNumberOfBroker();
        break;
    }
  }

  private getDefaultCriteria(): any {
    switch (this.currentListingType) {
      case 'businessListings':
        return this.filterStateService['createEmptyBusinessListingCriteria']();
      case 'commercialPropertyListings':
        return this.filterStateService['createEmptyCommercialPropertyListingCriteria']();
      case 'brokerListings':
        return this.filterStateService['createEmptyUserListingCriteria']();
    }
  }

  hasActiveFilters(): boolean {
    if (!this.criteria) return false;

    // Check all possible filter properties
    const hasBasicFilters = !!(this.criteria.state || this.criteria.city || this.criteria.types?.length);

    // Check business-specific filters
    if (this.currentListingType === 'businessListings') {
      const bc = this.criteria as BusinessListingCriteria;
      return (
        hasBasicFilters ||
        !!(
          bc.minPrice ||
          bc.maxPrice ||
          bc.minRevenue ||
          bc.maxRevenue ||
          bc.minCashFlow ||
          bc.maxCashFlow ||
          bc.minNumberEmployees ||
          bc.maxNumberEmployees ||
          bc.establishedMin ||
          bc.brokerName ||
          bc.title ||
          this.selectedPropertyType
        )
      );
    }

    // Check commercial property filters
    // if (this.currentListingType === 'commercialPropertyListings') {
    //   const cc = this.criteria as CommercialPropertyListingCriteria;
    //   return hasBasicFilters || !!(cc.minPrice || cc.maxPrice || cc.title);
    // }

    // Check user/broker filters
    // if (this.currentListingType === 'brokerListings') {
    //   const uc = this.criteria as UserListingCriteria;
    //   return hasBasicFilters || !!(uc.brokerName || uc.companyName || uc.counties?.length);
    // }

    return hasBasicFilters;
  }

  getSelectedPropertyTypeName(): string | null {
    return this.selectedPropertyType ? this.propertyTypeOptions.find(opt => opt.value === this.selectedPropertyType)?.name || null : null;
  }

  isTypeOfBusinessClicked(v: KeyValueStyle): boolean {
    return !!this.criteria.types?.find(t => t === v.value);
  }

  isTypeOfProfessionalClicked(v: KeyValue): boolean {
    return !!this.criteria.types?.find(t => t === v.value);
  }

  trackByFn(item: GeoResult): any {
    return item.id;
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }
}
