import { isPlatformBrowser } from '@angular/common';
import { inject, Injectable, PLATFORM_ID } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { SortByOptions } from '../../../../bizmatch-server/src/models/db.model';
import { BusinessListingCriteria, CommercialPropertyListingCriteria, UserListingCriteria } from '../../../../bizmatch-server/src/models/main.model';

type CriteriaType = BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria;
type ListingType = 'businessListings' | 'commercialPropertyListings' | 'brokerListings';

interface FilterState {
  businessListings: {
    criteria: BusinessListingCriteria;
    sortBy: SortByOptions | null;
  };
  commercialPropertyListings: {
    criteria: CommercialPropertyListingCriteria;
    sortBy: SortByOptions | null;
  };
  brokerListings: {
    criteria: UserListingCriteria;
    sortBy: SortByOptions | null;
  };
}

@Injectable({
  providedIn: 'root',
})
export class FilterStateService {
  private state: FilterState;
  private stateSubjects: Map<ListingType, BehaviorSubject<any>> = new Map();
  private platformId = inject(PLATFORM_ID);
  private isBrowser = isPlatformBrowser(this.platformId);

  constructor() {
    // Initialize state from sessionStorage or with defaults
    this.state = this.loadStateFromStorage();

    // Create BehaviorSubjects for each listing type
    this.stateSubjects.set('businessListings', new BehaviorSubject(this.state.businessListings));
    this.stateSubjects.set('commercialPropertyListings', new BehaviorSubject(this.state.commercialPropertyListings));
    this.stateSubjects.set('brokerListings', new BehaviorSubject(this.state.brokerListings));
  }

  // Get observable for specific listing type
  getState$(type: ListingType): Observable<any> {
    return this.stateSubjects.get(type)!.asObservable();
  }

  // Get current criteria
  getCriteria(type: ListingType): CriteriaType {
    return { ...this.state[type].criteria };
  }

  // Update criteria
  updateCriteria(type: ListingType, criteria: Partial<CriteriaType>): void {
    // Type-safe update basierend auf dem Listing-Typ
    if (type === 'businessListings') {
      this.state.businessListings.criteria = {
        ...this.state.businessListings.criteria,
        ...criteria,
      } as BusinessListingCriteria;
    } else if (type === 'commercialPropertyListings') {
      this.state.commercialPropertyListings.criteria = {
        ...this.state.commercialPropertyListings.criteria,
        ...criteria,
      } as CommercialPropertyListingCriteria;
    } else if (type === 'brokerListings') {
      this.state.brokerListings.criteria = {
        ...this.state.brokerListings.criteria,
        ...criteria,
      } as UserListingCriteria;
    }

    this.saveToStorage(type);
    this.emitState(type);
  }

  // Set complete criteria (for reset operations)
  setCriteria(type: ListingType, criteria: CriteriaType): void {
    if (type === 'businessListings') {
      this.state.businessListings.criteria = criteria as BusinessListingCriteria;
    } else if (type === 'commercialPropertyListings') {
      this.state.commercialPropertyListings.criteria = criteria as CommercialPropertyListingCriteria;
    } else if (type === 'brokerListings') {
      this.state.brokerListings.criteria = criteria as UserListingCriteria;
    }

    this.saveToStorage(type);
    this.emitState(type);
  }

  // Get current sortBy
  getSortBy(type: ListingType): SortByOptions | null {
    return this.state[type].sortBy;
  }

  // Update sortBy
  updateSortBy(type: ListingType, sortBy: SortByOptions | null): void {
    this.state[type].sortBy = sortBy;
    this.saveSortByToStorage(type, sortBy);
    this.emitState(type);
  }

  // Reset criteria to defaults
  resetCriteria(type: ListingType): void {
    if (type === 'businessListings') {
      this.state.businessListings.criteria = this.createEmptyBusinessListingCriteria();
    } else if (type === 'commercialPropertyListings') {
      this.state.commercialPropertyListings.criteria = this.createEmptyCommercialPropertyListingCriteria();
    } else if (type === 'brokerListings') {
      this.state.brokerListings.criteria = this.createEmptyUserListingCriteria();
    }

    this.saveToStorage(type);
    this.emitState(type);
  }

