import { fireEvent, render, screen } from "@solidjs/testing-library";
import { describe, expect, it, vi } from "vitest";
import { DropdownMenu } from "../../../src/components/dropdown-menu/index";

describe("DropdownMenu — rendering", () => {
  it("content has role=menu when open", () => {
    render(() => (
      <DropdownMenu defaultOpen>
        <DropdownMenu.Trigger>Actions</DropdownMenu.Trigger>
        <DropdownMenu.Content>
          <DropdownMenu.Item value="edit">Edit</DropdownMenu.Item>
        </DropdownMenu.Content>
      </DropdownMenu>
    ));
    expect(screen.getByRole("menu")).toBeTruthy();
  });

  it("items have role=menuitem", () => {
    render(() => (
      <DropdownMenu defaultOpen>
        <DropdownMenu.Trigger>Actions</DropdownMenu.Trigger>
        <DropdownMenu.Content>
          <DropdownMenu.Item value="edit">Edit</DropdownMenu.Item>
          <DropdownMenu.Item value="delete">Delete</DropdownMenu.Item>
        </DropdownMenu.Content>
      </DropdownMenu>
    ));
    expect(screen.getAllByRole("menuitem")).toHaveLength(2);
  });

  it("trigger has correct ARIA", () => {
    render(() => (
      <DropdownMenu>
        <DropdownMenu.Trigger>Actions</DropdownMenu.Trigger>
        <DropdownMenu.Content>
          <DropdownMenu.Item value="edit">Edit</DropdownMenu.Item>
        </DropdownMenu.Content>
      </DropdownMenu>
    ));
    const trigger = screen.getByText("Actions");
    expect(trigger.getAttribute("aria-haspopup")).toBe("menu");
    expect(trigger.getAttribute("aria-expanded")).toBe("false");
  });
});

describe("DropdownMenu — interactions", () => {
  it("click trigger opens", () => {
    render(() => (
      <DropdownMenu>
        <DropdownMenu.Trigger>Actions</DropdownMenu.Trigger>
        <DropdownMenu.Content>
          <DropdownMenu.Item value="edit">Edit</DropdownMenu.Item>
        </DropdownMenu.Content>
      </DropdownMenu>
    ));
    expect(screen.queryByRole("menu")).toBeNull();
    fireEvent.click(screen.getByText("Actions"));
    expect(screen.getByRole("menu")).toBeTruthy();
  });

  it("Escape closes", () => {
    render(() => (
      <DropdownMenu defaultOpen>
        <DropdownMenu.Trigger>Actions</DropdownMenu.Trigger>
        <DropdownMenu.Content>
          <DropdownMenu.Item value="edit">Edit</DropdownMenu.Item>
        </DropdownMenu.Content>
      </DropdownMenu>
    ));
    fireEvent.keyDown(screen.getByRole("menu"), { key: "Escape" });
    expect(screen.queryByRole("menu")).toBeNull();
  });

  it("item click activates and closes", () => {
    const onSelect = vi.fn();
    render(() => (
      <DropdownMenu defaultOpen>
        <DropdownMenu.Trigger>Actions</DropdownMenu.Trigger>
        <DropdownMenu.Content>
          <DropdownMenu.Item value="edit" onSelect={onSelect}>Edit</DropdownMenu.Item>
        </DropdownMenu.Content>
      </DropdownMenu>
    ));
    fireEvent.click(screen.getByRole("menuitem"));
    expect(onSelect).toHaveBeenCalled();
    expect(screen.queryByRole("menu")).toBeNull();
  });
});

describe("DropdownMenu — keyboard navigation", () => {
  it("Enter activates item", () => {
    const onSelect = vi.fn();
    render(() => (
      <DropdownMenu defaultOpen>
        <DropdownMenu.Trigger>Actions</DropdownMenu.Trigger>
        <DropdownMenu.Content>
          <DropdownMenu.Item value="edit" onSelect={onSelect}>Edit</DropdownMenu.Item>
        </DropdownMenu.Content>
      </DropdownMenu>
    ));
    const menu = screen.getByRole("menu");
    fireEvent.keyDown(menu, { key: "ArrowDown" });
    fireEvent.keyDown(menu, { key: "Enter" });
    expect(onSelect).toHaveBeenCalled();
  });

  it("ArrowDown navigates", () => {
    render(() => (
      <DropdownMenu defaultOpen>
        <DropdownMenu.Trigger>Actions</DropdownMenu.Trigger>
        <DropdownMenu.Content>
          <DropdownMenu.Item value="edit">Edit</DropdownMenu.Item>
          <DropdownMenu.Item value="delete">Delete</DropdownMenu.Item>
        </DropdownMenu.Content>
      </DropdownMenu>
    ));
    const menu = screen.getByRole("menu");
    fireEvent.keyDown(menu, { key: "ArrowDown" });
    const items = screen.getAllByRole("menuitem");
    expect(items[0].getAttribute("data-highlighted")).toBe("");
  });
});

describe("DropdownMenu — checkbox and radio items", () => {
  it("CheckboxItem toggles", () => {
    const onChange = vi.fn();
    render(() => (
      <DropdownMenu defaultOpen>
        <DropdownMenu.Trigger>Actions</DropdownMenu.Trigger>
        <DropdownMenu.Content>
          <DropdownMenu.CheckboxItem checked={false} onCheckedChange={onChange}>
            Bookmark
          </DropdownMenu.CheckboxItem>
        </DropdownMenu.Content>
      </DropdownMenu>
    ));
    fireEvent.click(screen.getByRole("menuitemcheckbox"));
    expect(onChange).toHaveBeenCalledWith(true);
  });

  it("RadioItem selects", () => {
    const onChange = vi.fn();
    render(() => (
      <DropdownMenu defaultOpen>
        <DropdownMenu.Trigger>Actions</DropdownMenu.Trigger>
        <DropdownMenu.Content>
          <DropdownMenu.RadioGroup value="list" onValueChange={onChange}>
            <DropdownMenu.RadioItem value="list">List</DropdownMenu.RadioItem>
            <DropdownMenu.RadioItem value="grid">Grid</DropdownMenu.RadioItem>
          </DropdownMenu.RadioGroup>
        </DropdownMenu.Content>
      </DropdownMenu>
    ));
    fireEvent.click(screen.getAllByRole("menuitemradio")[1]);
    expect(onChange).toHaveBeenCalledWith("grid");
  });
});
