import { useState } from "react";

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

import { Switch } from "./switch";

describe("Switch", () => {
  it("toggles by click and exposes slot/state hooks", async () => {
    const user = userEvent.setup();
    const onCheckedChange = vi.fn();

    render(<Switch aria-label="Email alerts" onCheckedChange={onCheckedChange} />);

    const control = screen.getByRole("switch", { name: "Email alerts" });

    expect(control).toHaveAttribute("data-slot", "root");
    expect(control).toHaveAttribute("data-state", "unchecked");
    expect(control.querySelector('[data-slot="control"]')).not.toBeNull();

    await user.click(control);

    expect(control).toBeChecked();
    expect(control).toHaveAttribute("data-state", "checked");
    expect(onCheckedChange).toHaveBeenCalledWith(true);
  });

  it("supports controlled state updates", async () => {
    const user = userEvent.setup();

    function ControlledSwitch() {
      const [checked, setChecked] = useState(false);
      return <Switch aria-label="Controlled switch" checked={checked} onCheckedChange={setChecked} />;
    }

    render(<ControlledSwitch />);

    const control = screen.getByRole("switch", { name: "Controlled switch" });
    expect(control).not.toBeChecked();

    await user.click(control);

    expect(control).toBeChecked();
  });

  it("supports keyboard interaction and disabled/invalid states", async () => {
    const user = userEvent.setup();

    render(
      <>
        <Switch aria-label="Keyboard switch" />
        <Switch aria-label="Disabled switch" disabled invalid />
      </>
    );

    const keyboardSwitch = screen.getByRole("switch", { name: "Keyboard switch" });
    const disabledSwitch = screen.getByRole("switch", { name: "Disabled switch" });

    await user.tab();
    expect(keyboardSwitch).toHaveFocus();

    await user.keyboard(" ");
    expect(keyboardSwitch).toBeChecked();

    expect(disabledSwitch).toBeDisabled();
    expect(disabledSwitch).toHaveAttribute("aria-invalid", "true");
    expect(disabledSwitch).toHaveAttribute("data-disabled", "");
  });
});
