/**
 * `useDashboardCountryData` hook.
 *
 * Fetches ban-by-country aggregates for dashboard chart components.  Unlike
 * `useMapData`, this hook has no debouncing or map-specific state.
 *
 * Re-fetches automatically when `timeRange` or `origin` changes.
 */

import { useCallback, useEffect, useRef, useState } from "react";
import { fetchBansByCountry } from "../api/map";
import { handleFetchError } from "../utils/fetchError";
import type { DashboardBanItem, BanOriginFilter, TimeRange } from "../types/ban";

// ---------------------------------------------------------------------------
// Return type
// ---------------------------------------------------------------------------

/** Return value shape for {@link useDashboardCountryData}. */
export interface UseDashboardCountryDataResult {
  /** ISO alpha-2 country code → ban count. */
  countries: Record<string, number>;
  /** ISO alpha-2 country code → human-readable country name. */
  countryNames: Record<string, string>;
  /** All ban records in the selected window. */
  bans: DashboardBanItem[];
  /** Total ban count in the window. */
  total: number;
  /** True while a fetch is in flight. */
  isLoading: boolean;
  /** Error message or `null`. */
  error: string | null;
  /** Re-fetch the data immediately. */
  reload: () => void;
}

// ---------------------------------------------------------------------------
// Hook
// ---------------------------------------------------------------------------

/**
 * Fetch and expose ban-by-country data for dashboard charts.
 *
 * @param timeRange - Time-range preset: `"24h"`, `"7d"`, `"30d"`, or `"365d"`.
 * @param origin    - Origin filter: `"all"`, `"blocklist"`, or `"selfblock"`.
 * @returns Aggregated country data, ban list, loading state, and error.
 */
export function useDashboardCountryData(
  timeRange: TimeRange,
  origin: BanOriginFilter,
  source: "fail2ban" | "archive" = "fail2ban",
): UseDashboardCountryDataResult {
  const [countries, setCountries] = useState<Record<string, number>>({});
  const [countryNames, setCountryNames] = useState<Record<string, string>>({});
  const [bans, setBans] = useState<DashboardBanItem[]>([]);
  const [total, setTotal] = useState<number>(0);
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [error, setError] = useState<string | null>(null);

  const abortRef = useRef<AbortController | null>(null);

  const load = useCallback((): void => {
    // Abort any in-flight request.
    abortRef.current?.abort();
    const controller = new AbortController();
    abortRef.current = controller;

    setIsLoading(true);
    setError(null);

    fetchBansByCountry(timeRange, origin, source)
      .then((data) => {
        if (controller.signal.aborted) return;
        setCountries(data.countries);
        setCountryNames(data.country_names);
        setBans(data.bans);
        setTotal(data.total);
      })
      .catch((err: unknown) => {
        if (controller.signal.aborted) return;
        handleFetchError(err, setError, "Failed to fetch dashboard country data");
      })
      .finally(() => {
        if (!controller.signal.aborted) {
          setIsLoading(false);
        }
      });
  }, [timeRange, origin, source]);

  useEffect(() => {
    load();
    return (): void => {
      abortRef.current?.abort();
    };
  }, [load]);

  return { countries, countryNames, bans, total, isLoading, error, reload: load };
}
