import {
  cleanup,
  render,
  screen,
} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { useContext } from "react";
import assert from "node:assert";
import {
  afterEach,
  describe,
  mock,
  test,
} from "node:test";
import { PaginationContext } from "./context";
import { Pagination } from "./index";

describe("Pagination", () => {
  afterEach(() => {
    cleanup();
  });

  test("renders radio inputs when name prop is provided", () => {
    const items = [
      { page: 1, isActive: true },
      { page: 2, isActive: false },
    ];

    render(
      <Pagination
        name={"page"}
        items={items}
      />
    );

    assert.strictEqual(screen.getAllByRole("radio").length, 2);
  });

  test("renders navigation landmark", () => {
    render(<Pagination items={[ { page: 1, href: "/page-1" } ]} />);
    assert.notStrictEqual(screen.queryByRole("navigation"), null);
  });

  test("calls onClick callback for link item", async () => {
    const user = userEvent.setup();
    const onClick = mock.fn(({ event }) => {
      event.preventDefault();
    });
    const items = [
      { page: 1, href: "/page-1" },
    ];

    render(
      <Pagination
        items={items}
        onClick={onClick}
      />
    );

    await user.click(screen.getByRole("link"));
    assert.strictEqual(onClick.mock.calls.length, 1);
  });

  test("does not mutate source items when active page changes", async () => {
    const user = userEvent.setup();
    const items = [
      { page: 1, isActive: true },
      { page: 2, isActive: false },
    ];
    const sourceSnapshot = JSON.stringify(items);

    render(<Pagination name={"page"} items={items} />);

    const radios = screen.getAllByRole("radio");
    await user.click(radios[1] as HTMLElement);

    assert.strictEqual(JSON.stringify(items), sourceSnapshot);
  });

  test("provides updated pages via context after state change", async () => {
    const user = userEvent.setup();
    const items = [
      { page: 1, isActive: true },
      { page: 2, isActive: false },
    ];

    const ActivePage = () => {
      const { pages } = useContext(PaginationContext);
      const active = (pages || []).find((item) => (item as { isActive?: boolean; }).isActive) as { page?: number; } | undefined;
      return <div data-testid={"active-page"}>{active?.page ?? "none"}</div>;
    };

    render(
      <Pagination name={"page"} items={items}>
        <ActivePage />
      </Pagination>
    );

    assert.strictEqual(screen.getByTestId("active-page").textContent, "1");

    const radios = screen.getAllByRole("radio");
    await user.click(radios[1] as HTMLElement);

    assert.strictEqual(screen.getByTestId("active-page").textContent, "2");
  });
});
