import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import type { ListingDetail } from './listings-api';

const MAX_COMPARE = 5;
const MIN_COMPARE = 2;

export interface ComparisonStats {
  priceRange: { min: number; max: number; avg: number };
  areaRange: { min: number; max: number; avg: number };
  pricePerM2Range: { min: number; max: number; avg: number } | null;
}

export interface ComparisonState {
  /** Listing IDs selected for comparison */
  selectedIds: string[];
  /** Cached listing details (loaded when user navigates to compare page) */
  listings: ListingDetail[];
  /** Whether listings data is loading */
  isLoading: boolean;
  /** Error message if fetching failed */
  error: string | null;

  /** Add a listing ID to the comparison set (max 5) */
  addToCompare: (id: string) => boolean;
  /** Remove a listing ID from the comparison set */
  removeFromCompare: (id: string) => void;
  /** Check if a listing ID is already selected */
  isSelected: (id: string) => boolean;
  /** Clear all selections */
  clearAll: () => void;
  /** Whether the compare button should be active */
  canCompare: () => boolean;
  /** Whether more listings can be added */
  canAdd: () => boolean;
  /** Set fetched listings data */
  setListings: (listings: ListingDetail[]) => void;
  /** Set loading state */
  setLoading: (loading: boolean) => void;
  /** Set error state */
  setError: (error: string | null) => void;
}

export function computeComparisonStats(listings: ListingDetail[]): ComparisonStats | null {
  if (listings.length < MIN_COMPARE) return null;

  const prices = listings.map((l) => Number(l.priceVND)).filter(Number.isFinite);
  const areas = listings.map((l) => l.property.areaM2).filter(Number.isFinite);
  const pricesPerM2 = listings
    .map((l) => l.pricePerM2)
    .filter((v): v is number => v != null && Number.isFinite(v));

  if (prices.length === 0 || areas.length === 0) return null;

  return {
    priceRange: {
      min: Math.min(...prices),
      max: Math.max(...prices),
      avg: Math.round(prices.reduce((a, b) => a + b, 0) / prices.length),
    },
    areaRange: {
      min: Math.min(...areas),
      max: Math.max(...areas),
      avg: Math.round((areas.reduce((a, b) => a + b, 0) / areas.length) * 100) / 100,
    },
    pricePerM2Range:
      pricesPerM2.length > 0
        ? {
            min: Math.min(...pricesPerM2),
            max: Math.max(...pricesPerM2),
            avg: Math.round(pricesPerM2.reduce((a, b) => a + b, 0) / pricesPerM2.length),
          }
        : null,
  };
}

export const useComparisonStore = create<ComparisonState>()(
  persist(
    (set, get) => ({
      selectedIds: [],
      listings: [],
      isLoading: false,
      error: null,

      addToCompare: (id: string) => {
        const { selectedIds } = get();
        if (selectedIds.length >= MAX_COMPARE || selectedIds.includes(id)) return false;
        set({ selectedIds: [...selectedIds, id], error: null });
        return true;
      },

      removeFromCompare: (id: string) => {
        set((state) => ({
          selectedIds: state.selectedIds.filter((sid) => sid !== id),
          listings: state.listings.filter((l) => l.id !== id),
        }));
      },

      isSelected: (id: string) => get().selectedIds.includes(id),

      clearAll: () => set({ selectedIds: [], listings: [], error: null }),

      canCompare: () => get().selectedIds.length >= MIN_COMPARE,

      canAdd: () => get().selectedIds.length < MAX_COMPARE,

      setListings: (listings: ListingDetail[]) => set({ listings, isLoading: false, error: null }),

      setLoading: (isLoading: boolean) => set({ isLoading }),

      setError: (error: string | null) => set({ error, isLoading: false }),
    }),
    {
      name: 'goodgo-compare',
      partialize: (state) => ({ selectedIds: state.selectedIds }),
    },
  ),
);

export { MAX_COMPARE, MIN_COMPARE };
