import { describe, expect, it, vi, beforeEach } from "vitest";
import { renderHook, act, waitFor } from "@testing-library/react";
import type { BansByCountryResponse } from "../../types/map";
import { useBansByCountry } from "../useBansByCountry";
import * as api from "../../api/map";

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

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

  it("fetches data automatically on mount", async () => {
    const fetchMock = vi.mocked(api.fetchBansByCountry);
    const response: BansByCountryResponse = {
      countries: { US: 1, GB: 2 },
      country_names: { US: "United States", GB: "United Kingdom" },
      bans: [],
      total: 3,
    };

    fetchMock.mockResolvedValueOnce(response);

    const { result } = renderHook(() => useBansByCountry("24h", "all", "fail2ban"));

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

    await waitFor(() => {
      expect(result.current.loading).toBe(false);
    });

    expect(result.current.countries).toEqual({ US: 1, GB: 2 });
    expect(result.current.countryNames).toEqual({ US: "United States", GB: "United Kingdom" });
    expect(result.current.total).toBe(3);
    expect(fetchMock).toHaveBeenCalledTimes(1);
  });

  it("does not fetch automatically when autoFetch is false", async () => {
    const fetchMock = vi.mocked(api.fetchBansByCountry);
    const response: BansByCountryResponse = {
      countries: { US: 1 },
      country_names: { US: "United States" },
      bans: [],
      total: 1,
    };

    fetchMock.mockResolvedValueOnce(response);

    const { result } = renderHook(() => useBansByCountry("24h", "all", "fail2ban", undefined, false));

    expect(result.current.loading).toBe(true);
    expect(fetchMock).not.toHaveBeenCalled();

    act(() => {
      result.current.refresh();
    });

    await waitFor(() => {
      expect(result.current.loading).toBe(false);
    });

    expect(result.current.countries).toEqual({ US: 1 });
    expect(fetchMock).toHaveBeenCalledTimes(1);
  });

  it("handles fetch errors correctly", async () => {
    const fetchMock = vi.mocked(api.fetchBansByCountry);
    const error = new Error("Network error");

    fetchMock.mockRejectedValueOnce(error);

    const { result } = renderHook(() => useBansByCountry("24h", "all", "fail2ban"));

    await waitFor(() => {
      expect(result.current.loading).toBe(false);
    });

    expect(result.current.error).not.toBeNull();
    expect(result.current.countries).toEqual({});
    expect(result.current.total).toBe(0);
  });
});
