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

import { Button } from "./button";
import { setReducedMotionPreference } from "../test/a11y";

describe("Button", () => {
  it("renders a native button with root and label slots", () => {
    render(<Button variant="secondary">Save changes</Button>);

    const button = screen.getByRole("button", { name: "Save changes" });

    expect(button).toHaveAttribute("data-slot", "root");
    expect(button).toHaveAttribute("data-variant", "secondary");
    expect(button).toHaveAttribute("type", "button");
    expect(screen.getByText("Save changes")).toHaveAttribute("data-slot", "label");
  });

  it("disables interaction and exposes loading hooks when loading", async () => {
    const user = userEvent.setup();
    const onClick = vi.fn();

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

    const button = screen.getByRole("button", { name: "Saving" });

    await user.click(button);

    expect(button).toBeDisabled();
    expect(button).toHaveAttribute("data-loading", "");
    expect(button.querySelector('[data-slot="icon"]')).toBeInTheDocument();
    expect(onClick).not.toHaveBeenCalled();
  });

  it("supports asChild rendering without forcing button semantics", () => {
    render(
      <Button asChild variant="ghost">
        <a href="/release-notes">Release notes</a>
      </Button>
    );

    const link = screen.getByRole("link", { name: "Release notes" });

    expect(link).toHaveAttribute("data-slot", "root");
    expect(link).toHaveAttribute("data-variant", "ghost");
    expect(link).not.toHaveAttribute("type");
  });

  it("preserves the loading contract when reduced motion is preferred", () => {
    setReducedMotionPreference(true);

    render(<Button loading>Saving</Button>);

    const button = screen.getByRole("button", { name: "Saving" });

    expect(button).toBeDisabled();
    expect(button).toHaveAttribute("data-loading", "");
    expect(button.querySelector('[data-slot="icon"]')).toBeInTheDocument();
  });
});
