import { CommonModule } from '@angular/common';
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
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 { CommercialPropertyListingCriteria, CountyResult, GeoResult } 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 { 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-commercial',
  standalone: true,
  imports: [CommonModule, FormsModule, NgSelectModule, ValidatedCityComponent, ValidatedPriceComponent],
  templateUrl: './search-modal-commercial.component.html',
  styleUrls: ['./search-modal.component.scss'],
})
export class SearchModalCommercialComponent implements OnInit, OnDestroy {
  @Input() isModal: boolean = true;

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

  // State
  criteria: CommercialPropertyListingCriteria;
  backupCriteria: any;

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

  // Results count
  numberOfResults$: Observable<number>;
  cancelDisable = false;

  constructor(
    public selectOptions: SelectOptionsService,
    public modalService: ModalService,
    private geoService: GeoService,
    private filterStateService: FilterStateService,
    private listingService: ListingsService,
    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 => {
        if (criteria?.criteriaType === 'commercialPropertyListings') {
          this.initializeWithCriteria(criteria);
        }
      });

      this.modalService.modalVisible$.pipe(untilDestroyed(this)).subscribe(val => {
        if (val.visible && val.type === 'commercialPropertyListings') {
          // Reset pagination when modal opens
          if (this.criteria) {
            this.criteria.page = 1;
            this.criteria.start = 0;
          }
        }
      });
    } else {
      // Embedded mode: Subscribe to state changes
      this.subscribeToStateChanges();
    }

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

  private initializeWithCriteria(criteria: CommercialPropertyListingCriteria): void {
    this.criteria = criteria;
    this.backupCriteria = JSON.parse(JSON.stringify(criteria));
    this.setTotalNumberOfResults();
  }

  private subscribeToStateChanges(): void {
    if (!this.isModal) {
      this.filterStateService
        .getState$('commercialPropertyListings')
        .pipe(takeUntil(this.destroy$))
        .subscribe(state => {
          this.criteria = { ...state.criteria };
          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 'types':
        updates.types = [];
        break;
      case 'title':
        updates.title = null;
        break;
      case 'brokerName':
        updates.brokerName = 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 });
  }

  // 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.setTotalNumberOfResults();
    } else {
      // Embedded: Use state service
      this.filterStateService.clearFilters('commercialPropertyListings');
    }
  }

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

  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('commercialPropertyListings', updates);
    }

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

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

  private setTotalNumberOfResults(): void {
    this.numberOfResults$ = this.listingService.getNumberOfListings('commercialProperty', this.criteria);
  }

  private getDefaultCriteria(): CommercialPropertyListingCriteria {
    // Access the private method through a workaround or create it here
    return {
      criteriaType: 'commercialPropertyListings',
      types: [],
      state: null,
      city: null,
      radius: null,
      searchType: 'exact' as const,
      minPrice: null,
      maxPrice: null,
      title: null,
      brokerName: null,
      prompt: null,
      page: 1,
      start: 0,
      length: 12,
    };
  }

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

    return !!(
      this.criteria.state ||
      this.criteria.city ||
      this.criteria.minPrice ||
      this.criteria.maxPrice ||
      this.criteria.types?.length ||
      this.criteria.title ||
      this.criteria.brokerName
    );
  }

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

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