import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { renderHook, act } from "@testing-library/react";
import { ApiError } from "../../api/client";
import { useRegexTester } from "../useRegexTester";

vi.mock("../../api/config", () => ({
  testRegex: vi.fn(),
}));

import { testRegex } from "../../api/config";

describe("useRegexTester", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  afterEach(() => {
    vi.clearAllMocks();
  });

  it("returns initial state with result and testing false", () => {
    const { result } = renderHook(() => useRegexTester());

    expect(result.current.result).toBeNull();
    expect(result.current.testing).toBe(false);
    expect(result.current.error).toBeNull();
  });

  it("sets result on successful test", async () => {
    const mockResponse = { matched: true, groups: ["host"], error: null };
    vi.mocked(testRegex).mockResolvedValue(mockResponse);

    const { result } = renderHook(() => useRegexTester());

    await act(async () => {
      await result.current.test({ log_line: "test", fail_regex: "pattern" });
    });

    expect(result.current.result).toEqual(mockResponse);
    expect(result.current.error).toBeNull();
    expect(result.current.testing).toBe(false);
  });

  it("sets error for normal errors via handleFetchError", async () => {
    vi.mocked(testRegex).mockRejectedValue(new Error("Network error"));

    const { result } = renderHook(() => useRegexTester());

    await act(async () => {
      await result.current.test({ log_line: "test", fail_regex: "pattern" });
    });

    expect(result.current.error).toBe("Network error");
    expect(result.current.testing).toBe(false);
  });

  it("ignores auth errors (401) via handleFetchError", async () => {
    vi.mocked(testRegex).mockRejectedValue(new ApiError(401, "Unauthorized"));

    const { result } = renderHook(() => useRegexTester());

    await act(async () => {
      await result.current.test({ log_line: "test", fail_regex: "pattern" });
    });

    expect(result.current.error).toBeNull();
    expect(result.current.testing).toBe(false);
  });

  it("ignores auth errors (403) via handleFetchError", async () => {
    vi.mocked(testRegex).mockRejectedValue(new ApiError(403, "Forbidden"));

    const { result } = renderHook(() => useRegexTester());

    await act(async () => {
      await result.current.test({ log_line: "test", fail_regex: "pattern" });
    });

    expect(result.current.error).toBeNull();
    expect(result.current.testing).toBe(false);
  });

  it("sets testing to false in finally block", async () => {
    vi.mocked(testRegex).mockResolvedValue({
      matched: false,
      groups: [],
      error: null,
    });

    const { result } = renderHook(() => useRegexTester());

    expect(result.current.testing).toBe(false);

    await act(async () => {
      await result.current.test({
        log_line: "test",
        fail_regex: "pattern",
      });
    });

    expect(result.current.testing).toBe(false);
  });
});
