// runtime.jsx — Mahana Playground scaffold
// Adapters register themselves onto window.__PG_ADAPTER and this mounts them.
// Exposes window.__playground for agent-driven screenshot walks.

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

// ──────────────────────────────────────────────────────────────
// Breakpoint presets
// ──────────────────────────────────────────────────────────────
const BREAKPOINTS = [
  { id: 'desktop', label: 'Desktop', width: '100%', px: null },
  { id: 'tablet',  label: 'Tablet',  width: '834px', px: 834 },
  { id: 'mobile',  label: 'Mobile',  width: '390px', px: 390 },
];

const BACKGROUNDS = [
  { id: 'paper',     label: 'Paper' },
  { id: 'grid',      label: 'Grid' },
  { id: 'neutral',   label: 'Neutral' },
  { id: 'painterly', label: 'Painterly' },
  { id: 'dark',      label: 'Dark' },
];

const DEFAULT_CTX = {
  breakpoint: 'desktop',
  theme: 'light',
  bg: 'paper',
  density: 'default',
  mobileSwap: true,
  showLabels: true,
  showGrid: false,
};

// ──────────────────────────────────────────────────────────────
// Segmented control
// ──────────────────────────────────────────────────────────────
function Segment({ options, value, onChange }) {
  return (
    <div className="pg-segment">
      {options.map(o => (
        <button key={o.id} aria-pressed={value === o.id} onClick={() => onChange(o.id)}>
          {o.label}
        </button>
      ))}
    </div>
  );
}

// ──────────────────────────────────────────────────────────────
// TweaksPanel — left rail
// ──────────────────────────────────────────────────────────────
function TweaksPanel({ ctx, setCtx, adapter }) {
  const patch = (k) => (v) => setCtx({ ...ctx, [k]: v });
  return (
    <div>
      <h3 className="pg-tweaks-title">Canvas</h3>
      <div className="pg-tweak">
        <label className="pg-tweak-label">Breakpoint</label>
        <Segment options={BREAKPOINTS} value={ctx.breakpoint} onChange={patch('breakpoint')} />
      </div>
      <div className="pg-tweak">
        <label className="pg-tweak-label">Theme</label>
        <Segment
          options={[{ id: 'light', label: 'Light' }, { id: 'dark', label: 'Dark' }]}
          value={ctx.theme}
          onChange={patch('theme')}
        />
      </div>
      <div className="pg-tweak">
        <label className="pg-tweak-label">Stage</label>
        <Segment options={BACKGROUNDS} value={ctx.bg} onChange={patch('bg')} />
      </div>
      <div className="pg-tweak">
        <label className="pg-tweak-label">Density</label>
        <Segment
          options={[{ id: 'default', label: 'Default' }, { id: 'dense', label: 'Dense' }]}
          value={ctx.density}
          onChange={patch('density')}
        />
      </div>

      <h3 className="pg-tweaks-title" style={{ marginTop: 24 }}>Rules</h3>
      <div className="pg-tweak">
        <label className="pg-check">
          <input
            type="checkbox"
            checked={ctx.mobileSwap}
            onChange={e => setCtx({ ...ctx, mobileSwap: e.target.checked })}
          />
          Swap to mobile variant in mobile breakpoint
        </label>
      </div>
      <div className="pg-tweak">
        <label className="pg-check">
          <input type="checkbox" checked={ctx.showLabels}
                 onChange={e => setCtx({ ...ctx, showLabels: e.target.checked })} />
          Show variant labels
        </label>
      </div>

      {adapter && adapter.tweaks && adapter.tweaks.length > 0 && (
        <>
          <h3 className="pg-tweaks-title" style={{ marginTop: 24 }}>
            {adapter.name} knobs
          </h3>
          {adapter.tweaks.map(t => (
            <div key={t.id} className="pg-tweak">
              <label className="pg-tweak-label">{t.label}</label>
              {t.kind === 'segment' && (
                <Segment
                  options={t.options}
                  value={ctx[t.id] ?? t.default}
                  onChange={v => setCtx({ ...ctx, [t.id]: v })}
                />
              )}
              {t.kind === 'checkbox' && (
                <label className="pg-check">
                  <input type="checkbox" checked={ctx[t.id] ?? t.default}
                         onChange={e => setCtx({ ...ctx, [t.id]: e.target.checked })} />
                  {t.checkboxLabel || ''}
                </label>
              )}
            </div>
          ))}
        </>
      )}
    </div>
  );
}

