// Live session view — desktop. Shows brainwave traces, REM detection meter,
// and event log. Self-contained simulation — runs an internal clock, advances
// fake θ/α ratio, and triggers a "REM CONFIRMED" event every ~30s.

function LiveSession({ t, label }) {
  const [tick, setTick] = React.useState(0);
  const [trace, setTrace] = React.useState(() =>
    Array.from({ length: 180 }, () => 0.4 + Math.random() * 0.5)
  );
  const [events, setEvents] = React.useState([
    { ts: '02:11:00', kind: 'info', msg: 'Stream connected — Mind Monitor OSC :5000' },
    { ts: '02:11:02', kind: 'info', msg: 'Subject entering N2. θ low.' },
  ]);
  const [confirmed, setConfirmed] = React.useState(0); // 0..10
  const [rem, setRem] = React.useState(false);

  React.useEffect(() => {
    const id = setInterval(() => setTick(x => x + 1), 220);
    return () => clearInterval(id);
  }, []);

  React.useEffect(() => {
    setTrace(prev => {
      const phase = tick / 18;
      const base = 0.7 + 0.45 * Math.sin(phase) + 0.15 * Math.sin(phase * 2.3);
      const noise = (Math.random() - 0.5) * 0.4;
      const next = Math.max(0, base + noise);
      return [...prev.slice(1), next];
    });

    const cur = trace[trace.length - 1];
    if (cur >= 1.0) {
      setConfirmed(c => Math.min(10, c + 1));
    } else {
      setConfirmed(c => Math.max(0, c - 1));
    }
  }, [tick]);

  React.useEffect(() => {
    if (confirmed >= 10 && !rem) {
      setRem(true);
      setEvents(e => [
        { ts: fmtTs(tick), kind: 'rem', msg: '✦ REM CONFIRMED — θ/α 1.34 · 10s' },
        { ts: fmtTs(tick + 1), kind: 'trig', msg: '↯ Haptic trigger fired → ESP32:5001 (×3 pulses)' },
        ...e,
      ].slice(0, 8));
      setTimeout(() => { setRem(false); setConfirmed(0); }, 5400);
    }
  }, [confirmed, rem, tick]);

  return (
    <div style={{
      display: 'grid',
      gridTemplateColumns: '1fr 240px',
      gap: 0,
      height: '100%',
      fontFamily: t.mono,
      color: t.ink,
      background: `linear-gradient(180deg, ${t.bg} 0%, ${t.bgEnd} 100%)`,
    }}>
      {/* Main panel */}
      <div style={{ padding: '20px 24px', display: 'flex', flexDirection: 'column', gap: 14, minWidth: 0 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
          <div>
            <div style={{ fontSize: 10, letterSpacing: '0.18em', color: t.inkFaint, textTransform: 'uppercase' }}>
              {label} · session 14
            </div>
            <div style={{ fontFamily: t.serif, fontSize: 26, fontWeight: 400, marginTop: 2, color: t.ink }}>
              <span style={{ fontStyle: 'italic' }}>watching</span> the dream surface
            </div>
          </div>
          <div style={{ display: 'flex', gap: 18, fontSize: 11 }}>
            <Stat t={t} k="elapsed" v={fmtElapsed(tick)} />
            <Stat t={t} k="θ/α" v={trace[trace.length-1].toFixed(2)} hot={trace[trace.length-1] >= 1.0} />
            <Stat t={t} k="confirm" v={`${confirmed}/10`} hot={confirmed >= 10} />
            <Stat t={t} k="phase" v={rem ? 'REM' : confirmed > 5 ? 'pre-REM' : 'N2'} hot={rem} />
          </div>
        </div>

        {/* Brainwave plot */}
        <BrainwavePlot t={t} trace={trace} rem={rem} confirmed={confirmed} />

        {/* REM detection meter */}
        <div>
          <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10, letterSpacing: '0.14em', color: t.inkFaint, textTransform: 'uppercase', marginBottom: 6 }}>
            <span>REM confirmation window</span>
            <span>10 s required</span>
          </div>
          <div style={{ display: 'flex', gap: 4 }}>
            {Array.from({length: 10}).map((_, i) => (
              <div key={i} style={{
                flex: 1, height: 10, borderRadius: 2,
                background: i < confirmed
                  ? (rem ? t.rem : t.accent)
                  : t.surface,
                border: `1px solid ${t.line}`,
                boxShadow: i < confirmed && rem ? `0 0 12px ${t.rem}` : 'none',
                transition: 'background 200ms',
              }} />
            ))}
          </div>
        </div>
      </div>

      {/* Event log */}
      <div style={{
        borderLeft: `1px solid ${t.line}`,
        padding: '20px 16px',
        background: t.surface,
        display: 'flex', flexDirection: 'column', gap: 6,
        fontSize: 10.5,
      }}>
        <div style={{ fontSize: 10, letterSpacing: '0.18em', color: t.inkFaint, textTransform: 'uppercase', marginBottom: 6 }}>
          ledger
        </div>
        {events.map((e, i) => (
          <div key={i} style={{
            display: 'grid', gridTemplateColumns: '54px 1fr', gap: 8,
            color: e.kind === 'rem' ? t.rem : e.kind === 'trig' ? t.accent : t.inkSoft,
            opacity: 1 - i * 0.08,
            lineHeight: 1.45,
          }}>
            <span style={{ color: t.inkFaint }}>{e.ts}</span>
            <span>{e.msg}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

function Stat({ t, k, v, hot }) {
  return (
    <div style={{ textAlign: 'right' }}>
      <div style={{ fontSize: 9, letterSpacing: '0.18em', color: t.inkFaint, textTransform: 'uppercase' }}>{k}</div>
      <div style={{ fontFamily: t.mono, fontSize: 14, color: hot ? t.rem : t.ink, fontVariantNumeric: 'tabular-nums' }}>
        {v}
      </div>
    </div>
  );
}

function BrainwavePlot({ t, trace, rem, confirmed }) {
  const W = 760, H = 220;
  const max = 2.4;
  const pts = trace.map((v, i) => {
    const x = (i / (trace.length - 1)) * W;
    const y = H - (Math.min(v, max) / max) * H;
    return [x, y];
  });
  const path = pts.map(([x,y], i) => `${i===0?'M':'L'} ${x.toFixed(1)} ${y.toFixed(1)}`).join(' ');
  const fillPath = path + ` L ${W} ${H} L 0 ${H} Z`;
  const thresholdY = H - (1.0 / max) * H;

  return (
    <div style={{
      position: 'relative', flex: 1, minHeight: 200,
      border: `1px solid ${t.line}`, borderRadius: 6,
      background: t.surface,
      overflow: 'hidden',
    }}>
      <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none"
           style={{ width: '100%', height: '100%', display: 'block' }}>
        <defs>
          <linearGradient id="trace-fill" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor={rem ? t.rem : t.accent} stopOpacity="0.35" />
            <stop offset="100%" stopColor={rem ? t.rem : t.accent} stopOpacity="0" />
          </linearGradient>
        </defs>

        {/* gridlines */}
        {[0.25, 0.5, 0.75].map(p => (
          <line key={p} x1="0" y1={H*p} x2={W} y2={H*p}
                stroke={t.grid} strokeWidth="0.5" />
        ))}
        {/* threshold */}
        <line x1="0" y1={thresholdY} x2={W} y2={thresholdY}
              stroke={t.rem} strokeWidth="0.7" strokeDasharray="3 4" opacity="0.5" />
        <text x={W - 6} y={thresholdY - 5} textAnchor="end"
              fontFamily={t.mono} fontSize="9" fill={t.rem} opacity="0.7">
          θ/α ≥ 1.00 — REM
        </text>

        {/* fill */}
        <path d={fillPath} fill="url(#trace-fill)" />
        {/* line */}
        <path d={path} fill="none" stroke={rem ? t.rem : t.accent} strokeWidth="1.4"
              style={{ filter: `drop-shadow(0 0 6px ${rem ? t.rem : t.accent})` }} />

        {/* leading dot */}
        {pts.length > 0 && (
          <circle cx={pts[pts.length-1][0]} cy={pts[pts.length-1][1]} r="3.5"
                  fill={rem ? t.rem : t.accent}>
            <animate attributeName="r" values="3.5;5.5;3.5" dur="1.4s" repeatCount="indefinite" />
          </circle>
        )}
      </svg>

      {/* axis labels */}
      <div style={{
        position: 'absolute', left: 8, top: 8,
        fontFamily: t.mono, fontSize: 9, letterSpacing: '0.14em',
        color: t.inkFaint, textTransform: 'uppercase',
      }}>
        TP9 + TP10 · θ/α · 3 min
      </div>

      {rem && (
        <div style={{
          position: 'absolute', right: 12, bottom: 12,
          fontFamily: t.serif, fontStyle: 'italic',
          fontSize: 18, color: t.rem,
          textShadow: `0 0 12px ${t.rem}`,
          animation: 'oneiro-pulse 1.6s ease-in-out infinite',
        }}>
          surfacing.
        </div>
      )}
    </div>
  );
}

function fmtTs(tick) {
  const total = 130 + tick;
  const m = Math.floor(total / 60).toString().padStart(2, '0');
  const s = (total % 60).toString().padStart(2, '0');
  return `02:${m}:${s}`;
}
function fmtElapsed(tick) {
  const sec = 130 + tick;
  const h = Math.floor(sec / 3600);
  const m = Math.floor((sec % 3600) / 60);
  const s = sec % 60;
  return `${h}:${m.toString().padStart(2,'0')}:${s.toString().padStart(2,'0')}`;
}

window.LiveSession = LiveSession;
