import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, lastValueFrom } from 'rxjs';
import { BusinessListing, CommercialPropertyListing } from '../../../../bizmatch-server/src/models/db.model';
import { ListingType, ResponseBusinessListingArray, ResponseCommercialPropertyListingArray } from '../../../../bizmatch-server/src/models/main.model';
import { environment } from '../../environments/environment';
import { getCriteriaByListingCategory, getSortByListingCategory } from '../utils/utils';

@Injectable({
  providedIn: 'root',
})
export class ListingsService {
  private apiBaseUrl = environment.apiBaseUrl;
  constructor(private http: HttpClient) { }

  async getListings(listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty'): Promise<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray> {
    const criteria = getCriteriaByListingCategory(listingsCategory);
    const sortBy = getSortByListingCategory(listingsCategory);
    const body = { ...criteria, sortBy }; // Merge sortBy in Body
    const result = await lastValueFrom(this.http.post<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/find`, body));
    return result;
  }

  getNumberOfListings(listingsCategory: 'business' | 'commercialProperty', crit?: any): Observable<number> {
    const criteria = crit ? crit : getCriteriaByListingCategory(listingsCategory);
    const sortBy = getSortByListingCategory(listingsCategory);
    const body = { ...criteria, sortBy }; // Merge, falls relevant (wenn Backend sortBy für Count braucht; sonst ignorieren)
    return this.http.post<number>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/findTotal`, body);
  }

  getListingById(id: string, listingsCategory?: 'business' | 'commercialProperty'): Observable<ListingType> {
    const result = this.http.get<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`);
    return result;
  }
  getListingsByEmail(email: string, listingsCategory: 'business' | 'commercialProperty'): Promise<ListingType[]> {
    return lastValueFrom(this.http.get<BusinessListing[]>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/user/${email}`));
  }
  getFavoriteListings(listingsCategory: 'business' | 'commercialProperty' | 'user'): Promise<ListingType[]> {
    return lastValueFrom(this.http.post<BusinessListing[] | CommercialPropertyListing[] | any[]>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/favorites/all`, {}));
  }
  async save(listing: any, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty') {
    if (listing.id) {
      return await lastValueFrom(this.http.put<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}`, listing));
    } else {
      return await lastValueFrom(this.http.post<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}`, listing));
    }
  }
  async deleteBusinessListing(id: string) {
    await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/business/listing/${id}`));
  }
  async deleteCommercialPropertyListing(id: string, imagePath: string) {
    await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/commercialProperty/listing/${id}/${imagePath}`));
  }
  async addToFavorites(id: string, listingsCategory?: 'business' | 'commercialProperty' | 'user') {
    const url = `${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/favorite/${id}`;
    console.log('[ListingsService] addToFavorites calling URL:', url);
    await lastValueFrom(this.http.post<void>(url, {}));
  }
  async removeFavorite(id: string, listingsCategory?: 'business' | 'commercialProperty' | 'user') {
    const url = `${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/favorite/${id}`;
    console.log('[ListingsService] removeFavorite calling URL:', url);
    await lastValueFrom(this.http.delete<ListingType>(url));
  }

  /**
   * Get related listings based on current listing
   * Finds listings with same category, same state, and similar price range
   * @param currentListing The current listing to find related items for
   * @param listingsCategory Type of listings (business or commercialProperty)
   * @param limit Maximum number of related listings to return
   * @returns Array of related listings
   */
  async getRelatedListings(currentListing: any, listingsCategory: 'business' | 'commercialProperty', limit: number = 3): Promise<ListingType[]> {
    const criteria: any = {
      types: [currentListing.type], // Same category/type
      state: currentListing.location.state, // Same state
      minPrice: currentListing.price ? Math.floor(currentListing.price * 0.5) : undefined, // 50% lower
      maxPrice: currentListing.price ? Math.ceil(currentListing.price * 1.5) : undefined, // 50% higher
      page: 0,
      resultsPerPage: limit + 1, // Get one extra to filter out current listing
      showDraft: false
    };

    try {
      const response = await lastValueFrom(
        this.http.post<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray>(
          `${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/find`,
          criteria
        )
      );

      // Filter out the current listing and limit results
      const filtered = response.results
        .filter(listing => listing.id !== currentListing.id)
        .slice(0, limit);

      return filtered;
    } catch (error) {
      console.error('Error fetching related listings:', error);
      return [];
    }
  }
}