  // Clear all filters but keep sortBy
  clearFilters(type: ListingType): void {
    const sortBy = this.state[type].sortBy;
    this.resetCriteria(type);
    this.state[type].sortBy = sortBy;
    this.emitState(type);
  }

  private emitState(type: ListingType): void {
    this.stateSubjects.get(type)?.next({ ...this.state[type] });
  }

  private saveToStorage(type: ListingType): void {
    if (!this.isBrowser) return;
    sessionStorage.setItem(type, JSON.stringify(this.state[type].criteria));
  }

  private saveSortByToStorage(type: ListingType, sortBy: SortByOptions | null): void {
    if (!this.isBrowser) return;
    const sortByKey = type === 'businessListings' ? 'businessSortBy' : type === 'commercialPropertyListings' ? 'commercialSortBy' : 'professionalsSortBy';

    if (sortBy) {
      sessionStorage.setItem(sortByKey, sortBy);
    } else {
      sessionStorage.removeItem(sortByKey);
    }
  }

  private loadStateFromStorage(): FilterState {
    return {
      businessListings: {
        criteria: this.loadCriteriaFromStorage('businessListings') as BusinessListingCriteria,
        sortBy: this.loadSortByFromStorage('businessSortBy'),
      },
      commercialPropertyListings: {
        criteria: this.loadCriteriaFromStorage('commercialPropertyListings') as CommercialPropertyListingCriteria,
        sortBy: this.loadSortByFromStorage('commercialSortBy'),
      },
      brokerListings: {
        criteria: this.loadCriteriaFromStorage('brokerListings') as UserListingCriteria,
        sortBy: this.loadSortByFromStorage('professionalsSortBy'),
      },
    };
  }

  private loadCriteriaFromStorage(key: ListingType): CriteriaType {
    if (this.isBrowser) {
      const stored = sessionStorage.getItem(key);
      if (stored) {
        return JSON.parse(stored);
      }
    }

    switch (key) {
      case 'businessListings':
        return this.createEmptyBusinessListingCriteria();
      case 'commercialPropertyListings':
        return this.createEmptyCommercialPropertyListingCriteria();
      case 'brokerListings':
        return this.createEmptyUserListingCriteria();
    }
  }

  private loadSortByFromStorage(key: string): SortByOptions | null {
    if (!this.isBrowser) return null;
    const stored = sessionStorage.getItem(key);
    return stored && stored !== 'null' ? (stored as SortByOptions) : null;
  }

  // Helper methods to create empty criteria
  private createEmptyBusinessListingCriteria(): BusinessListingCriteria {
    return {
      criteriaType: 'businessListings',
      types: [],
      state: null,
      city: null,
      radius: null,
      searchType: 'exact' as const,
      minPrice: null,
      maxPrice: null,
      minRevenue: null,
      maxRevenue: null,
      minCashFlow: null,
      maxCashFlow: null,
      minNumberEmployees: null,
      maxNumberEmployees: null,
      establishedMin: null,
      brokerName: null,
      title: null,
      realEstateChecked: false,
      leasedLocation: false,
      franchiseResale: false,
      email: null,
      prompt: null,
      page: 1,
      start: 0,
      length: 12,
    };
  }

  private createEmptyCommercialPropertyListingCriteria(): CommercialPropertyListingCriteria {
    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,
    };
  }

  private createEmptyUserListingCriteria(): UserListingCriteria {
    return {
      criteriaType: 'brokerListings',
      types: [],
      state: null,
      city: null,
      radius: null,
      searchType: 'exact' as const,
      brokerName: null,
      companyName: null,
      counties: [],
      prompt: null,
      page: 1,
      start: 0,
      length: 12,
    };
  }
}
