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

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

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

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

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

  it("returns initial state with preview and loading false", () => {
    const { result } = renderHook(() => useLogPreview());

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

  it("sets preview on successful run", async () => {
    const mockResponse = {
      lines: [{ line: "test", matched: true, groups: [] }],
      total_lines: 1,
      matched_count: 1,
      regex_error: null,
    };
    vi.mocked(previewLog).mockResolvedValue(mockResponse);

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

    await act(async () => {
      await result.current.run({
        log_path: "/var/log/test.log",
        fail_regex: "pattern",
        num_lines: 100,
      });
    });

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

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

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

    await act(async () => {
      await result.current.run({
        log_path: "/var/log/test.log",
        fail_regex: "pattern",
        num_lines: 100,
      });
    });

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

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

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

    await act(async () => {
      await result.current.run({
        log_path: "/var/log/test.log",
        fail_regex: "pattern",
        num_lines: 100,
      });
    });

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

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

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

    await act(async () => {
      await result.current.run({
        log_path: "/var/log/test.log",
        fail_regex: "pattern",
        num_lines: 100,
      });
    });

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

  it("sets loading to false in finally block", async () => {
    vi.mocked(previewLog).mockResolvedValue({
      lines: [],
      total_lines: 0,
      matched_count: 0,
      regex_error: null,
    });

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

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

    await act(async () => {
      await result.current.run({
        log_path: "/var/log/test.log",
        fail_regex: "pattern",
        num_lines: 100,
      });
    });

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