import React, { useState, useEffect, useCallback, useRef } from 'react';
import Map from './components/Map';
import Filters from './components/Filters';
import { DEFAULT_FILTERS } from './lib/constants';

const DEBOUNCE_MS = 150;

export default function App() {
  const [filters, setFilters] = useState(DEFAULT_FILTERS);
  const [data, setData] = useState([]);
  const [resolution, setResolution] = useState(8);
  const [bounds, setBounds] = useState(null);
  const [loading, setLoading] = useState(false);
  const debounceRef = useRef(null);
  const abortControllerRef = useRef(null);

  // Debounced fetch when dependencies change
  useEffect(() => {
    if (!bounds) return;

    // Clear previous debounce timer
    if (debounceRef.current) {
      clearTimeout(debounceRef.current);
    }

    debounceRef.current = setTimeout(async () => {
      // Cancel any in-flight request
      if (abortControllerRef.current) {
        abortControllerRef.current.abort();
      }
      abortControllerRef.current = new AbortController();

      setLoading(true);
      try {
        const boundsStr = `${bounds.south},${bounds.west},${bounds.north},${bounds.east}`;
        const params = new URLSearchParams({
          resolution: resolution.toString(),
          min_year: filters.minYear.toString(),
          max_year: filters.maxYear.toString(),
          min_price: filters.minPrice.toString(),
          max_price: filters.maxPrice.toString(),
          bounds: boundsStr,
        });
        const res = await fetch(`/api/hexagons?${params}`, {
          signal: abortControllerRef.current.signal,
        });
        const json = await res.json();
        setData(json.features || []);
      } catch (err) {
        if (err.name !== 'AbortError') {
          console.error('Failed to fetch data:', err);
        }
      } finally {
        setLoading(false);
      }
    }, DEBOUNCE_MS);

    return () => {
      if (debounceRef.current) {
        clearTimeout(debounceRef.current);
      }
    };
  }, [filters, resolution, bounds]);

  const handleViewChange = useCallback(({ resolution: newRes, bounds: newBounds }) => {
    setResolution(newRes);
    setBounds(newBounds);
  }, []);

  return (
    <div className="h-screen flex">
      <Filters filters={filters} onChange={setFilters} />
      <div className="flex-1 relative">
        <Map data={data} onViewChange={handleViewChange} />
        {loading && (
          <div className="absolute top-4 right-4 bg-white px-3 py-1 rounded shadow">
            Loading...
          </div>
        )}
      </div>
    </div>
  );
}
