import { describe, it, expect, vi } from "vitest";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { FluentProvider, webLightTheme } from "@fluentui/react-components";
import { BannedIpsSection, type BannedIpsSectionProps } from "../BannedIpsSection";
import type { ActiveBan } from "../../../types/jail";

function makeBan(ip: string): ActiveBan {
  return {
    ip,
    jail: "sshd",
    banned_at: "2025-01-01T10:00:00+00:00",
    expires_at: "2025-01-01T10:10:00+00:00",
    ban_count: 1,
    country: "US",
  };
}

function renderWithProps(props: Partial<BannedIpsSectionProps> = {}) {
  const defaults: BannedIpsSectionProps = {
    items: [makeBan("1.2.3.4"), makeBan("5.6.7.8")],
    total: 2,
    page: 1,
    pageSize: 25,
    search: "",
    loading: false,
    error: null,
    opError: null,
    onSearch: vi.fn(),
    onPageChange: vi.fn(),
    onPageSizeChange: vi.fn(),
    onRefresh: vi.fn(),
    onUnban: vi.fn(),
  };

  return render(
    <FluentProvider theme={webLightTheme}>
      <BannedIpsSection {...defaults} {...props} />
    </FluentProvider>,
  );
}

describe("BannedIpsSection", () => {
  it("shows the table rows and total count", () => {
    renderWithProps();
    expect(screen.getByText("Currently Banned IPs")).toBeTruthy();
    expect(screen.getByText("1.2.3.4")).toBeTruthy();
    expect(screen.getByText("5.6.7.8")).toBeTruthy();
  });

  it("shows a spinner while loading", () => {
    renderWithProps({ loading: true, items: [] });
    expect(screen.getByText("Loading banned IPs…")).toBeTruthy();
  });

  it("shows error message when error is present", () => {
    renderWithProps({ error: "Failed to load" });
    expect(screen.getByText(/Failed to load/i)).toBeTruthy();
  });

  it("triggers onUnban for IP row button", async () => {
    const onUnban = vi.fn();
    renderWithProps({ onUnban });

    const unbanBtn = screen.getByLabelText("Unban 1.2.3.4");
    await userEvent.click(unbanBtn);

    expect(onUnban).toHaveBeenCalledWith("1.2.3.4");
  });

  it("calls onSearch when the search input changes", async () => {
    const onSearch = vi.fn();
    renderWithProps({ onSearch });

    const input = screen.getByPlaceholderText("e.g. 192.168");
    await userEvent.type(input, "1.2.3");

    expect(onSearch).toHaveBeenCalled();
  });
});
