import { describe, test, expect, vi, afterEach } from 'vitest';
import React from 'react';
import { createRoot, Root } from 'react-dom/client';
import { act } from 'react-dom/test-utils';
import { HeadCodeModal } from './HeadCodeModal';
import { SiteDesignProvider, useSiteDesign } from '../../state/SiteDesignContext';

/* ---------- DOM test harness -- same react-dom/client + `act` pattern used
   throughout src/ui/*.test.tsx (no @testing-library/react in this repo). ---------- */
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);
  });
}

afterEach(() => {
  if (container) {
    act(() => { root.unmount(); });
    container.remove();
  }
  document.body.style.overflow = '';
});

// Exposes the current headCode so assertions can read it back after a
// simulated edit -- CodeEditor writes through `updateDesign`, this just
// surfaces the result.
function Harness({ onReady }: { onReady: (headCode: string) => void }) {
  const { design } = useSiteDesign();
  onReady(design.headCode);
  return null;
}

describe('HeadCodeModal', () => {
  // HeadCodeModal portals its content to document.body (see the comment in
  // HeadCodeModal.tsx), so the rendered DOM lives outside `container` --
  // query document.body instead.

  test('renders the CodeEditor (fallback textarea path) seeded with the current headCode', () => {
    render(
      <SiteDesignProvider>
        <HeadCodeModal open onClose={vi.fn()} />
      </SiteDesignProvider>,
    );
    // CodeMirror loads via async dynamic import (see CodeEditor.test.tsx);
    // synchronously after mount the fallback textarea is what's live.
    const textarea = document.body.querySelector<HTMLTextAreaElement>('[data-testid="code-editor-fallback"]');
    expect(textarea).not.toBeNull();
    expect(textarea!.value).toBe('');
    expect(textarea!.dataset.language).toBe('html');
  });

  test('typing in the editor writes through to SiteDesignContext.headCode', () => {
    let latestHeadCode = '';
    render(
      <SiteDesignProvider>
        <HeadCodeModal open onClose={vi.fn()} />
        <Harness onReady={(v) => { latestHeadCode = v; }} />
      </SiteDesignProvider>,
    );

    const textarea = document.body.querySelector<HTMLTextAreaElement>('[data-testid="code-editor-fallback"]')!;
    act(() => {
      const setter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value')!.set!;
      setter.call(textarea, '<meta name="x" content="y">');
      textarea.dispatchEvent(new Event('input', { bubbles: true }));
    });

    expect(latestHeadCode).toBe('<meta name="x" content="y">');
  });

  test('does not render when closed', () => {
    render(
      <SiteDesignProvider>
        <HeadCodeModal open={false} onClose={vi.fn()} />
      </SiteDesignProvider>,
    );
    expect(document.body.querySelector('[data-testid="code-editor-fallback"]')).toBeNull();
  });
});
