/* eslint-disable */
const { useState, useEffect, useRef } = React;

// ──────────────────────────────────────────────
// Logo  —  ".mo" with a glowing dot accent
// ──────────────────────────────────────────────
function DotmoMark({ size = 28, accent }) {
  return (
    <div className="dotmo-mark" style={{ height: size }}>
      <span
        className="dotmo-dot"
        style={{
          width: size * 0.42,
          height: size * 0.42,
          background: accent,
          boxShadow: `0 0 ${size * 0.6}px ${accent}, 0 0 ${size * 1.4}px ${accent}55`,
        }}
      />
      <span className="dotmo-word" style={{ fontSize: size * 0.78 }}>mo</span>
    </div>
  );
}

// ──────────────────────────────────────────────
// Moment card — always-visible Play pill,
// hover "video preview" via Ken-Burns + grain.
// ──────────────────────────────────────────────
function MomentCard({ moment, hoverPlays, onOpen }) {
  const [hover, setHover] = useState(false);
  const { title, desc, pos, duration, tag } = moment;

  return (
    <article
      className={`moment moment-third ${hover ? 'is-hover' : ''}`}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      onClick={() => onOpen && onOpen(moment)}
      role="button"
      tabIndex={0}
      onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onOpen && onOpen(moment); } }}
    >
      <div className="moment-frame">
        <div
          className="moment-image"
          style={{
            backgroundImage: `url(${window.__resources.blasphemousBg})`,
            backgroundPosition: `${pos.x}% ${pos.y}%`,
            transform: hover && hoverPlays
              ? `scale(${pos.scale * 1.06})`
              : `scale(${pos.scale})`,
          }}
        />
        <div className={`moment-grain ${hover && hoverPlays ? 'is-on' : ''}`} />
        <div className="moment-shade" />

        <div className="moment-top">
          <span className="moment-tag">{tag}</span>
          <span className={`moment-live ${hover && hoverPlays ? 'is-on' : ''}`}>
            <span className="moment-live-dot" />
            <span>PREVIEW</span>
          </span>
        </div>

        <span className="moment-duration">{duration}</span>
      </div>

      <div className="moment-meta">
        <h3 className="moment-title">{title}</h3>
        <p className="moment-desc">{desc}</p>
      </div>
    </article>
  );
}

// ──────────────────────────────────────────────
// Section header for "Blasphemous"
// ──────────────────────────────────────────────
function SectionHeader({ count }) {
  return (
    <header className="section-head">
      <div className="section-head-meta">
        <span className="section-eyebrow">Featured · Live</span>
        <span className="section-meta-sep" />
        <span className="section-meta">{count === 1 ? '1 moment' : `${count} moments`}</span>
        <span className="section-meta-sep" />
        <span className="section-meta">2D · Souls-like · Generative</span>
      </div>
      <h2 className="section-title">Blasphemous</h2>
      <p className="section-desc">
        Pre-rendered moments from a single run, each one an entry point.
        Press play to drop into a real-time, infinitely branching continuation.
      </p>
    </header>
  );
}

// ──────────────────────────────────────────────
// Site header
// ──────────────────────────────────────────────
function SiteHeader({ accent }) {
  return (
    <header className="site-header">
      <a className="brand" href="#">
        <DotmoMark size={26} accent={accent} />
        <span className="brand-tag">GAMING. REDEFINED</span>
      </a>
      <nav className="site-nav">
        <a className="site-nav-link is-active" href="#">Library</a>
        <a className="site-nav-link" href="#">Docs</a>
      </nav>
      <div className="site-header-right">
        <button className="hdr-icon" aria-label="Search">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <circle cx="11" cy="11" r="7"/><path d="M21 21l-4.3-4.3"/>
          </svg>
        </button>
        <div className="hdr-avatar" aria-label="Account">
          <span>A</span>
        </div>
      </div>
    </header>
  );
}

