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

test("List renders with options", () => {
  const options = [
    { label: "Option 1", value: "1" },
    { label: "Option 2", value: "2" },
  ];

  render(<List optionLabel="label" options={options} />);

  expect(screen.getByText("Option 1")).toBeInTheDocument();
  expect(screen.getByText("Option 2")).toBeInTheDocument();
});

test("List calls onChange when option is clicked", () => {
  const onChange = vi.fn();
  const options = [{ label: "Click me", value: "clicked" }];

  render(<List optionLabel="label" options={options} onChange={onChange} />);

  fireEvent.click(screen.getByText("Click me"));
  expect(onChange).toHaveBeenCalled();
});

test("List renders with selected value", () => {
  const options = [
    { label: "Selected", value: "Selected" },
    { label: "Not selected", value: "Not selected" },
  ];

  render(<List optionLabel="label" options={options} value="Selected" />);

  const selectedItem = screen
    .getByText("Selected")
    .closest("[role-slot='list-item']");
  expect(selectedItem).toHaveClass("bg-blue-500", "text-white");
});

test("List handles keyboard navigation with Enter", () => {
  const onChange = vi.fn();
  const options = [{ label: "Keyboard test", value: "kb" }];

  render(<List optionLabel="label" options={options} onChange={onChange} />);

  const item = screen
    .getByText("Keyboard test")
    .closest("[role-slot='list-item']");
  if (item) {
    fireEvent.keyDown(item, { key: "Enter" });
  }

  expect(onChange).toHaveBeenCalled();
});

test("List handles keyboard navigation with Space", () => {
  const onChange = vi.fn();
  const options = [{ label: "Space test", value: "space" }];

  render(<List optionLabel="label" options={options} onChange={onChange} />);

  const item = screen
    .getByText("Space test")
    .closest("[role-slot='list-item']");
  if (item) {
    fireEvent.keyDown(item, { key: " " });
  }

  expect(onChange).toHaveBeenCalled();
});

test("List renders group headers with optionGroupLabel", () => {
  const options = [
    {
      label: "Group 1",
      children: [
        { label: "Item 1", value: "1" },
        { label: "Item 2", value: "2" },
      ],
    },
  ];

  render(
    <List
      optionLabel="label"
      optionGroupLabel="label"
      optionGroupChildren="children"
      options={options}
    />,
  );

  expect(screen.getByText("Group 1")).toBeInTheDocument();
  expect(screen.getByText("Item 1")).toBeInTheDocument();
  expect(screen.getByText("Item 2")).toBeInTheDocument();
});

test("List applies custom styles", () => {
  const options = [{ label: "Styled", value: "1" }];

  render(
    <List
      optionLabel="label"
      options={options}
      listStyle={{ backgroundColor: "red" }}
      listItemStyle={{ color: "blue" }}
      listGroupStyle={{ fontWeight: "bold" }}
    />,
  );

  const container = document.querySelector("[data-slot='list']");
  expect(container).toHaveStyle({ backgroundColor: "red" });
});

test("List renders empty when no options", () => {
  render(<List optionLabel="label" options={[]} />);

  const listbox = document.querySelector("[role-slot='listbox']");
  expect(listbox?.children).toHaveLength(0);
});