import { useState, useEffect, useCallback, useRef } from 'react';

export type MatchProfile = {
  id: string;
  imaginaryName?: string;
  age?: number;
  gender?: string;
  sexuality?: string;
  bio?: string;
  desires?: string[];
  connectionGoals?: string[];
  interests?: string[];
  isMajestic?: boolean;
  verificationStatus?: string;
  distance?: { km: number; mi: number };
  photos?: Array<{
    id: string;
    pictureUrls?: { small?: string; medium?: string; large?: string };
    pictureType?: string;
  }>;
  interactionStatus?: {
    mine?: string;
    theirs?: string;
    message?: string;
  };
  discoveredAt?: string;
  _score: number;
  _scoreBreakdown: Record<string, number>;
};

export type MatchFilters = {
  search?: string;
  minAge?: number;
  maxAge?: number;
  maxDistance?: number;
  gender?: string;
  verifiedOnly?: boolean;
  theyLikedOnly?: boolean;
  sort?: 'score' | 'distance' | 'recent';
};

export type MatchWeights = {
  [key: string]: number;
};

const FILTERS_KEY = 'feeld_match_filters';

function loadSavedFilters(): MatchFilters {
  try {
    const saved = localStorage.getItem(FILTERS_KEY);
    return saved ? JSON.parse(saved) : {};
  } catch {
    return {};
  }
}

export function useMatches() {
  const [matches, setMatches] = useState<MatchProfile[]>([]);
  const [total, setTotal] = useState(0);
  const [loading, setLoading] = useState(false);
  const [filters, setFiltersState] = useState<MatchFilters>(loadSavedFilters);
  const [weights, setWeights] = useState<MatchWeights | null>(null);
  const [offset, setOffset] = useState(0);
  const searchTimerRef = useRef<number | null>(null);

  const setFilters = useCallback((newFilters: MatchFilters | ((prev: MatchFilters) => MatchFilters)) => {
    setFiltersState(prev => {
      const updated = typeof newFilters === 'function' ? newFilters(prev) : newFilters;
      localStorage.setItem(FILTERS_KEY, JSON.stringify(updated));
      return updated;
    });
    setOffset(0);
    setMatches([]);
  }, []);

  const fetchMatches = useCallback(async (currentOffset = 0, append = false) => {
    setLoading(true);
    try {
      const params = new URLSearchParams();
      if (filters.search) params.set('search', filters.search);
      if (filters.minAge) params.set('minAge', String(filters.minAge));
      if (filters.maxAge) params.set('maxAge', String(filters.maxAge));
      if (filters.maxDistance) params.set('maxDistance', String(filters.maxDistance));
      if (filters.gender) params.set('gender', filters.gender);
      if (filters.verifiedOnly) params.set('verifiedOnly', 'true');
      if (filters.theyLikedOnly) params.set('theyLikedOnly', 'true');
      if (filters.sort && filters.sort !== 'score') params.set('sort', filters.sort);
      params.set('limit', '50');
      params.set('offset', String(currentOffset));

      const res = await fetch(`/api/matches?${params.toString()}`);
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const data = await res.json();

      if (append) {
        setMatches(prev => [...prev, ...data.matches]);
      } else {
        setMatches(data.matches);
      }
      setTotal(data.total);
    } catch (e) {
      console.error('Failed to fetch matches:', e);
    } finally {
      setLoading(false);
    }
  }, [filters]);

  const loadMore = useCallback(() => {
    const newOffset = offset + 50;
    setOffset(newOffset);
    fetchMatches(newOffset, true);
  }, [offset, fetchMatches]);

  const removeMatch = useCallback((profileId: string) => {
    setMatches(prev => prev.filter(m => m.id !== profileId));
    setTotal(prev => Math.max(0, prev - 1));
  }, []);

  // Fetch weights
  const fetchWeights = useCallback(async () => {
    try {
      const res = await fetch('/api/matches/weights');
      if (!res.ok) return;
      const data = await res.json();
      setWeights(data.weights);
    } catch (e) {
      console.error('Failed to fetch weights:', e);
    }
  }, []);

  const updateWeights = useCallback(async (newWeights: MatchWeights) => {
    try {
      const res = await fetch('/api/matches/weights', {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ weights: newWeights }),
      });
      if (!res.ok) return;
      const data = await res.json();
      setWeights(data.weights);
      // Re-fetch matches with new weights
      setOffset(0);
      setMatches([]);
    } catch (e) {
      console.error('Failed to update weights:', e);
    }
  }, []);

  // Debounced fetch on filter change
  useEffect(() => {
    if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
    searchTimerRef.current = window.setTimeout(() => {
      fetchMatches(0, false);
    }, 300);
    return () => {
      if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
    };
  }, [fetchMatches]);

  // Fetch weights on mount
  useEffect(() => {
    fetchWeights();
  }, [fetchWeights]);

  return {
    matches,
    total,
    loading,
    filters,
    setFilters,
    fetchMatches: () => { setOffset(0); setMatches([]); fetchMatches(0, false); },
    loadMore,
    removeMatch,
    weights,
    updateWeights,
    hasMore: matches.length < total,
  };
}
