// components/KnowledgeGapRitual.jsx
//
// Knowledge Gap Surfacing Ritual. End-of-DM-session modal per SCAR-201.
// Fires when user clicks "End session" on /dungeon-master or navigates away.
//
// Displays R1-R7 final scores, Cerebras-inferred self-report (what Morphy
// learned, what Morphy still cannot do well), and persists via Kaitiaki receipt.
//
// SCAR-201: R4 (Morphy Own Learning) is load-bearing. Persist self-report
// even on Cerebras failure (graceful empty learned/gaps).
//
// Wire-in: window.KnowledgeGapRitual = { open, isOpen }
// Babel-standalone React. No import/export.

const { useState, useEffect, useRef, useCallback } = React;

/* ---- Scoped styles ---- */

function KGRStyles() {
  return React.createElement('style', null, `
    .kgr-backdrop {
      position: fixed;
      inset: 0;
      background: rgba(14, 14, 14, 0.5);
      backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
      z-index: 200;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .kgr-modal {
      background: var(--cream-warm, #f9f6f0);
      border: 1px solid rgba(14, 14, 14, 0.06);
      border-radius: var(--radius-lg, 20px);
      max-width: 640px;
      max-height: 90vh;
      overflow-y: auto;
      width: 92%;
      box-shadow: var(--shadow-xl, 0 24px 64px rgba(14, 14, 14, 0.14));
      position: relative;
      font-family: var(--font-body, sans-serif);
      animation: fadeInUp 0.35s cubic-bezier(0.16, 1, 0.3, 1) both;
    }
    .kgr-header {
      padding: 20px 24px;
      padding-right: 52px;
      border-bottom: 1px solid rgba(14, 14, 14, 0.08);
    }
    .kgr-header h2 {
      font-family: var(--font-display, serif);
      font-size: 22px;
      font-weight: 400;
      color: var(--pounamu, #1f8a3a);
      margin: 0;
    }
    .kgr-close {
      position: absolute;
      top: 16px;
      right: 20px;
      background: transparent;
      border: 1px solid rgba(14, 14, 14, 0.08);
      border-radius: var(--radius-sm, 6px);
      color: var(--ng40, #5f5e5a);
      font-size: 16px;
      width: 28px;
      height: 28px;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
      line-height: 1;
      box-shadow: none;
      transition: background 0.15s ease, border-color 0.15s ease;
    }
    .kgr-close:hover {
      background: var(--cream-deep, #ebe7dd);
      border-color: rgba(14, 14, 14, 0.12);
      box-shadow: none;
    }
    .kgr-section {
      padding: 18px 24px;
      border-bottom: 1px solid rgba(14, 14, 14, 0.06);
    }
    .kgr-section:last-child {
      border-bottom: none;
    }
    .kgr-section-title {
      font-size: 14px;
      font-weight: 600;
      color: var(--ng40, #5f5e5a);
      text-transform: uppercase;
      letter-spacing: 0.08em;
      margin: 0 0 12px 0;
    }
    .kgr-list {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    .kgr-item {
      display: flex;
      align-items: center;
      padding: 6px 0;
      font-size: 13px;
    }
    .kgr-item-label {
      flex: 0 0 180px;
      color: var(--ng20, #2c2c2a);
      font-weight: 500;
    }
    .kgr-bar-track {
      flex: 1;
      height: 8px;
      background: var(--cream-deep, #ebe7dd);
      border-radius: 4px;
      overflow: hidden;
      margin: 0 8px;
      border: 1px solid rgba(14, 14, 14, 0.04);
    }
    .kgr-bar-fill {
      height: 100%;
      background: linear-gradient(90deg, var(--pounamu, #1f8a3a), var(--pounamu-deep, #156b2d));
      border-radius: var(--radius-sm, 4px);
      transition: width 0.4s ease;
    }
    .kgr-score-val {
      flex: 0 0 48px;
      text-align: right;
      font-family: var(--font-mono, monospace);
      font-size: 12px;
      color: var(--ng20, #2c2c2a);
    }
    .kgr-item-r4 {
      border-left: 4px solid var(--kowhai, #c4881f);
      background: rgba(196, 136, 31, 0.08);
      padding-left: 8px;
      border-radius: 0 var(--radius-sm, 4px) var(--radius-sm, 4px) 0;
      margin: 4px 0;
    }
    .kgr-text-block {
      min-height: 64px;
      border: 1px solid var(--rule, #cccccc);
      border-radius: var(--radius-sm, 4px);
      padding: 12px;
      background: var(--cream, #f4f1ea);
      color: var(--ng10, #1a1a1a);
      font-size: 14px;
      line-height: 1.6;
      white-space: pre-wrap;
    }
    .kgr-loading {
      display: flex;
      align-items: center;
      gap: 8px;
      color: var(--ng60, #888780);
      font-size: 13px;
      font-style: italic;
    }
    .kgr-spinner {
      display: inline-block;
      width: 14px;
      height: 14px;
      border: 1px solid rgba(14, 14, 14, 0.08);
      border-top-color: var(--pounamu, #1f8a3a);
      border-radius: 50%;
      animation: kgr-spin 0.8s linear infinite;
    }
    @keyframes kgr-spin {
      to { transform: rotate(360deg); }
    }
    .kgr-save-btn {
      width: 100%;
      padding: 12px;
      background: var(--pounamu, #1f8a3a);
      color: var(--cream, #f4f1ea);
      border: none;
      border-radius: var(--radius-sm, 4px);
      font-size: 15px;
      font-weight: 600;
      cursor: pointer;
      transition: opacity 0.15s ease;
    }
    .kgr-save-btn:hover {
      opacity: 0.9;
    }
    .kgr-save-btn:disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }
    .kgr-anon-note {
      font-size: 12px;
      color: var(--ng60, #888780);
      margin-top: 8px;
      padding: 8px 12px;
      background: var(--ng90, #d3d1c7);
      border-radius: var(--radius-sm, 4px);
    }
    .kgr-error {
      font-size: 12px;
      color: #c0392b;
      margin-top: 8px;
    }
  `);
}