// ──────────────────────────────────────────────────────────────
// Spec side-panel — right rail
// ──────────────────────────────────────────────────────────────
function SpecPanel({ adapter, ctx }) {
  if (!adapter) return null;
  const meta = adapter.meta || {};
  return (
    <div className="pg-spec">
      <h3>{adapter.name}</h3>
      <p className="desc">{adapter.description || meta.description}</p>

      {meta.level && (
        <div className="section">
          <div className="section-title">Level</div>
          <span className="pill">{meta.level}</span>
        </div>
      )}
      {meta.source && (
        <div className="section">
          <div className="section-title">Source</div>
          <span className="pill">{meta.source}</span>
        </div>
      )}
      {meta.props && meta.props.length > 0 && (
        <div className="section">
          <div className="section-title">Props</div>
          <div className="pill-row">
            {meta.props.map(p => <span key={p} className="pill">{p}</span>)}
          </div>
        </div>
      )}
      {meta.tokens && meta.tokens.length > 0 && (
        <div className="section">
          <div className="section-title">Tokens consumed</div>
          <div className="pill-row">
            {meta.tokens.map(t => <span key={t} className="pill">{t}</span>)}
          </div>
        </div>
      )}
      {meta.links && (
        <div className="section">
          <div className="section-title">Context</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12 }}>
            {meta.links.map(l => (
              <a key={l.href} href={l.href} target="_blank" rel="noreferrer">{l.label}</a>
            ))}
          </div>
        </div>
      )}
      <div className="section" style={{ marginTop: 20 }}>
        <div className="section-title">Shortcuts</div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12, color: 'var(--pg-ink-dim)' }}>
          <div><span className="pg-kbd">G</span> gallery walk</div>
          <div><span className="pg-kbd">S</span> screenshot this variant</div>
          <div><span className="pg-kbd">A</span> agent: mark all for capture</div>
          <div><span className="pg-kbd">←</span>/<span className="pg-kbd">→</span> prev/next in gallery</div>
          <div><span className="pg-kbd">Esc</span> exit gallery</div>
        </div>
      </div>
    </div>
  );
}

// ──────────────────────────────────────────────────────────────
// Canvas — grids grouped variants at the current breakpoint
// ──────────────────────────────────────────────────────────────
function Canvas({ adapter, ctx }) {
  if (!adapter) return <div className="pg-empty">No adapter loaded</div>;
  const bp = BREAKPOINTS.find(b => b.id === ctx.breakpoint);
  const isMobile = ctx.breakpoint === 'mobile' && ctx.mobileSwap;
  const variantsToShow = isMobile && adapter.mobileVariants
    ? adapter.mobileVariants
    : adapter.variants;

  // Pick the right groups, falling back to a single "all variants" group when
  // the adapter's groups reference ids that don't exist in the current variant set
  // (e.g. desktop groups referencing mobile-prefixed ids).
  let groups;
  if (isMobile && adapter.mobileGroups) {
    groups = adapter.mobileGroups;
  } else if (adapter.groups) {
    const allIds = new Set(variantsToShow.map(v => v.id));
    const filtered = adapter.groups
      .map(g => ({ ...g, variantIds: g.variantIds.filter(id => allIds.has(id)) }))
      .filter(g => g.variantIds.length > 0);
    groups = filtered.length > 0
      ? filtered
      : [{ id: '_default', label: isMobile ? 'Mobile variants' : '', variantIds: variantsToShow.map(v => v.id) }];
  } else {
    groups = [{ id: '_default', label: '', variantIds: variantsToShow.map(v => v.id) }];
  }

  return (
    <div className="pg-viewport" style={{ '--pg-viewport-w': bp.width }}>
      {groups.map(g => {
        const vs = g.variantIds.map(id => variantsToShow.find(v => v.id === id)).filter(Boolean);
        if (vs.length === 0) return null;
        return (
          <section key={g.id} className="pg-group">
            {g.label && <h3 className="pg-group-title">{g.label}</h3>}
            <div className="pg-canvas" style={{ '--pg-card-min': (g.minCard || 240) + 'px' }}>
              {vs.map(v => (
                <VariantCard key={v.id} variant={v} ctx={ctx} />
              ))}
            </div>
          </section>
        );
      })}
    </div>
  );
}

