import { screen, fireEvent, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import { setupReady } from './testHelpers';

describe('screen controls', () => {
  let originalRequestFullscreen;
  let originalExitFullscreen;
  let originalFullscreenElement;
  let originalVisibilityState;
  let originalWakeLock;

  beforeEach(() => {
    localStorage.clear();
    originalRequestFullscreen = document.documentElement.requestFullscreen;
    originalExitFullscreen = document.exitFullscreen;
    originalFullscreenElement = Object.getOwnPropertyDescriptor(document, 'fullscreenElement');
    originalVisibilityState = Object.getOwnPropertyDescriptor(document, 'visibilityState');
    originalWakeLock = Object.getOwnPropertyDescriptor(navigator, 'wakeLock');
  });

  afterEach(() => {
    document.documentElement.requestFullscreen = originalRequestFullscreen;
    document.exitFullscreen = originalExitFullscreen;
    if (originalFullscreenElement) Object.defineProperty(document, 'fullscreenElement', originalFullscreenElement);
    else Object.defineProperty(document, 'fullscreenElement', { configurable: true, value: null });
    if (originalVisibilityState) Object.defineProperty(document, 'visibilityState', originalVisibilityState);
    if (originalWakeLock) Object.defineProperty(navigator, 'wakeLock', originalWakeLock);
    else Object.defineProperty(navigator, 'wakeLock', { configurable: true, value: undefined });
    localStorage.clear();
  });

  test('encounter header exposes prevent-sleep, browser-fullscreen, and popout controls', async () => {
    await setupReady('ScreenCamp', 'ScreenEnc');

    expect(screen.getAllByRole('button', { name: 'Prevent sleep' }).length).toBeGreaterThanOrEqual(2);
    expect(screen.getAllByRole('button', { name: 'Enter browser fullscreen' })).toHaveLength(1);
    expect(screen.getByRole('button', { name: 'Expand encounter to full page' })).toBeInTheDocument();
  });

  test('re-acquires wake lock when tablet becomes visible after browser release', async () => {
    let releaseListener;
    const sentinel = {
      released: false,
      release: jest.fn().mockResolvedValue(undefined),
      addEventListener: jest.fn((event, callback) => { if (event === 'release') releaseListener = callback; }),
    };
    const request = jest.fn().mockResolvedValue(sentinel);
    Object.defineProperty(navigator, 'wakeLock', { configurable: true, value: { request } });
    let visibility = 'visible';
    Object.defineProperty(document, 'visibilityState', { configurable: true, get: () => visibility });

    await setupReady('WakeCamp', 'WakeEnc');
    fireEvent.click(screen.getAllByRole('button', { name: 'Prevent sleep' })[0]);
    await waitFor(() => expect(request).toHaveBeenCalledTimes(1));

    visibility = 'hidden';
    releaseListener();
    visibility = 'visible';
    document.dispatchEvent(new Event('visibilitychange'));

    await waitFor(() => expect(request).toHaveBeenCalledTimes(2));
  });

  test('character editor has labeled tablet-sized save button', async () => {
    await setupReady('SaveCamp', 'SaveEnc');
    fireEvent.change(screen.getByLabelText('Name', { selector: '#characterName' }), { target: { value: 'Tablet Hero' } });
    fireEvent.click(screen.getByRole('button', { name: 'Add Character' }));
    await screen.findByText('Tablet Hero');

    fireEvent.click(screen.getByRole('button', { name: 'Edit character' }));
    const save = screen.getByRole('button', { name: 'Save character' });
    expect(save).toHaveTextContent('Save');
    expect(save).toHaveClass('min-h-[40px]');
  });

  test('attempts to restore fullscreen when tablet becomes visible after lock', async () => {
    const requestFullscreen = jest.fn().mockResolvedValue(undefined);
    document.documentElement.requestFullscreen = requestFullscreen;
    document.exitFullscreen = jest.fn().mockResolvedValue(undefined);
    Object.defineProperty(document, 'fullscreenElement', { configurable: true, get: () => null });
    let visibility = 'visible';
    Object.defineProperty(document, 'visibilityState', { configurable: true, get: () => visibility });

    await setupReady('RestoreCamp', 'RestoreEnc');
    fireEvent.click(screen.getByRole('button', { name: 'Enter browser fullscreen' }));
    await waitFor(() => expect(requestFullscreen).toHaveBeenCalledTimes(1));

    visibility = 'hidden';
    document.dispatchEvent(new Event('fullscreenchange'));
    visibility = 'visible';
    document.dispatchEvent(new Event('visibilitychange'));

    await waitFor(() => expect(requestFullscreen).toHaveBeenCalledTimes(2));
  });
});
