// src/widgets/R51CockpitMount/R51CockpitMount.jsx · Wave κ-4
//
// IIFE mount harness for the 4 R51 widgets bundled in `dist/v3-r51-widgets.js`
// (built by `scripts/build-r51-widgets.mjs`). Self-mounts when the URL
// `?screen=` parameter matches one of the known R51 screens.
//
// Why this exists
// ---------------
// Waves ε/ζ shipped 4 widgets as ES modules with `export default`. The cockpit
// shell (`index.html` + `src/app/App.jsx`) loads widgets via `<script src=...>`
// tags that depend on the IIFE + `window.X` pattern. Module-style widgets
// therefore never reached the browser even though their ci-local gates passed.
// Wave κ-2 closed the bundle gap; this file closes the mount gap.
//
// Screens
// -------
// `?screen=recommendations`  → window.R51Widgets.RecommendationsInbox
// `?screen=inference-health` → window.R51Widgets.InferenceHealthDashboard
// `?screen=sources`          → window.R51Widgets.SourceConnectorModal
//
// HydratorBadge is a primitive (composed by other widgets), not URL-routed.
//
// File extension is .jsx for convention only — the body is plain ES5+ with
// `React.createElement` calls (matches SyntheticDomainsPanel pattern), so the
// browser executes the file directly without transpilation. preview-v3.mjs
// serves it as text/javascript.