// ──────────────────────────────────────────────
// Play overlay — gradient fade to black, centered
// 512×288 demo stage with a live canvas + Play / Reset / Close.
// ──────────────────────────────────────────────
function PlayOverlay({ moment, onClose }) {
  const [mounted, setMounted] = useState(false);
  const demoRef = useRef(null);
  // Lift DemoStage state up so the HUD can render outside the stage frame.
  const [demoState, setDemoState] = useState({
    status: 'connecting',
    statusMsg: 'connecting…',
    recvCount: 0,
    queueLen: 0,
    heldDisplay: [],
    renderedHeld: [],
    pingMs: null,
    denoiseMs: null,
    decodeMs: null,
  });

  useEffect(() => {
    if (moment) {
      const id = requestAnimationFrame(() => setMounted(true));
      return () => cancelAnimationFrame(id);
    } else {
      setMounted(false);
    }
  }, [moment]);

  if (!moment) return null;

  const { status: demoStatus } = demoState;
  const playEnabled = demoStatus === 'ready';
  const resetEnabled = ['ready', 'streaming', 'starting', 'error'].includes(demoStatus);

  return (
    <div className={`play-overlay ${mounted ? 'is-on' : ''}`} role="dialog" aria-modal="true">
      <div className="play-stats">
        <StatsPanel
          pingMs={demoState.pingMs}
          denoiseMs={demoState.denoiseMs}
          decodeMs={demoState.decodeMs}
        />
      </div>

      <button className="play-close" onClick={onClose} aria-label="Close and return to gallery">
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
          <path d="M6 6l12 12M18 6L6 18" />
        </svg>
      </button>

      <div className="play-stage-wrap">
        <div className="play-meta">
          <span className="play-meta-tag">{moment.tag}</span>
          <h3 className="play-meta-title">{moment.title}</h3>
        </div>

        <div className={`play-stage ${demoStatus === 'streaming' ? 'is-live' : ''}`}>
          {/* The decorative still + grain stay underneath the canvas; they
              fade out once live frames are flowing (see styles). */}
          <div
            className="play-stage-image"
            style={{
              backgroundImage: `url(${window.__resources.blasphemousBg})`,
              backgroundPosition: `${moment.pos.x}% ${moment.pos.y}%`,
              transform: `scale(${moment.pos.scale})`,
            }}
          />
          <div className="play-stage-grain" />
          <DemoStage ref={demoRef} onClose={onClose} onState={setDemoState} />
        </div>

        <DemoHud
          recvCount={demoState.recvCount}
          queueLen={demoState.queueLen}
          heldDisplay={demoState.heldDisplay}
          streaming={demoState.status === 'streaming'}
        />

        <Keyboard active={demoState.renderedHeld} />

        <div className="play-actions">
          <button
            className="play-primary"
            disabled={!playEnabled}
            onClick={() => demoRef.current && demoRef.current.play()}
            aria-label={`Play ${moment.title}`}
          >
            <svg width="11" height="13" viewBox="0 0 11 13" fill="none" aria-hidden="true">
              <path d="M0 0L11 6.5L0 13V0Z" fill="currentColor" />
            </svg>
            Play
          </button>
          <button
            className="play-reset"
            disabled={!resetEnabled}
            onClick={() => demoRef.current && demoRef.current.reset()}
          >
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M3 12a9 9 0 1 0 3-6.7" />
              <path d="M3 4v5h5" />
            </svg>
            Reset
          </button>
        </div>
      </div>
    </div>
  );
}

// ──────────────────────────────────────────────
// StatsPanel — top-left HUD with PING / DENOISE / DECODE.
// PING is a real WS round-trip measured by demo.jsx; DENOISE/DECODE come
// from the model server, attached to the first frame of every block.
// ──────────────────────────────────────────────
function StatsPanel({ pingMs, denoiseMs, decodeMs }) {
  const fmt = (v) => (v == null ? '—' : Math.round(v));
  const ping = pingMs == null ? null : Math.round(pingMs);
  const quality = ping == null ? 'good' : ping < 30 ? 'good' : ping < 55 ? 'ok' : 'bad';

  return (
    <div className={`ping-panel ping-${quality}`}>
      <div className="ping-row">
        <span className="ping-label">PING</span>
        <span className="ping-value">
          {fmt(pingMs)}<span className="ping-unit">ms</span>
        </span>
      </div>
      <div className="ping-row ping-row-sub">
        <span className="ping-label">DENOISE</span>
        <span className="ping-value-sub">
          {fmt(denoiseMs)}<span className="ping-unit">ms</span>
        </span>
      </div>
      <div className="ping-row ping-row-sub">
        <span className="ping-label">DECODE</span>
        <span className="ping-value-sub">
          {fmt(decodeMs)}<span className="ping-unit">ms</span>
        </span>
      </div>
    </div>
  );
}

// ──────────────────────────────────────────────
// App
// ──────────────────────────────────────────────
const ACCENT = '#FF3B2F';

function App() {
  useEffect(() => {
    document.documentElement.style.setProperty('--accent', ACCENT);
  }, []);

  const moments = window.BLASPHEMOUS_MOMENTS;

  const [playing, setPlaying] = useState(null);
  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') setPlaying(null); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);

  return (
    <div className="app density-spacious grid-editorial">
      <SiteHeader accent={ACCENT} />

      <main className="content">
        <section className="library-section">
          <SectionHeader count={moments.length} />
          <div className="moment-grid grid-row3">
            {moments.map((m) => (
              <MomentCard
                key={m.id}
                moment={m}
                hoverPlays={true}
                onOpen={setPlaying}
              />
            ))}
          </div>
        </section>

        <footer className="site-footer">
          <span>© 2026 Dotmo · Real-time generative play</span>
          <span>v0.5 · build 2026.05</span>
        </footer>
      </main>

      <PlayOverlay moment={playing} onClose={() => setPlaying(null)} />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
