import { describe, it, expect, vi, beforeEach } from "vitest";
import { renderHook, act } from "@testing-library/react";
import * as configApi from "../../api/config";
import { useActionConfig } from "../useActionConfig";

vi.mock("../../api/config");

describe("useActionConfig", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    vi.mocked(configApi.fetchAction).mockResolvedValue({
      name: "iptables",
      filename: "iptables.conf",
      source_file: "/etc/fail2ban/action.d/iptables.conf",
      active: false,
      used_by_jails: [],
      before: null,
      after: null,
      actionstart: "",
      actionstop: "",
      actioncheck: "",
      actionban: "",
      actionunban: "",
      actionflush: "",
      definition_vars: {},
      init_vars: {},
      has_local_override: false,
    });
    vi.mocked(configApi.updateAction).mockResolvedValue(undefined);
  });

  it("calls fetchAction exactly once for stable name and rerenders", async () => {
    const { rerender } = renderHook(
      ({ name }) => useActionConfig(name),
      { initialProps: { name: "iptables" } },
    );

    await act(async () => {
      await new Promise((resolve) => setTimeout(resolve, 0));
    });

    expect(configApi.fetchAction).toHaveBeenCalledTimes(1);

    // Rerender with the same action name; fetch should not be called again.
    rerender({ name: "iptables" });

    await act(async () => {
      await new Promise((resolve) => setTimeout(resolve, 0));
    });

    expect(configApi.fetchAction).toHaveBeenCalledTimes(1);
  });

  it("calls fetchAction again when name changes", async () => {
    const { rerender } = renderHook(
      ({ name }) => useActionConfig(name),
      { initialProps: { name: "iptables" } },
    );

    await act(async () => {
      await new Promise((resolve) => setTimeout(resolve, 0));
    });

    expect(configApi.fetchAction).toHaveBeenCalledTimes(1);

    rerender({ name: "ssh" });

    await act(async () => {
      await new Promise((resolve) => setTimeout(resolve, 0));
    });

    expect(configApi.fetchAction).toHaveBeenCalledTimes(2);
  });
});