function VariantCard({ variant, ctx }) {
  return (
    <div className="pg-card" data-variant={variant.id}>
      <div className="pg-card-stage" data-bg={ctx.bg}>
        {variant.render(ctx)}
      </div>
      {ctx.showLabels && (
        <div className="pg-card-meta">
          <span className="pg-card-label">{variant.label}</span>
          {variant.sublabel && <span className="pg-card-sublabel">{variant.sublabel}</span>}
        </div>
      )}
    </div>
  );
}

// ──────────────────────────────────────────────────────────────
// Gallery — fullscreen one-variant-at-a-time, arrow-key navigable
// ──────────────────────────────────────────────────────────────
function Gallery({ adapter, ctx, idx, onClose, onPrev, onNext }) {
  const variants = (ctx.breakpoint === 'mobile' && ctx.mobileSwap && adapter.mobileVariants)
    ? adapter.mobileVariants
    : adapter.variants;
  const v = variants[idx % variants.length];
  if (!v) return null;
  return (
    <div className="pg-gallery" data-gallery-idx={idx} data-gallery-id={v.id}>
      <div className="pg-gallery-top">
        <div className="pg-brand">
          {adapter.name} <span className="dim">/ {v.label}</span>
        </div>
        <div className="pg-spacer" />
        <div style={{ fontSize: 12, color: 'var(--pg-ink-dim)' }}>
          {idx + 1} / {variants.length}
        </div>
        <button className="pg-btn" onClick={onPrev} aria-label="Previous">←</button>
        <button className="pg-btn" onClick={onNext} aria-label="Next">→</button>
        <button className="pg-btn" onClick={onClose}>Exit (Esc)</button>
      </div>
      <div className="pg-gallery-stage" data-bg={ctx.bg} data-variant={v.id}>
        {v.render(ctx)}
      </div>
      <div className="pg-gallery-meta">
        <div>
          <div style={{ fontSize: 13, fontWeight: 600 }}>{v.label}</div>
          {v.sublabel && <div style={{ fontSize: 12, color: 'var(--pg-ink-dim)', fontFamily: 'var(--pg-mono)' }}>{v.sublabel}</div>}
        </div>
        <div className="pg-spacer" />
        {v.notes && <div style={{ fontSize: 12, color: 'var(--pg-ink-dim)', maxWidth: 480 }}>{v.notes}</div>}
      </div>
    </div>
  );
}

