/**
 * React hook for loading action metadata used by the actions tab.
 */
import { useCallback, useEffect, useRef, useState } from "react";
import { fetchActions, removeActionFromJail, createAction, assignActionToJail } from "../api/config";
import { handleFetchError } from "../utils/fetchError";
import type { ActionConfig, ActionCreateRequest } from "../types/config";

export interface UseActionListResult {
  actions: ActionConfig[];
  loading: boolean;
  error: string | null;
  refresh: () => void;
  removeActionFromJail: (jailName: string, actionName: string) => Promise<void>;
  createAction: (payload: ActionCreateRequest) => Promise<ActionConfig>;
  assignActionToJail: (jailName: string, payload: { action_name: string }, reload: boolean) => Promise<void>;
}

/**
 * Load the action inventory and expose related action operations.
 */
export function useActionList(): UseActionListResult {
  const [actions, setActions] = useState<ActionConfig[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const abortRef = useRef<AbortController | null>(null);

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

    setLoading(true);
    setError(null);

    fetchActions()
      .then((resp) => {
        if (!controller.signal.aborted) {
          setActions(resp.actions);
        }
      })
      .catch((err: unknown) => {
        if (!controller.signal.aborted) {
          handleFetchError(err, setError, "Failed to load actions");
        }
      })
      .finally(() => {
        if (!controller.signal.aborted) {
          setLoading(false);
        }
      });
  }, []);

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

  const handleRemoveActionFromJail = useCallback(
    async (jailName: string, actionName: string): Promise<void> => {
      await removeActionFromJail(jailName, actionName);
    },
    [],
  );

  const handleCreateAction = useCallback(
    async (payload: ActionCreateRequest): Promise<ActionConfig> => {
      return await createAction(payload);
    },
    [],
  );

  const handleAssignActionToJail = useCallback(
    async (jailName: string, payload: { action_name: string }, reload: boolean): Promise<void> => {
      await assignActionToJail(jailName, payload, reload);
    },
    [],
  );

  return {
    actions,
    loading,
    error,
    refresh,
    removeActionFromJail: handleRemoveActionFromJail,
    createAction: handleCreateAction,
    assignActionToJail: handleAssignActionToJail,
  };
}
