import { useEffect, useRef, useState } from 'react';
import type { ActualListing, ActualListingsResponse, Bounds } from '../types';
import { apiUrl, authHeaders, isAbortError, logNonAbortError } from '../lib/api';

const DEBOUNCE_MS = 200;

interface UseActualListingsOptions {
  filterParam?: string;
  travelParam?: string;
  shareCode?: string;
}

export function useActualListings(
  bounds: Bounds | null,
  { filterParam = '', travelParam = '', shareCode = '' }: UseActualListingsOptions = {}
) {
  const [listings, setListings] = useState<ActualListing[]>([]);
  const [loading, setLoading] = useState(false);
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const abortControllerRef = useRef<AbortController | null>(null);
  const requestIdRef = useRef(0);

  useEffect(() => {
    requestIdRef.current += 1;
    const requestId = requestIdRef.current;

    if (!bounds) {
      abortControllerRef.current?.abort();
      if (listings.length !== 0) setListings([]);
      setLoading(false);
      return;
    }

    if (debounceRef.current) clearTimeout(debounceRef.current);
    setLoading(true);

    debounceRef.current = setTimeout(async () => {
      abortControllerRef.current?.abort();
      abortControllerRef.current = new AbortController();
      try {
        const boundsStr = `${bounds.south},${bounds.west},${bounds.north},${bounds.east}`;
        const params = new URLSearchParams({ bounds: boundsStr });
        if (filterParam) params.set('filters', filterParam);
        if (travelParam) params.set('travel', travelParam);
        if (shareCode) params.set('share', shareCode);
        const res = await fetch(
          apiUrl('actual-listings', params),
          authHeaders({ signal: abortControllerRef.current.signal })
        );
        if (!res.ok) {
          if (requestIdRef.current === requestId) {
            setListings([]);
            setLoading(false);
          }
          throw new Error(`Actual listings fetch failed: HTTP ${res.status}`);
        }
        const json: ActualListingsResponse = await res.json();
        if (requestIdRef.current !== requestId) return;
        setListings(json.listings || []);
        setLoading(false);
      } catch (err) {
        if (requestIdRef.current === requestId && !isAbortError(err)) {
          setLoading(false);
        }
        logNonAbortError('Failed to fetch actual listings', err);
      }
    }, DEBOUNCE_MS);

    return () => {
      if (debounceRef.current) clearTimeout(debounceRef.current);
      abortControllerRef.current?.abort();
    };
    // listings intentionally excluded — it's internal state, not an input.
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [bounds, filterParam, travelParam, shareCode]);

  return { listings, loading };
}