// ──────────────────────────────────────────────────────────────
// Main app
// ──────────────────────────────────────────────────────────────
function PlaygroundApp({ adapter }) {
  const storageKey = 'mahana-pg-ctx:' + (adapter?.id || 'default');
  const [ctx, setCtxRaw] = useState(() => {
    try {
      const saved = localStorage.getItem(storageKey);
      return saved ? { ...DEFAULT_CTX, ...JSON.parse(saved) } : DEFAULT_CTX;
    } catch { return DEFAULT_CTX; }
  });
  const setCtx = useCallback((next) => {
    setCtxRaw(next);
    try { localStorage.setItem(storageKey, JSON.stringify(next)); } catch {}
  }, [storageKey]);

  const [galleryIdx, setGalleryIdx] = useState(null);
  const [toast, setToast] = useState(null);
  const flashToast = (msg) => { setToast(msg); setTimeout(() => setToast(null), 2000); };

  // Theme
  useEffect(() => {
    document.documentElement.dataset.pgTheme = ctx.theme;
  }, [ctx.theme]);

  // Expose agent hooks
  useEffect(() => {
    if (!adapter) return;
    const variants = (ctx.breakpoint === 'mobile' && ctx.mobileSwap && adapter.mobileVariants)
      ? adapter.mobileVariants
      : adapter.variants;
    window.__playground = {
      adapter: { id: adapter.id, name: adapter.name },
      ctx,
      variants: variants.map(v => ({ id: v.id, label: v.label })),
      openGallery: (i = 0) => setGalleryIdx(i),
      closeGallery: () => setGalleryIdx(null),
      nextVariant: () => setGalleryIdx(i => (i == null ? 0 : (i + 1) % variants.length)),
      prevVariant: () => setGalleryIdx(i => (i == null ? 0 : (i - 1 + variants.length) % variants.length)),
      setCtx: (patch) => setCtx({ ...ctx, ...patch }),
    };
  }, [adapter, ctx, setCtx]);

  // Keyboard
  useEffect(() => {
    const onKey = (e) => {
      if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
      if (e.key === 'g' || e.key === 'G') { setGalleryIdx(i => i == null ? 0 : null); }
      if (e.key === 'Escape' && galleryIdx != null) setGalleryIdx(null);
      if (galleryIdx != null) {
        const len = (ctx.breakpoint === 'mobile' && ctx.mobileSwap && adapter?.mobileVariants
          ? adapter.mobileVariants : adapter?.variants || []).length;
        if (e.key === 'ArrowRight') setGalleryIdx(i => (i + 1) % len);
        if (e.key === 'ArrowLeft')  setGalleryIdx(i => (i - 1 + len) % len);
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [galleryIdx, adapter, ctx]);

  if (!adapter) {
    return <div className="pg-empty">Loading adapter…</div>;
  }

  return (
    <>
      <div className="pg-shell">
        <header className="pg-topbar">
          <div className="pg-brand">Mahana <span className="dim">Playground</span></div>
          <div className="pg-component-name">{adapter.id}</div>
          <div className="pg-spacer" />
          <a className="pg-btn" href="playground/index.html">All components</a>
          <button className="pg-btn" onClick={() => setGalleryIdx(0)} title="Gallery walk (G)">
            Gallery <span className="pg-kbd">G</span>
          </button>
          <button className="pg-btn primary" onClick={() => {
            const url = window.location.href;
            navigator.clipboard?.writeText(url);
            flashToast('URL copied');
          }}>Share</button>
        </header>
        <aside className="pg-sidebar-left">
          <TweaksPanel ctx={ctx} setCtx={setCtx} adapter={adapter} />
        </aside>
        <main className="pg-canvas-wrap" data-pg-canvas>
          <Canvas adapter={adapter} ctx={ctx} />
        </main>
        <aside className="pg-sidebar-right">
          <SpecPanel adapter={adapter} ctx={ctx} />
        </aside>
      </div>
      {galleryIdx != null && (
        <Gallery
          adapter={adapter}
          ctx={ctx}
          idx={galleryIdx}
          onClose={() => setGalleryIdx(null)}
          onPrev={() => {
            const len = (ctx.breakpoint === 'mobile' && ctx.mobileSwap && adapter.mobileVariants
              ? adapter.mobileVariants : adapter.variants).length;
            setGalleryIdx(i => (i - 1 + len) % len);
          }}
          onNext={() => {
            const len = (ctx.breakpoint === 'mobile' && ctx.mobileSwap && adapter.mobileVariants
              ? adapter.mobileVariants : adapter.variants).length;
            setGalleryIdx(i => (i + 1) % len);
          }}
        />
      )}
      {toast && <div className="pg-toast">{toast}</div>}
    </>
  );
}

// ──────────────────────────────────────────────────────────────
// Mount — called after the adapter registers
// ──────────────────────────────────────────────────────────────
window.__PG_MOUNT = function(adapter) {
  window.__PG_ADAPTER = adapter;
  const root = window.__PG_ROOT || ReactDOM.createRoot(document.getElementById('root'));
  window.__PG_ROOT = root;
  root.render(<PlaygroundApp adapter={adapter} />);
};

// If the adapter already registered before runtime loaded, mount now.
if (window.__PG_ADAPTER) {
  window.__PG_MOUNT(window.__PG_ADAPTER);
}
