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

import {
  Tooltip,
  TooltipArrow,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger
} from "./tooltip";

describe("Tooltip", () => {
  it("shows and hides tooltip content around hover", async () => {
    const user = userEvent.setup();

    render(
      <TooltipProvider delayDuration={0} disableHoverableContent>
        <Tooltip>
          <TooltipTrigger>Help</TooltipTrigger>
          <TooltipContent size="lg">
            Helpful context
            <TooltipArrow />
          </TooltipContent>
        </Tooltip>
      </TooltipProvider>
    );

    await user.hover(screen.getByRole("button", { name: "Help" }));

    const tooltip = await screen.findByRole("tooltip");
    const content = tooltip.closest('[data-slot="content"]');

    expect(content).toHaveAttribute("data-size", "lg");
    expect(document.querySelector('[data-slot="arrow"]')).toBeInTheDocument();

    await user.unhover(screen.getByRole("button", { name: "Help" }));
    await waitFor(() => {
      expect(screen.queryByRole("tooltip")).not.toBeInTheDocument();
    });
  });

  it("reports controlled open changes from the trigger", async () => {
    const user = userEvent.setup();
    const onOpenChange = vi.fn();

    render(
      <TooltipProvider delayDuration={0}>
        <Tooltip open={false} onOpenChange={onOpenChange}>
          <TooltipTrigger>Help</TooltipTrigger>
          <TooltipContent>Helpful context</TooltipContent>
        </Tooltip>
      </TooltipProvider>
    );

    await user.hover(screen.getByRole("button", { name: "Help" }));

    await waitFor(() => {
      expect(onOpenChange).toHaveBeenCalledWith(true);
    });
  });

  it("shows tooltip content on focus and hides it on blur", async () => {
    render(
      <TooltipProvider delayDuration={0}>
        <Tooltip>
          <TooltipTrigger>Focus help</TooltipTrigger>
          <TooltipContent>Focus context</TooltipContent>
        </Tooltip>
      </TooltipProvider>
    );

    const trigger = screen.getByRole("button", { name: "Focus help" });

    trigger.focus();

    const tooltip = await screen.findByRole("tooltip");

    expect(tooltip).toHaveTextContent("Focus context");
    expect(trigger).toHaveFocus();

    trigger.blur();

    await waitFor(() => {
      expect(screen.queryByRole("tooltip")).not.toBeInTheDocument();
    });
  });
});
