import { describe, test, expect } from 'vitest';
import React from 'react';
import { createRoot, Root } from 'react-dom/client';
import { act } from 'react-dom/test-utils';
import { MobileChromeProvider, useMobileChrome, MobileSheetTab } from './MobileChromeContext';
import { SitesmithProvider, useSitesmithModal } from './SitesmithContext';

/**
 * Mobile-A2 (review item 5): covers the two invariants item 3 depends on --
 * (1) only one sheet is ever open ("tab-bar-always-wins", Phase A's existing
 * behavior, now backed by the shared context instead of a private
 * useState), and (2) opening a sheet closes any open full-screen modal
 * (Templates / Head Code / Sitesmith), so a sheet is never shown stacked
 * underneath one.
 *
 * DOM-harness pattern mirrors PageContext.pure-updaters.test.tsx: bare
 * createRoot + act, a Consumer component that stashes the hook result on an
 * outer variable so assertions can run outside of render.
 */

let container: HTMLDivElement;
let root: Root;

function render(ui: React.ReactElement) {
  container = document.createElement('div');
  document.body.appendChild(container);
  act(() => {
    root = createRoot(container);
    root.render(ui);
  });
}

function unmount() {
  act(() => {
    root.unmount();
  });
  container.remove();
}

let chrome: ReturnType<typeof useMobileChrome> | null = null;
let sitesmith: ReturnType<typeof useSitesmithModal> | null = null;

const Consumer: React.FC = () => {
  chrome = useMobileChrome();
  sitesmith = useSitesmithModal();
  return null;
};

function renderProviders() {
  render(
    <SitesmithProvider>
      <MobileChromeProvider>
        <Consumer />
      </MobileChromeProvider>
    </SitesmithProvider>,
  );
}

describe('MobileChromeContext', () => {
  test('only one sheet is ever open at a time', () => {
    renderProviders();

    act(() => chrome!.openSheet('blocks'));
    expect(chrome!.activeSheet).toBe('blocks');

    // Opening a different sheet replaces the previous one -- never both.
    act(() => chrome!.openSheet('styles'));
    expect(chrome!.activeSheet).toBe('styles');

    act(() => chrome!.closeSheet());
    expect(chrome!.activeSheet).toBeNull();

    unmount();
  });

  test('openSheet is idempotent-safe: opening the same tab twice stays open (caller owns toggle-to-close)', () => {
    renderProviders();

    act(() => chrome!.openSheet('pages'));
    expect(chrome!.activeSheet).toBe('pages');

    act(() => chrome!.openSheet('pages'));
    expect(chrome!.activeSheet).toBe('pages');

    unmount();
  });

  test('openSheet closes an open Templates modal', () => {
    renderProviders();

    act(() => chrome!.setTemplateModalOpen(true));
    expect(chrome!.templateModalOpen).toBe(true);

    act(() => chrome!.openSheet('blocks'));
    expect(chrome!.templateModalOpen).toBe(false);
    expect(chrome!.activeSheet).toBe('blocks');

    unmount();
  });

  test('openSheet closes an open Head Code modal', () => {
    renderProviders();

    act(() => chrome!.setHeadCodeModalOpen(true));
    expect(chrome!.headCodeModalOpen).toBe(true);

    act(() => chrome!.openSheet('assets'));
    expect(chrome!.headCodeModalOpen).toBe(false);
    expect(chrome!.activeSheet).toBe('assets');

    unmount();
  });

  test('openSheet closes an open Sitesmith modal', () => {
    renderProviders();

    act(() => sitesmith!.open());
    expect(sitesmith!.isOpen).toBe(true);

    act(() => chrome!.openSheet('layers'));

    // sitesmith is a stale snapshot from before the re-render the `act`
    // above triggered; re-read via the live ref after settling.
    expect(sitesmith!.isOpen).toBe(false);
    expect(chrome!.activeSheet).toBe('layers');

    unmount();
  });

  test('closeSheet does not disturb modal state', () => {
    renderProviders();

    act(() => chrome!.openSheet('styles'));
    act(() => chrome!.closeSheet());

    expect(chrome!.activeSheet).toBeNull();
    expect(chrome!.templateModalOpen).toBe(false);
    expect(chrome!.headCodeModalOpen).toBe(false);

    unmount();
  });

  test('sheet tabs are exactly the five mobile panels', () => {
    const tabs: MobileSheetTab[] = ['blocks', 'pages', 'layers', 'assets', 'styles'];
    renderProviders();
    tabs.forEach((tab) => {
      act(() => chrome!.openSheet(tab));
      expect(chrome!.activeSheet).toBe(tab);
    });
    unmount();
  });
});
