/**
 * <kerf-embed> — Self-contained Web Component for the Kerf vectorization app.
 *
 * Usage:
 *   <kerf-embed engine-url="https://kerf.example.com/engine"></kerf-embed>
 *
 * All styles are isolated inside Shadow DOM. @font-face rules are hoisted
 * to document.head because fonts declared in Shadow DOM don't reliably
 * load cross-browser.
 */

import { createRoot } from 'react-dom/client';
import { StrictMode } from 'react';
import App from './App';
import { setEngineBaseUrl } from './api/engine';

// Vite ?inline imports — CSS is embedded as strings, not injected into <head>
import indexCss from './index.css?inline';
import appCss from './App.css?inline';

/**
 * Extract @font-face blocks from a CSS string.
 * Returns [fontFaceRules, remainingCss].
 */
function extractFontFaces(css: string): [string, string] {
  const fontFaceBlocks: string[] = [];
  // Match @font-face { ... } — handles nested braces safely enough for our case
  const regex = /@font-face\s*\{[^}]*\}/g;
  let remaining = css;
  let match: RegExpExecArray | null;
  while ((match = regex.exec(css)) !== null) {
    fontFaceBlocks.push(match[0]);
  }
  remaining = css.replace(regex, '').trim();
  return [fontFaceBlocks.join('\n'), remaining];
}

/**
 * Rewrite `:root` selectors to `:host` so CSS custom properties work
 * inside Shadow DOM.
 */
function rewriteRootToHost(css: string): string {
  return css.replace(/:root/g, ':host');
}

/** Inject @font-face rules into document.head (idempotent). */
function injectFontFaces(fontFaceCss: string): void {
  if (!fontFaceCss.trim()) return;
  const id = 'kerf-embed-fonts';
  if (document.getElementById(id)) return;
  const style = document.createElement('style');
  style.id = id;
  style.textContent = fontFaceCss;
  document.head.appendChild(style);
}

class KerfEmbed extends HTMLElement {
  private _root: ReturnType<typeof createRoot> | null = null;

  connectedCallback(): void {
    // Read configurable engine URL before any rendering
    const engineUrl = this.getAttribute('engine-url');
    if (engineUrl) {
      setEngineBaseUrl(engineUrl);
    }

    // Attach open Shadow DOM
    const shadow = this.attachShadow({ mode: 'open' });

    // Process App.css: extract @font-face → document.head, rest → shadow
    const [fontFaceCss, appCssClean] = extractFontFaces(appCss);
    injectFontFaces(fontFaceCss);

    // Rewrite :root → :host for index.css custom properties
    const indexCssRewritten = rewriteRootToHost(indexCss);

    // Inject all styles into shadow root
    const styleEl = document.createElement('style');
    styleEl.textContent = `
${indexCssRewritten}
${appCssClean}

/* Embed-specific overrides */
:host {
  display: block;
  width: 100%;
  box-sizing: border-box;
}
`;
    shadow.appendChild(styleEl);

    // Create mount point
    const mountDiv = document.createElement('div');
    mountDiv.id = 'root';
    shadow.appendChild(mountDiv);

    // Mount React app
    this._root = createRoot(mountDiv);
    this._root.render(
      <StrictMode>
        <App />
      </StrictMode>,
    );
  }

  disconnectedCallback(): void {
    // Clean up React root on removal
    if (this._root) {
      this._root.unmount();
      this._root = null;
    }
  }
}

// Register the custom element (guard against double-registration)
if (!customElements.get('kerf-embed')) {
  customElements.define('kerf-embed', KerfEmbed);
}

export { KerfEmbed };
