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

describe("Button", () => {
  it("renders a secondary button by default", () => {
    render(<Button>Save</Button>);

    const button = screen.getByRole("button", { name: "Save" });
    expect(button).toHaveAttribute("type", "button");
    expect(button).toBeEnabled();
  });

  it("supports the four visual variants", () => {
    render(
      <>
        <Button variant="primary">Primary</Button>
        <Button variant="secondary">Secondary</Button>
        <Button variant="ghost">Ghost</Button>
        <Button variant="danger">Danger</Button>
      </>
    );

    expect(screen.getByRole("button", { name: "Primary" })).toBeInTheDocument();
    expect(screen.getByRole("button", { name: "Secondary" })).toBeInTheDocument();
    expect(screen.getByRole("button", { name: "Ghost" })).toBeInTheDocument();
    expect(screen.getByRole("button", { name: "Danger" })).toBeInTheDocument();
  });

  it("supports the three size options", () => {
    render(
      <>
        <Button size="sm">Small</Button>
        <Button size="md">Medium</Button>
        <Button size="lg">Large</Button>
      </>
    );

    expect(screen.getByRole("button", { name: "Small" })).toBeInTheDocument();
    expect(screen.getByRole("button", { name: "Medium" })).toBeInTheDocument();
    expect(screen.getByRole("button", { name: "Large" })).toBeInTheDocument();
  });

  it("preserves legacy compatibility classes for migrated callers", () => {
    render(
      <Button variant="primary" size="lg" className="auth-submit">
        Submit
      </Button>
    );

    expect(screen.getByRole("button", { name: "Submit" })).toHaveClass(
      "btn",
      "btn-primary",
      "btn-lg",
      "auth-submit"
    );
  });

  it("disables click handlers while loading", async () => {
    const user = userEvent.setup();
    const onClick = vi.fn();

    render(
      <Button loading onClick={onClick}>
        Create
      </Button>
    );

    const button = screen.getByRole("button", { name: "Create" });
    expect(button).toBeDisabled();
    expect(button).toHaveAttribute("aria-busy", "true");

    await user.click(button);
    expect(onClick).not.toHaveBeenCalled();
  });

  it("calls onClick when enabled", async () => {
    const user = userEvent.setup();
    const onClick = vi.fn();

    render(<Button onClick={onClick}>Run</Button>);

    await user.click(screen.getByRole("button", { name: "Run" }));
    expect(onClick).toHaveBeenCalledTimes(1);
  });

  it("renders leading and trailing icons", () => {
    render(
      <Button
        leadingIcon={<span data-testid="leading-icon">L</span>}
        trailingIcon={<span data-testid="trailing-icon">R</span>}
      >
        Open
      </Button>
    );

    expect(screen.getByTestId("leading-icon")).toBeInTheDocument();
    expect(screen.getByTestId("trailing-icon")).toBeInTheDocument();
    expect(screen.getByRole("button", { name: "Open" })).toBeInTheDocument();
  });

  it("renders as an anchor when as='a'", () => {
    render(
      <Button as="a" href="/settings">
        Settings
      </Button>
    );

    expect(screen.getByRole("link", { name: "Settings" })).toHaveAttribute("href", "/settings");
  });

  it("preserves legacy classes and loading semantics for anchors", () => {
    render(
      <Button as="a" href="/settings" loading variant="ghost" size="sm">
        Settings
      </Button>
    );

    expect(screen.getByRole("link", { name: "Settings" })).toHaveClass(
      "btn",
      "btn-ghost",
      "btn-sm"
    );
    expect(screen.getByRole("link", { name: "Settings" })).toHaveAttribute("aria-busy", "true");
    expect(screen.getByRole("link", { name: "Settings" })).not.toHaveAttribute("disabled");
  });
});
