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

const DEBOUNCE_MS = 200;

interface UseDevelopmentsOptions {
  /** Only fetch when the "new developments" overlay is toggled on. */
  enabled?: boolean;
  shareCode?: string;
}

/**
 * Fetches planned/pipeline development sites (brownfield register + Homes
 * England) within the current viewport. Mirrors useActualListings, but gated by
 * an `enabled` flag so nothing is fetched until the overlay is switched on.
 */
export function useDevelopments(
  bounds: Bounds | null,
  { enabled = false, shareCode = '' }: UseDevelopmentsOptions = {}
) {
  const [developments, setDevelopments] = useState<Development[]>([]);
  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 (!enabled || !bounds) {
      abortControllerRef.current?.abort();
      if (developments.length !== 0) setDevelopments([]);
      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 (shareCode) params.set('share', shareCode);
        const res = await fetch(
          apiUrl('developments', params),
          authHeaders({ signal: abortControllerRef.current.signal })
        );
        if (!res.ok) {
          if (requestIdRef.current === requestId) {
            setDevelopments([]);
            setLoading(false);
          }
          throw new Error(`Developments fetch failed: HTTP ${res.status}`);
        }
        const json: DevelopmentsResponse = await res.json();
        if (requestIdRef.current !== requestId) return;
        setDevelopments(json.developments || []);
        setLoading(false);
      } catch (err) {
        if (requestIdRef.current === requestId && !isAbortError(err)) {
          setLoading(false);
        }
        logNonAbortError('Failed to fetch developments', err);
      }
    }, DEBOUNCE_MS);

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

  return { developments, loading };
}
