/**
 * React hook for live active ban list management.
 */

import { useCallback, useEffect, useRef, useState } from "react";
import { banIp, fetchActiveBans, unbanAllBans, unbanIp } from "../api/jails";
import { handleFetchError } from "../utils/fetchError";
import type { ActiveBan, UnbanAllResponse } from "../types/jail";

export interface UseActiveBansResult {
  bans: ActiveBan[];
  total: number;
  loading: boolean;
  error: string | null;
  refresh: () => void;
  banIp: (jail: string, ip: string) => Promise<void>;
  unbanIp: (ip: string, jail?: string) => Promise<void>;
  unbanAll: () => Promise<UnbanAllResponse>;
}

/**
 * Fetch and manage the currently-active ban list.
 */
export function useActiveBans(): UseActiveBansResult {
  const [bans, setBans] = useState<ActiveBan[]>([]);
  const [total, setTotal] = useState(0);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const abortRef = useRef<AbortController | null>(null);

  const load = useCallback(() => {
    abortRef.current?.abort();
    const ctrl = new AbortController();
    abortRef.current = ctrl;
    setLoading(true);
    setError(null);

    fetchActiveBans()
      .then((res) => {
        if (!ctrl.signal.aborted) {
          setBans(res.bans);
          setTotal(res.total);
        }
      })
      .catch((err: unknown) => {
        if (!ctrl.signal.aborted) {
          handleFetchError(err, setError, "Failed to fetch active bans");
        }
      })
      .finally(() => {
        if (!ctrl.signal.aborted) {
          setLoading(false);
        }
      });
  }, []);

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

  const doBan = useCallback(async (jail: string, ip: string): Promise<void> => {
    await banIp(jail, ip);
    load();
  }, [load]);

  const doUnban = useCallback(async (ip: string, jail?: string): Promise<void> => {
    await unbanIp(ip, jail);
    load();
  }, [load]);

  const doUnbanAll = useCallback(async (): Promise<UnbanAllResponse> => {
    const result = await unbanAllBans();
    load();
    return result;
  }, [load]);

  return {
    bans,
    total,
    loading,
    error,
    refresh: load,
    banIp: doBan,
    unbanIp: doUnban,
    unbanAll: doUnbanAll,
  };
}
