import { useState } from "react";

import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";

import { Button } from "./button";
import {
  Command,
  CommandDialog,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
  CommandSeparator,
  CommandShortcut
} from "./command";

describe("Command", () => {
  it("renders root, input, list, item, and shortcut slots", async () => {
    const user = userEvent.setup();

    render(
      <Command label="Quick actions">
        <CommandInput placeholder="Search actions" />
        <CommandList>
          <CommandEmpty>No results.</CommandEmpty>
          <CommandGroup heading="Actions">
            <CommandItem value="launch-release">Launch release</CommandItem>
            <CommandItem value="open-legal">
              Open legal review
              <CommandShortcut>G L</CommandShortcut>
            </CommandItem>
          </CommandGroup>
          <CommandSeparator />
        </CommandList>
      </Command>
    );

    const root = document.querySelector('[data-slot="root"]');
    const input = screen.getByPlaceholderText("Search actions");

    expect(root).toHaveAttribute("data-slot", "root");
    expect(input).toHaveAttribute("data-slot", "input");
    expect(document.querySelector('[data-slot="list"]')).toBeInTheDocument();
    expect(screen.getByText("Open legal review").closest('[data-slot="item"]')).toBeInTheDocument();
    expect(screen.getByText("G L")).toHaveAttribute("data-slot", "shortcut");

    await user.type(input, "zzz");
    expect(await screen.findByText("No results.")).toHaveAttribute("data-slot", "empty");
  });

  it("calls onSelect when a command item is chosen", async () => {
    const user = userEvent.setup();
    const onSelect = vi.fn();

    render(
      <Command>
        <CommandInput placeholder="Search actions" />
        <CommandList>
          <CommandItem onSelect={onSelect} value="launch-release">
            Launch release
          </CommandItem>
        </CommandList>
      </Command>
    );

    await user.click(screen.getByText("Launch release"));

    expect(onSelect).toHaveBeenCalledWith("launch-release");
  });

  it("renders inside a dialog and closes through the default close control", async () => {
    const user = userEvent.setup();

    function CommandDialogExample() {
      const [open, setOpen] = useState(true);

      return (
        <CommandDialog onOpenChange={setOpen} open={open}>
          <CommandInput placeholder="Search across workspace" />
          <CommandList>
            <CommandItem value="open-docs">Open docs</CommandItem>
          </CommandList>
        </CommandDialog>
      );
    }

    render(<CommandDialogExample />);

    expect(screen.getByPlaceholderText("Search across workspace")).toBeInTheDocument();

    await user.click(screen.getByRole("button", { name: "Close dialog" }));

    await waitFor(() => {
      expect(screen.queryByPlaceholderText("Search across workspace")).not.toBeInTheDocument();
    });
  });

  it("supports loading and footer content on the root command surface", async () => {
    render(
      <Command
        footer={<Button size="sm">Manage commands</Button>}
        label="Workspace palette"
        loading
        loadingMessage="Searching workspace…"
      >
        <CommandInput placeholder="Search workspace" />
        <CommandList>
          <CommandEmpty>No matching items.</CommandEmpty>
        </CommandList>
      </Command>
    );

    expect(screen.getByText("Searching workspace…")).toHaveAttribute("data-slot", "loading");
    expect(screen.getByText("Manage commands")).toBeInTheDocument();
  });

  it("supports dialog title, description, and footer actions for a practical palette shell", async () => {
    const user = userEvent.setup();

    function CommandDialogExample() {
      const [open, setOpen] = useState(true);

      return (
        <CommandDialog
          description="Jump to docs, recent launches, and operational shortcuts."
          footer={<Button size="sm">Manage shortcuts</Button>}
          onOpenChange={setOpen}
          open={open}
          title="Workspace command palette"
        >
          <CommandInput placeholder="Search across workspace" />
          <CommandList>
            <CommandGroup heading="Recent">
              <CommandItem value="recent-release">Recent release brief</CommandItem>
            </CommandGroup>
          </CommandList>
        </CommandDialog>
      );
    }

    render(<CommandDialogExample />);

    expect(screen.getByText("Workspace command palette")).toBeInTheDocument();
    expect(screen.getByText("Jump to docs, recent launches, and operational shortcuts.")).toBeInTheDocument();
    expect(screen.getByText("Manage shortcuts")).toBeInTheDocument();

    await user.click(screen.getByRole("button", { name: "Close dialog" }));

    await waitFor(() => {
      expect(screen.queryByText("Workspace command palette")).not.toBeInTheDocument();
    });
  });
});
