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

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

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

  it("fetches data and exposes country data with reload function", async () => {
    const fetchMock = vi.mocked(api.fetchBansByCountry);
    const response: BansByCountryResponse = {
      countries: { US: 1, GB: 2 },
      country_names: { US: "United States", GB: "United Kingdom" },
      bans: [
        {
          ip: "1.2.3.4",
          jail: "sshd",
          banned_at: "2024-01-01T00:00:00Z",
          service: null,
          country_code: "US",
          country_name: "United States",
          asn: "AS123",
          org: "Org",
          ban_count: 1,
          origin: "selfblock",
        },
      ],
      total: 3,
    };

    fetchMock.mockResolvedValueOnce(response);

    const { result } = renderHook(() => useDashboardCountryData("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.bans).toHaveLength(1);
    expect(result.current.total).toBe(3);
    expect(fetchMock).toHaveBeenCalledTimes(1);
  });

  it("supports the reload function for manual refresh", async () => {
    const fetchMock = vi.mocked(api.fetchBansByCountry);
    const response: BansByCountryResponse = {
      countries: { US: 1 },
      country_names: { US: "United States" },
      bans: [],
      total: 1,
    };

    fetchMock.mockResolvedValueOnce(response);
    fetchMock.mockResolvedValueOnce({ ...response, total: 2 });

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

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

    expect(result.current.total).toBe(1);

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

    await waitFor(() => {
      expect(result.current.total).toBe(2);
    });

    expect(fetchMock).toHaveBeenCalledTimes(2);
  });
});
