import { fireEvent, render, screen, within } from "@testing-library/react";
import { expect, test, vi } from "vitest";

import type { PageData } from "@/shared/api/pagination";
import { ResourcePagination } from "@/shared/ui/resource-pagination";

const pageData: PageData<string> = {
  totalCount: 42,
  page: 1,
  size: 20,
  hasNext: true,
  items: [],
};

test("ResourcePagination uses PageData and real buttons for accessible page movement", () => {
  const onPageChange = vi.fn();
  const onSizeChange = vi.fn();

  render(<ResourcePagination data={pageData} onPageChange={onPageChange} onSizeChange={onSizeChange} />);

  const previous = screen.getByRole("button", { name: "이전 페이지" });
  const next = screen.getByRole("button", { name: "다음 페이지" });

  expect(previous.tagName).toBe("BUTTON");
  expect(next).toBeEnabled();
  expect(screen.getByText("총 42개 · 2페이지")).toBeInTheDocument();

  fireEvent.click(previous);
  fireEvent.click(next);
  fireEvent.change(screen.getByLabelText("페이지 크기"), { target: { value: "50" } });

  expect(onPageChange).toHaveBeenNthCalledWith(1, 0);
  expect(onPageChange).toHaveBeenNthCalledWith(2, 2);
  expect(onSizeChange).toHaveBeenCalledWith(50);
});

test("ResourcePagination disables unavailable previous and next actions", () => {
  render(<ResourcePagination data={{ ...pageData, page: 0, hasNext: false }} onPageChange={vi.fn()} onSizeChange={vi.fn()} />);

  expect(screen.getByRole("button", { name: "이전 페이지" })).toBeDisabled();
  expect(screen.getByRole("button", { name: "다음 페이지" })).toBeDisabled();
});

test("ResourcePagination connects each page size label to a unique select", () => {
  const { container } = render(
    <>
      <ResourcePagination data={pageData} onPageChange={vi.fn()} onSizeChange={vi.fn()} />
      <ResourcePagination data={{ ...pageData, page: 0 }} onPageChange={vi.fn()} onSizeChange={vi.fn()} />
    </>,
  );

  const selects = screen.getAllByLabelText("페이지 크기");
  const selectIds = selects.map((select) => select.id);
  const labels = Array.from(container.querySelectorAll("label"));

  expect(new Set(selectIds).size).toBe(selectIds.length);
  expect(labels.map((label) => label.control)).toEqual(selects);
});

test("ResourcePagination separates page size from stacked mobile movement controls", () => {
  render(<ResourcePagination data={pageData} onPageChange={vi.fn()} onSizeChange={vi.fn()} />);

  const sizeControls = screen.getByRole("group", { name: "페이지 크기 설정" });
  const movementControls = screen.getByRole("group", { name: "페이지 이동" });
  const previous = within(movementControls).getByRole("button", { name: "이전 페이지" });
  const next = within(movementControls).getByRole("button", { name: "다음 페이지" });

  expect(within(sizeControls).getByLabelText("페이지 크기")).toBeInTheDocument();
  expect(sizeControls).not.toContainElement(previous);
  expect(movementControls).toHaveClass("grid-cols-1");
  expect(previous).toHaveClass("min-h-11", "w-full", "whitespace-nowrap");
  expect(next).toHaveClass("min-h-11", "w-full", "whitespace-nowrap");
});
