import { act, render, screen } from '@testing-library/react';
import { WDS_LIVE_REGION_DELAY_MS } from '../constants';
import { LiveRegion, LiveRegionProps, resetLiveRegionAnnouncementQueue } from './LiveRegion';

describe('LiveRegion', () => {
  beforeEach(() => {
    jest.useFakeTimers();
    resetLiveRegionAnnouncementQueue();
  });

  afterEach(() => {
    jest.clearAllTimers();
    jest.useRealTimers();
  });

  const renderLiveRegion = (props: Partial<LiveRegionProps> & Pick<LiveRegionProps, 'aria-live'>) =>
    render(<LiveRegion {...props}>{props.children ?? 'Live content'}</LiveRegion>);

  const enableLiveRegion = (delay = WDS_LIVE_REGION_DELAY_MS) => {
    act(() => {
      jest.advanceTimersByTime(delay);
    });
  };

  describe('when aria-live is "polite"', () => {
    it('renders with role="status"', () => {
      renderLiveRegion({ 'aria-live': 'polite' });
      enableLiveRegion();
      expect(screen.getByRole('status')).toBeInTheDocument();
    });

    it('sets aria-live="polite"', () => {
      renderLiveRegion({ 'aria-live': 'polite' });
      enableLiveRegion();
      expect(screen.getByRole('status')).toHaveAttribute('aria-live', 'polite');
    });

    it('sets aria-atomic="true"', () => {
      renderLiveRegion({ 'aria-live': 'polite' });
      enableLiveRegion();
      expect(screen.getByRole('status')).toHaveAttribute('aria-atomic', 'true');
    });
  });

  describe('when aria-live is "assertive"', () => {
    it('renders with role="alert"', () => {
      renderLiveRegion({ 'aria-live': 'assertive' });
      enableLiveRegion();
      expect(screen.getByRole('alert')).toBeInTheDocument();
    });

    it('sets aria-live="assertive"', () => {
      renderLiveRegion({ 'aria-live': 'assertive' });
      enableLiveRegion();
      expect(screen.getByRole('alert')).toHaveAttribute('aria-live', 'assertive');
    });

    it('sets aria-atomic="true"', () => {
      renderLiveRegion({ 'aria-live': 'assertive' });
      enableLiveRegion();
      expect(screen.getByRole('alert')).toHaveAttribute('aria-atomic', 'true');
    });
  });

  it('delays live-region activation before the configured timeout', () => {
    renderLiveRegion({ 'aria-live': 'polite', children: 'Delayed content' });

    const liveRegion = screen.getByRole('status');
    expect(liveRegion).toBeInTheDocument();
    expect(liveRegion.firstElementChild).toHaveAttribute('aria-hidden', 'true');

    enableLiveRegion(WDS_LIVE_REGION_DELAY_MS - 1);
    expect(liveRegion.firstElementChild).toHaveAttribute('aria-hidden', 'true');

    enableLiveRegion(1);
    expect(liveRegion.firstElementChild).not.toHaveAttribute('aria-hidden');
    expect(liveRegion).toHaveTextContent('Delayed content');
  });

  it('queues multiple assertive regions so each one gets announced', () => {
    render(
      <>
        <LiveRegion aria-live="assertive">First prompt</LiveRegion>
        <LiveRegion aria-live="assertive">Second prompt</LiveRegion>
      </>,
    );

    const liveRegions = screen.getAllByRole('alert');
    expect(liveRegions).toHaveLength(2);
    expect(liveRegions[0].firstElementChild).toHaveAttribute('aria-hidden', 'true');
    expect(liveRegions[1].firstElementChild).toHaveAttribute('aria-hidden', 'true');

    enableLiveRegion();
    const firstEnabledLiveRegions = screen.getAllByRole('alert');
    expect(firstEnabledLiveRegions[0].firstElementChild).not.toHaveAttribute('aria-hidden');
    expect(firstEnabledLiveRegions[1].firstElementChild).toHaveAttribute('aria-hidden', 'true');
    expect(firstEnabledLiveRegions[0]).toHaveTextContent('First prompt');

    enableLiveRegion();
    const secondEnabledLiveRegions = screen.getAllByRole('alert');
    expect(secondEnabledLiveRegions[1].firstElementChild).not.toHaveAttribute('aria-hidden');
    expect(secondEnabledLiveRegions[0]).toHaveTextContent('First prompt');
    expect(secondEnabledLiveRegions[1]).toHaveTextContent('Second prompt');
  });

  it('renders children', () => {
    renderLiveRegion({ 'aria-live': 'polite', children: 'Transfer sent' });
    enableLiveRegion();
    expect(screen.getByText('Transfer sent')).toBeInTheDocument();
  });

  it('passes additional HTML attributes to the wrapper div', () => {
    renderLiveRegion({ 'aria-live': 'polite', className: 'custom' });
    enableLiveRegion();
    expect(screen.getByRole('status')).toHaveClass('custom');
  });

  it('supports data-testid prop', () => {
    renderLiveRegion({ 'aria-live': 'polite', 'data-testid': 'live-region' });
    enableLiveRegion();
    expect(screen.getByTestId('live-region')).toBeInTheDocument();
  });
});
