/**
 * React hook for the online board search pages.
 *
 * Calls `searchFlights` on param change, manages loading/error/data state.
 * Supports AbortController-based cancellation (§4.1.12).
 * Thin wrapper — integration-tested by 2E/2H, not unit-tested here.
 *
 * @module
 */

import { useState, useEffect, useCallback, useRef } from "react";
import { useApiClient } from "@/shared/api/provider.js";
import { searchFlights } from "../api.js";
import type { SearchFlightsParams } from "../api.js";
import type { ISimpleFlight } from "../types.js";
import type { ApiError } from "@/shared/api/errors.js";

export interface UseOnlineBoardResult {
  flights: ISimpleFlight[];
  loading: boolean;
  error: ApiError | null;
  refresh: () => void;
  /** Cancel the in-flight request (§4.1.12). Resets loading to false. */
  cancel: () => void;
}

/**
 * Hook for online board search pages. Fetches flights based on search params
 * and provides refresh + cancel capability.
 */
export function useOnlineBoard(
  params: SearchFlightsParams,
): UseOnlineBoardResult {
  const client = useApiClient();
  const [flights, setFlights] = useState<ISimpleFlight[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<ApiError | null>(null);
  const [refreshKey, setRefreshKey] = useState(0);

  // Serialize params for useEffect dependency
  const paramsRef = useRef(params);
  paramsRef.current = params;

  // AbortController for the current in-flight request (§4.1.12)
  const abortRef = useRef<AbortController | null>(null);

  const refresh = useCallback(() => {
    setRefreshKey((k) => k + 1);
  }, []);

  const cancel = useCallback(() => {
    if (abortRef.current) {
      abortRef.current.abort();
      abortRef.current = null;
    }
    setLoading(false);
  }, []);

  useEffect(() => {
    // Callers pass empty strings when the search context isn't resolved
    // yet (e.g. details page with no `?request=...`). Skip the fetch
    // rather than sending `dateFrom=&dateTo=` — the backend rejects that
    // with HTTP 400 and it shows up as an error in the browser console.
    if (!params.dateFrom || !params.dateTo) {
      setFlights([]);
      setLoading(false);
      setError(null);
      return;
    }

    // Abort any previous in-flight request (§4.1.12 — new search aborts in-flight)
    if (abortRef.current) {
      abortRef.current.abort();
    }
    const controller = new AbortController();
    abortRef.current = controller;

    setLoading(true);
    setError(null);

    searchFlights(client, paramsRef.current, controller.signal)
      .then((response) => {
        if (!controller.signal.aborted) {
          setFlights(response.data?.routes ?? []);
          setLoading(false);
        }
      })
      .catch((err: unknown) => {
        // Ignore aborted requests — the user cancelled intentionally
        if (controller.signal.aborted) return;
        console.error("[useOnlineBoard] API error:", err);
        setError(err as ApiError);
        setLoading(false);
      });

    return () => {
      controller.abort();
      abortRef.current = null;
    };
  }, [
    client,
    params.flightNumber,
    params.dateFrom,
    params.dateTo,
    params.departure,
    params.arrival,
    params.timeFrom,
    params.timeTo,
    refreshKey,
  ]);

  return { flights, loading, error, refresh, cancel };
}
