/**
 * React hook for managing inactive jail operations and configuration actions.
 */
import { useCallback, useEffect, useRef, useState } from "react";
import {
  activateJail,
  deactivateJail,
  deleteJailLocalOverride,
  fetchInactiveJails,
  validateJailConfig,
  createJailConfigFile,
} from "../api/config";
import { handleFetchError } from "../utils/fetchError";
import type {
  ActivateJailRequest,
  ConfFileCreateRequest,
  InactiveJail,
  JailActivationResponse,
  JailValidationResult,
} from "../types/config";

export interface UseJailAdminResult {
  inactiveJails: InactiveJail[];
  inactiveLoading: boolean;
  inactiveError: string | null;
  refreshInactiveJails: () => void;
  deactivateJail: (name: string) => Promise<void>;
  deleteJailLocalOverride: (name: string) => Promise<void>;
  validateJailConfig: (name: string) => Promise<JailValidationResult>;
  activateJail: (name: string, payload: ActivateJailRequest) => Promise<JailActivationResponse>;
  createJailConfigFile: (payload: ConfFileCreateRequest) => Promise<void>;
}

/**
 * Load inactive fail2ban jails and expose the admin actions used by the
 * jail configuration tab.
 */
export function useJailAdmin(): UseJailAdminResult {
  const [inactiveJails, setInactiveJails] = useState<InactiveJail[]>([]);
  const [inactiveLoading, setInactiveLoading] = useState(false);
  const [inactiveError, setInactiveError] = useState<string | null>(null);
  const abortRef = useRef<AbortController | null>(null);

  const refreshInactiveJails = useCallback((): void => {
    abortRef.current?.abort();
    const ctrl = new AbortController();
    abortRef.current = ctrl;

    setInactiveLoading(true);
    setInactiveError(null);

    fetchInactiveJails()
      .then((resp) => {
        if (!ctrl.signal.aborted) {
          setInactiveJails(resp.jails);
        }
      })
      .catch((err: unknown) => {
        if (!ctrl.signal.aborted) {
          handleFetchError(err, setInactiveError, "Failed to load inactive jails");
        }
      })
      .finally(() => {
        if (!ctrl.signal.aborted) {
          setInactiveLoading(false);
        }
      });
  }, []);

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

  const handleDeactivateJail = useCallback(
    async (name: string): Promise<void> => {
      await deactivateJail(name);
    },
    [],
  );

  const handleDeleteLocalOverride = useCallback(
    async (name: string): Promise<void> => {
      await deleteJailLocalOverride(name);
    },
    [],
  );

  const handleValidateJailConfig = useCallback(
    async (name: string): Promise<JailValidationResult> => {
      return await validateJailConfig(name);
    },
    [],
  );

  const handleActivateJail = useCallback(
    async (name: string, payload: ActivateJailRequest): Promise<JailActivationResponse> => {
      return await activateJail(name, payload);
    },
    [],
  );

  const handleCreateJailConfigFile = useCallback(
    async (payload: ConfFileCreateRequest): Promise<void> => {
      await createJailConfigFile(payload);
    },
    [],
  );

  return {
    inactiveJails,
    inactiveLoading,
    inactiveError,
    refreshInactiveJails,
    deactivateJail: handleDeactivateJail,
    deleteJailLocalOverride: handleDeleteLocalOverride,
    validateJailConfig: handleValidateJailConfig,
    activateJail: handleActivateJail,
    createJailConfigFile: handleCreateJailConfigFile,
  };
}