(function () {
  'use strict';

  if (typeof window === 'undefined') return;
  if (window.__R51CockpitMountInstalled) return;
  window.__R51CockpitMountInstalled = true;

  var SCREEN_MAP = {
    'recommendations': 'RecommendationsInbox',
    'inference-health': 'InferenceHealthDashboard',
    'sources': 'SourceConnectorModal',
  };

  var PORTAL_ID = 'xcp-r51-cockpit-portal';
  var LAUNCHER_ID = 'xcp-r51-cockpit-launcher';
  var LAUNCHER_DISABLED_GLOBAL = '__XCP_R51_LAUNCHER_DISABLED';

  // Wave κ-tail-2: floating launcher so the operator can discover the 3 R51
  // screens without typing URL params. Bottom-right corner · idle when no
  // screen is selected · self-hides when a screen IS selected (header
  // already provides the close button). Opt-out: set
  // window.__XCP_R51_LAUNCHER_DISABLED = true before this script loads.
  function ensureLauncher() {
    if (typeof window === 'undefined') return;
    if (window[LAUNCHER_DISABLED_GLOBAL]) return;
    // Hide when a screen is rendered (would overlap the screen's own header).
    if (readScreen()) {
      var existing = document.getElementById(LAUNCHER_ID);
      if (existing) existing.style.display = 'none';
      return;
    }
    var node = document.getElementById(LAUNCHER_ID);
    if (node) {
      node.style.display = 'block';
      return;
    }
    if (!document.body) return;
    node = document.createElement('div');
    node.id = LAUNCHER_ID;
    node.setAttribute('data-r51-launcher', '1');
    node.style.cssText = [
      'position:fixed', 'right:18px', 'bottom:18px', 'z-index:99986',
      'pointer-events:auto', 'font-family:Geist, -apple-system, system-ui, sans-serif',
    ].join(';');

    var open = false;
    function paint() {
      node.innerHTML = '';
      var btn = document.createElement('button');
      btn.type = 'button';
      btn.setAttribute('aria-label', open ? 'Close R51 cockpit launcher' : 'Open R51 cockpit launcher');
      btn.setAttribute('aria-expanded', open ? 'true' : 'false');
      btn.style.cssText = [
        'background:linear-gradient(135deg,rgba(48,72,120,0.92),rgba(28,40,72,0.92))',
        'color:#fff', 'border:1px solid rgba(255,255,255,0.16)', 'border-radius:999px',
        'padding:10px 16px', 'font-size:12px', 'font-weight:600', 'letter-spacing:0.02em',
        'cursor:pointer', 'box-shadow:0 6px 22px rgba(0,0,0,0.32)',
        'display:flex', 'align-items:center', 'gap:8px',
      ].join(';');
      btn.textContent = open ? '× R51 · LEM-v4' : '◉ R51 · LEM-v4';
      btn.onclick = function () {
        open = !open;
        paint();
      };
      node.appendChild(btn);
      if (open) {
        var menu = document.createElement('div');
        menu.setAttribute('role', 'menu');
        menu.setAttribute('aria-label', 'R51 cockpit screens');
        menu.style.cssText = [
          'margin-top:8px', 'background:rgba(10,12,20,0.96)',
          'border:1px solid rgba(255,255,255,0.12)', 'border-radius:10px',
          'padding:6px', 'min-width:220px',
          'box-shadow:0 14px 40px rgba(0,0,0,0.5)',
          'backdrop-filter:blur(8px)',
        ].join(';');
        var items = [
          { screen: 'recommendations',  label: 'Recommendations inbox',  hint: 'LEM-v4 · CES · accept/reject' },
          { screen: 'inference-health', label: 'Inference health',       hint: '6-panel cockpit · auto-refresh' },
          { screen: 'sources',          label: 'Connect a source',       hint: '8 OAuth providers · 3 free-tier' },
        ];
        items.forEach(function (it) {
          var row = document.createElement('button');
          row.type = 'button';
          row.setAttribute('role', 'menuitem');
          row.style.cssText = [
            'display:block', 'width:100%', 'text-align:left',
            'background:transparent', 'color:#fff',
            'border:none', 'padding:10px 12px', 'border-radius:8px',
            'cursor:pointer', 'font-size:13px', 'line-height:1.4',
          ].join(';');
          row.onmouseenter = function () { row.style.background = 'rgba(80,120,200,0.18)'; };
          row.onmouseleave = function () { row.style.background = 'transparent'; };
          var title = document.createElement('div');
          title.textContent = it.label;
          title.style.fontWeight = '600';
          var hint = document.createElement('div');
          hint.textContent = it.hint;
          hint.style.cssText = 'opacity:0.55;font-size:11px;margin-top:2px;font-family:JetBrains Mono, ui-monospace, monospace';
          row.appendChild(title);
          row.appendChild(hint);
          row.onclick = function () {
            try {
              var u = new URL(window.location.href);
              u.searchParams.set('screen', it.screen);
              window.history.pushState({}, '', u.toString());
              open = false;
              render(); // mounts the portal
            } catch (e) { void e; }
          };
          menu.appendChild(row);
        });
        node.appendChild(menu);
      }
    }
    paint();
    document.body.appendChild(node);
  }

  function readScreen() {
    try {
      var params = new URLSearchParams(window.location.search);
      var s = (params.get('screen') || '').toLowerCase();
      return SCREEN_MAP[s] ? s : null;
    } catch (e) {
      void e;
      return null;
    }
  }

  function getOrCreatePortal() {
    var existing = document.getElementById(PORTAL_ID);
    if (existing) return existing;
    var div = document.createElement('div');
    div.id = PORTAL_ID;
    div.setAttribute('data-r51-cockpit-mount', '1');
    div.style.cssText = 'position:fixed;inset:0;z-index:99987;pointer-events:auto;overflow:auto;background:rgba(8,10,16,0.96);';
    document.body.appendChild(div);
    return div;
  }

  function removePortal() {
    var p = document.getElementById(PORTAL_ID);
    if (p && p.parentNode) p.parentNode.removeChild(p);
  }

  var currentRoot = null;
  var currentScreen = null;

  function render() {
    ensureLauncher();
    var screen = readScreen();
    if (!screen) {
      if (currentRoot) {
        try { currentRoot.unmount(); } catch (e) { void e; }
        currentRoot = null;
        currentScreen = null;
      }
      removePortal();
      return;
    }

    if (!window.React || !window.ReactDOM) return;
    if (!window.R51Widgets) {
      console.warn('[R51CockpitMount] window.R51Widgets not loaded — bundle missing?');
      return;
    }

    var widgetName = SCREEN_MAP[screen];
    var Widget = window.R51Widgets[widgetName];
    if (!Widget) {
      console.warn('[R51CockpitMount] widget not registered: ' + widgetName);
      return;
    }

    // Idempotent: if same screen already rendered, no-op.
    if (currentScreen === screen && currentRoot) return;

    var portal = getOrCreatePortal();
    if (currentRoot) {
      try { currentRoot.unmount(); } catch (e) { void e; }
      currentRoot = null;
    }
    portal.innerHTML = '';

    var React = window.React;
    var ReactDOM = window.ReactDOM;

    if (!ReactDOM.createRoot) {
      // React 17 fallback (codebase pins 18, but defensive).
      try {
        ReactDOM.render(
          React.createElement(Shell, { widgetName: widgetName, Widget: Widget }),
          portal,
        );
      } catch (e) {
        console.error('[R51CockpitMount] render failed', e);
      }
      currentScreen = screen;
      return;
    }

    currentRoot = ReactDOM.createRoot(portal);
    currentRoot.render(
      React.createElement(Shell, { widgetName: widgetName, Widget: Widget }),
    );
    currentScreen = screen;
  }

  // Shell adds a header bar with a close button (?screen= cleared) so the
  // operator never feels trapped on a panel.
  function Shell(props) {
    var React = window.React;
    return React.createElement(
      'div',
      {
        style: {
          width: '100%', minHeight: '100%', display: 'flex', flexDirection: 'column',
          color: 'var(--fg-1, rgba(255,255,255,0.96))',
          fontFamily: 'Geist, -apple-system, system-ui, sans-serif',
        },
        'data-r51-screen': props.widgetName,
      },
      React.createElement(
        'header',
        {
          style: {
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            padding: '14px 18px', borderBottom: '1px solid rgba(255,255,255,0.08)',
            background: 'rgba(8,10,16,0.92)', backdropFilter: 'blur(8px)',
            position: 'sticky', top: 0, zIndex: 1,
          },
        },
        React.createElement(
          'div',
          { style: { display: 'flex', alignItems: 'center', gap: 12 } },
          React.createElement(
            'span',
            {
              style: {
                fontSize: 11, fontFamily: 'JetBrains Mono, ui-monospace, monospace',
                opacity: 0.6, textTransform: 'uppercase', letterSpacing: '0.08em',
              },
            },
            'R51 · LEM-v4 cockpit',
          ),
          React.createElement(
            'span',
            { style: { fontSize: 16, fontWeight: 600 } },
            props.widgetName,
          ),
        ),
        React.createElement(
          'button',
          {
            type: 'button',
            'aria-label': 'Close R51 cockpit panel',
            onClick: function () {
              try {
                var url = new URL(window.location.href);
                url.searchParams.delete('screen');
                window.history.pushState({}, '', url.toString());
                render();
              } catch (e) {
                void e;
                window.location.search = '';
              }
            },
            style: {
              background: 'transparent', border: '1px solid rgba(255,255,255,0.16)',
              color: 'inherit', padding: '6px 12px', borderRadius: 6,
              fontSize: 12, cursor: 'pointer',
            },
          },
          '× Close',
        ),
      ),
      React.createElement(
        'main',
        { style: { flex: 1, padding: '20px 24px', overflowY: 'auto' } },
        // Pass `open: true` + a no-op onClose for modal-shaped widgets
        // (SourceConnectorModal). Non-modal widgets ignore these props.
        // Close routes through the header button instead.
        React.createElement(props.Widget, { open: true, isOpen: true, onClose: function () {} }),
      ),
    );
  }

  function install() {
    if (window.React && window.ReactDOM) {
      render();
    } else {
      // Wait for React UMD to finish loading.
      var t = setInterval(function () {
        if (window.React && window.ReactDOM) {
          clearInterval(t);
          render();
        }
      }, 50);
      setTimeout(function () { clearInterval(t); }, 8000);
    }

    // React to URL changes.
    window.addEventListener('popstate', render);
    // pushState/replaceState don't fire popstate — patch them to dispatch.
    if (!window.__r51PushStatePatched) {
      window.__r51PushStatePatched = true;
      var origPush = window.history.pushState.bind(window.history);
      var origReplace = window.history.replaceState.bind(window.history);
      window.history.pushState = function () {
        var r = origPush.apply(null, arguments);
        try { window.dispatchEvent(new Event('xcp:url-change')); } catch (e) { void e; }
        return r;
      };
      window.history.replaceState = function () {
        var r = origReplace.apply(null, arguments);
        try { window.dispatchEvent(new Event('xcp:url-change')); } catch (e) { void e; }
        return r;
      };
    }
    window.addEventListener('xcp:url-change', render);

    // Re-render once the R51 widget bundle finishes loading.
    if (!window.R51Widgets) {
      var bundleTimer = setInterval(function () {
        if (window.R51Widgets) {
          clearInterval(bundleTimer);
          render();
        }
      }, 50);
      setTimeout(function () { clearInterval(bundleTimer); }, 8000);
    }
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', install, { once: true });
  } else {
    install();
  }
})();