/* ---- Score row renderer ---- */

function KGRScoreRow({ label, value, highlight }) {
  const pct = Math.round((value ?? 0) * 100);
  const cls = 'kgr-item' + (highlight ? ' kgr-item-r4' : '');
  return (
    React.createElement('li', { className: cls },
      React.createElement('span', { className: 'kgr-item-label' }, label),
      React.createElement('div', { className: 'kgr-bar-track' },
        React.createElement('div', {
          className: 'kgr-bar-fill',
          style: { width: pct + '%' }
        })
      ),
      React.createElement('span', { className: 'kgr-score-val' }, pct + '%')
    )
  );
}

/* ---- Modal component ---- */

function KnowledgeGapRitualModal({ zoneId, onClose, resolvePromise }) {
  const [scores, setScores] = useState(null);
  const [learned, setLearned] = useState('');
  const [gaps, setGaps] = useState('');
  const [loadingInference, setLoadingInference] = useState(true);
  const [saving, setSaving] = useState(false);
  const [saved, setSaved] = useState(false);
  const [errorMsg, setErrorMsg] = useState('');
  const resolvedRef = useRef(false);

  // Fetch scores on mount
  useEffect(() => {
    if (
      window.CerebrasBackchannel &&
      typeof window.CerebrasBackchannel.getRewardScores === 'function'
    ) {
      try {
        const s = window.CerebrasBackchannel.getRewardScores();
        setScores(s || {});
      } catch (err) {
        console.error('[KnowledgeGapRitual] Score fetch failed:', err);
        setScores({});
      }
    } else {
      setScores({});
    }
  }, []);

  // Run parallel Cerebras inference for learned + gaps
  useEffect(() => {
    if (
      !window.CerebrasBackchannel ||
      typeof window.CerebrasBackchannel.inferSelfReport !== 'function'
    ) {
      setLearned('');
      setGaps('');
      setLoadingInference(false);
      return;
    }

    Promise.allSettled([
      window.CerebrasBackchannel.inferSelfReport({ type: 'learned', zoneId }),
      window.CerebrasBackchannel.inferSelfReport({ type: 'gaps', zoneId }),
    ]).then(([learnedResult, gapsResult]) => {
      setLearned(
        learnedResult.status === 'fulfilled' ? (learnedResult.value || '') : ''
      );
      setGaps(
        gapsResult.status === 'fulfilled' ? (gapsResult.value || '') : ''
      );
      setLoadingInference(false);
    });
  }, [zoneId]);

  const doResolve = useCallback((result) => {
    if (resolvedRef.current) return;
    resolvedRef.current = true;
    if (resolvePromise) resolvePromise(result);
  }, [resolvePromise]);

  const handleSave = async () => {
    setSaving(true);
    setErrorMsg('');
    let didSave = false;

    const receipt = {
      type: 'self-report',
      zoneId: zoneId,
      scores: scores || {},
      learned: learned || '',
      gaps: gaps || '',
      timestamp: new Date().toISOString(),
    };

    if (
      window.Persistence &&
      typeof window.Persistence.writeReceipt === 'function'
    ) {
      try {
        await window.Persistence.writeReceipt(receipt);
        didSave = true;
      } catch (err) {
        console.error('[KnowledgeGapRitual] Persistence write failed:', err);
        setErrorMsg('Failed to persist self-report. Receipt logged to console.');
      }
    } else {
      console.warn('[KnowledgeGapRitual] window.Persistence unavailable. Receipt:', receipt);
      setErrorMsg('Persistence service unavailable.');
    }

    setSaving(false);
    setSaved(didSave);
    doResolve({ saved: didSave, scores: scores || {}, learned: learned || '', gaps: gaps || '' });
    if (onClose) onClose();
  };

  const handleClose = () => {
    doResolve({ saved: false, scores: scores || {}, learned: learned || '', gaps: gaps || '' });
    if (onClose) onClose();
  };

  const isAnonymous = (
    window.AudienceMode &&
    typeof window.AudienceMode.isAnonymous === 'function' &&
    window.AudienceMode.isAnonymous()
  );

  const REWARD_LABELS = [
    { key: 'R1', label: 'R1: Shared Understanding', highlight: false },
    { key: 'R2', label: 'R2: Constitutional Score', highlight: false },
    { key: 'R3', label: 'R3: Player Agency', highlight: false },
    { key: 'R4', label: 'R4: Morphy Own Learning', highlight: true },
    { key: 'R5', label: 'R5: Game Vitality', highlight: false },
    { key: 'R6', label: 'R6: Anonymous Voice', highlight: false },
    { key: 'R7', label: 'R7: Truthfulness about Game', highlight: false },
  ];

  return (
    <div className="kgr-backdrop" onClick={handleClose}>
      <KGRStyles />
      <div className="kgr-modal" onClick={(e) => e.stopPropagation()}>
        <button className="kgr-close" onClick={handleClose} aria-label="Close">
          X
        </button>

        <div className="kgr-header">
          <h2>Knowledge Gap Surfacing</h2>
        </div>

        {/* R1-R7 Scores */}
        <div className="kgr-section">
          <h3 className="kgr-section-title">Reward Function (R1-R7)</h3>
          <ul className="kgr-list">
            {scores && REWARD_LABELS.map((r) => (
              <KGRScoreRow
                key={r.key}
                label={r.label}
                value={scores[r.key]}
                highlight={r.highlight}
              />
            ))}
          </ul>
        </div>

        {/* What I learned */}
        <div className="kgr-section">
          <h3 className="kgr-section-title">What I learned this session</h3>
          {loadingInference ? (
            <div className="kgr-loading">
              <span className="kgr-spinner"></span>
              Morphy is reflecting...
            </div>
          ) : (
            <div className="kgr-text-block">
              {learned || 'No inference available.'}
            </div>
          )}
        </div>

        {/* What I still cannot do well */}
        <div className="kgr-section">
          <h3 className="kgr-section-title">What I still cannot do well</h3>
          {loadingInference ? (
            <div className="kgr-loading">
              <span className="kgr-spinner"></span>
              Morphy is reflecting...
            </div>
          ) : (
            <div className="kgr-text-block">
              {gaps || 'No inference available.'}
            </div>
          )}
        </div>

        {/* Save + notes */}
        <div className="kgr-section">
          <button
            className="kgr-save-btn"
            onClick={handleSave}
            disabled={saving || saved}
          >
            {saving ? 'Saving...' : saved ? 'Saved' : 'Save self-report'}
          </button>

          {isAnonymous && (
            <div className="kgr-anon-note">
              Anonymous mode preserves participant identity.
            </div>
          )}

          {errorMsg && (
            <div className="kgr-error">{errorMsg}</div>
          )}
        </div>
      </div>
    </div>
  );
}

/* ---- Window global API ---- */

(function () {
  let _mountContainer = null;
  let _root = null;
  let _isOpen = false;

  function _ensureContainer() {
    if (!_mountContainer) {
      _mountContainer = document.createElement('div');
      _mountContainer.id = 'kgr-mount';
      document.body.appendChild(_mountContainer);
    }
    return _mountContainer;
  }

  function open({ zoneId, onClose }) {
    if (_isOpen) {
      return Promise.resolve({ saved: false, scores: {}, learned: '', gaps: '' });
    }
    _isOpen = true;

    return new Promise(function (resolve) {
      var container = _ensureContainer();

      function handleResolve(result) {
        _isOpen = false;
        if (_root) {
          _root.unmount();
          _root = null;
        }
        resolve(result);
      }

      function handleClose() {
        if (onClose) {
          try { onClose(); } catch (e) { console.error(e); }
        }
      }

      _root = ReactDOM.createRoot(container);
      _root.render(
        React.createElement(KnowledgeGapRitualModal, {
          zoneId: zoneId,
          onClose: handleClose,
          resolvePromise: handleResolve,
        })
      );
    });
  }

  function isOpen() {
    return _isOpen;
  }

  window.KnowledgeGapRitual = { open: open, isOpen: isOpen };
})();
