/** Local mounting and diagnostics only. No telemetry, cookies, storage, or navigation. */
import React, { Component, useEffect } from 'react';
import { createRoot } from 'react-dom/client';
import { ThemeProvider } from './host';

declare global {
  interface Window {
    __STYLEGALLERY_PREVIEW__: { id: string; status: string; errors: string[] };
  }
}

export function mount(Demo: React.ComponentType<any>, id: string, props: object = {}) {
  const state = window.__STYLEGALLERY_PREVIEW__ = { id, status: 'loading', errors: [] as string[] };
  const report = (error: unknown) => {
    const message = error instanceof Error ? error.message : String(error);
    if (!state.errors.includes(message)) state.errors.push(message);
    state.status = 'error';
    document.body.dataset.previewStatus = 'error';
    parent.postMessage({ type: 'sg-preview-error', id, message }, '*');
  };
  window.addEventListener('error', (event) => report(event.error ?? event.message));
  window.addEventListener('unhandledrejection', (event) => report(event.reason));
  document.addEventListener('error', (event) => {
    const node = event.target;
    if (node instanceof HTMLImageElement || node instanceof HTMLVideoElement || node instanceof HTMLSourceElement) {
      parent.postMessage({ type: 'sg-preview-asset-error', id, tag: node.tagName.toLowerCase(), message: 'A preview media asset did not load.' }, '*');
    }
  }, true);
  const observe = () => {
    const root = document.getElementById('root')!;
    const elements = Array.from(root.querySelectorAll('*'));
    const rect = root.getBoundingClientRect();
    const diagnostics = {
      textLength: (root.textContent ?? '').trim().length,
      elementCount: elements.length,
      visibleElementCount: elements.filter((element) => {
        const bounds = element.getBoundingClientRect();
        const style = getComputedStyle(element);
        return bounds.width > 0 && bounds.height > 0 && style.display !== 'none' && style.visibility !== 'hidden' && Number(style.opacity) !== 0;
      }).length,
      images: Array.from(root.querySelectorAll('img')).map((image) => ({ complete: image.complete, naturalWidth: image.naturalWidth, naturalHeight: image.naturalHeight })),
      canvases: Array.from(root.querySelectorAll('canvas')).map((canvas) => {
        const bounds = canvas.getBoundingClientRect();
        return { width: canvas.width, height: canvas.height, rectWidth: bounds.width, rectHeight: bounds.height };
      }),
      rootRect: { width: rect.width, height: rect.height },
      documentWidth: document.documentElement.scrollWidth,
      viewportWidth: innerWidth,
    };
    parent.postMessage({ type: 'sg-preview-observation', id, diagnostics }, '*');
  };
  class Boundary extends Component<{ children: React.ReactNode }, { error: string | null }> {
    state = { error: null as string | null };
    static getDerivedStateFromError(error: Error) { return { error: error.message }; }
    componentDidCatch(error: Error) { report(error); }
    render() { return this.state.error ? <p role="alert">This preview could not render: {this.state.error}</p> : this.props.children; }
  }
  function Ready() {
    useEffect(() => {
      let second = 0;
      let delayed = 0;
      const first = requestAnimationFrame(() => { second = requestAnimationFrame(() => {
        if (state.status !== 'error') {
          state.status = 'mounted';
          document.body.dataset.previewStatus = 'mounted';
          parent.postMessage({ type: 'sg-preview-ready', id }, '*');
          observe();
          delayed = window.setTimeout(observe, 700);
        }
      }); });
      return () => { cancelAnimationFrame(first); cancelAnimationFrame(second); clearTimeout(delayed); };
    }, []);
    return <Demo {...props} />;
  }
  // Preserve demonstration appearance while keeping preview navigation local.
  document.addEventListener('click', (event) => {
    if ((event.target as Element)?.closest?.('a')) event.preventDefault();
  }, true);
  document.addEventListener('submit', (event) => event.preventDefault());
  const removeDestinations = () => document.querySelectorAll('a[href]').forEach((node) => {
    node.removeAttribute('href');
    node.removeAttribute('target');
  });
  new MutationObserver(removeDestinations).observe(document.getElementById('root')!, { childList: true, subtree: true });
  createRoot(document.getElementById('root')!).render(<Boundary><ThemeProvider><Ready /></ThemeProvider></Boundary>);
}
