import { useEffect, useState } from 'react';

import type { NearbyStation, GeoPoint } from '../lib/nearby-stations';
import {
  STATION_CATEGORIES,
  selectNearbyStations,
  stationSearchBounds,
} from '../lib/nearby-stations';
import type { POIResponse } from '../types';
import { apiUrl, assertOk, authHeaders, logNonAbortError } from '../lib/api';

function boundsParam(bounds: ReturnType<typeof stationSearchBounds>): string {
  return `${bounds.south},${bounds.west},${bounds.north},${bounds.east}`;
}

export function useNearbyStations(origin: GeoPoint | null) {
  const [stations, setStations] = useState<NearbyStation[]>([]);
  const [loading, setLoading] = useState(false);
  const lat = origin?.lat;
  const lon = origin?.lon;

  useEffect(() => {
    if (lat == null || lon == null) {
      setStations([]);
      setLoading(false);
      return;
    }

    const controller = new AbortController();
    setStations([]);
    setLoading(true);

    const originPoint = { lat, lon };
    const bounds = stationSearchBounds(originPoint);
    const params = new URLSearchParams({
      bounds: boundsParam(bounds),
      categories: STATION_CATEGORIES.join(','),
    });

    fetch(apiUrl('pois', params), authHeaders({ signal: controller.signal }))
      .then((response) => {
        assertOk(response, 'nearby stations');
        return response.json() as Promise<POIResponse>;
      })
      .then((json) => {
        if (!controller.signal.aborted) {
          setStations(selectNearbyStations(json.pois ?? [], originPoint));
        }
      })
      .catch((error) => logNonAbortError('Failed to fetch nearby stations', error))
      .finally(() => {
        if (!controller.signal.aborted) setLoading(false);
      });

    return () => controller.abort();
  }, [lat, lon]);

  return { stations, loading };
}
