import { render, screen } from '@testing-library/react';
import { userEvent } from '@testing-library/user-event';

import Tooltip from '.';

describe('Tooltip Component', () => {
  it('renders an empty list when no items are passed', () => {
    expect(
      render(
        <Tooltip label="Test Tooltip">
          <span>Hover me</span>
        </Tooltip>,
      ).container,
    ).toMatchSnapshot();
  });

  it('initially is hidden (test with toBeInTheDocument)', () => {
    render(
      <Tooltip label="Test Tooltip">
        <span>Hover me</span>
      </Tooltip>,
    );
    const tooltip = screen.getByRole('tooltip', { hidden: true });
    expect(tooltip).toBeInTheDocument();
    expect(tooltip).toHaveAttribute('aria-hidden', 'true');
  });

  it('should render the tooltip label when closed', async () => {
    render(
      <Tooltip label="Test Tooltip">
        <span>Hover me</span>
      </Tooltip>,
    );
    const triggerElement = screen.getByText('Hover me');
    const tooltip = screen.getByRole('tooltip', { hidden: true });
    expect(tooltip).toHaveAttribute('aria-hidden', 'true');

    await userEvent.hover(triggerElement);
    expect(tooltip).toHaveAttribute('aria-hidden', 'false');
  });

  it('should display the tooltip on mouse hover', async () => {
    render(
      <Tooltip label="Test Tooltip">
        <span>Hover over me!</span>
      </Tooltip>,
    );
    const triggerElement = screen.getByText('Hover over me!');

    await userEvent.hover(triggerElement);

    const tooltipElement = screen.queryByText('Test Tooltip');
    expect(tooltipElement).toBeVisible();
  });

  it('should hide the tooltip on mouse out', async () => {
    render(
      <Tooltip label="Test Tooltip">
        <span>Hover me</span>
      </Tooltip>,
    );
    const triggerElement = screen.getByText('Hover me');

    await userEvent.hover(triggerElement);
    let tooltipElement = screen.getByText('Test Tooltip');
    expect(tooltipElement).toBeVisible();

    await userEvent.unhover(triggerElement);
    tooltipElement = screen.getByRole('tooltip', { hidden: true });
    expect(tooltipElement).toHaveAttribute('aria-hidden', 'true');
  });

  it('should display the tooltip on focus', async () => {
    render(
      <Tooltip label="Test Tooltip">
        <span>Focus me</span>
      </Tooltip>,
    );
    const triggerElement = screen.getByText('Focus me');

    await userEvent.tab();
    const tooltipElement = screen.getByText('Test Tooltip');
    expect(tooltipElement).toBeVisible();
  });

  it('should hide the tooltip on blur', async () => {
    render(
      <Tooltip label="Test Tooltip">
        <span>Focus me</span>
      </Tooltip>,
    );
    const triggerElement = screen.getByText('Focus me');

    await userEvent.tab();
    let tooltipElement = screen.getByRole('tooltip', { hidden: true });
    expect(tooltipElement).toBeVisible();

    await userEvent.tab({ shift: true }); // Blur the element
    tooltipElement = screen.getByRole('tooltip', { hidden: true });
    expect(tooltipElement).toHaveAttribute('aria-hidden', 'true');
  });

  it('should display the tooltip when the "children" prop is a React element', async () => {
    render(
      <Tooltip label="Test Tooltip">
        <button type="button">Click me</button>
      </Tooltip>,
    );
    const triggerElement = screen.getByText('Click me');

    await userEvent.hover(triggerElement);
    const tooltipElement = screen.getByRole('tooltip', { hidden: true });
    expect(tooltipElement).toBeVisible();
  });
});
