// Shared kiosk atoms: StatusBar, Stepper, FaceMesh placeholder, sensor visualizations.

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

// ── StatusBar (top of every screen post-idle) ─────────────────
function StatusBar({ stepIdx, location = 'Smile Dental · Bandra W', clock = true }) {
  const [time, setTime] = useState(() => fmtTime());
  useEffect(() => {
    if (!clock) return;
    const t = setInterval(() => setTime(fmtTime()), 1000 * 30);
    return () => clearInterval(t);
  }, [clock]);
  function fmtTime() {
    return new Date().toLocaleTimeString('en-IN', { hour: '2-digit', minute: '2-digit', hour12: false });
  }
  return (
    <div className="statusbar">
      <div className="lhs">
        <div className="brand">
          <span className="brand-mark">
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none">
              <circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2"/>
              <path d="M7 12c1.5-3 8-3 9.5 0" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
            </svg>
          </span>
          OraScan
        </div>
        <span style={{ color: 'var(--line-2)' }}>·</span>
        <span>{location}</span>
      </div>
      <div className="rhs">
        {stepIdx != null && <Stepper idx={stepIdx} />}
      </div>
      <div className="rhs">
        <span className="dot-online" />
        <span>Kiosk 04 · {time} IST</span>
      </div>
    </div>
  );
}

// ── Stepper across major phases ────────────────────────────────
const PHASES = ['Check-in', 'Questions', 'Photos', 'Voice', 'Breath', 'Done'];
function Stepper({ idx = 0 }) {
  return (
    <div className="stepper">
      {PHASES.map((p, i) => (
        <React.Fragment key={p}>
          <span className={`seg ${i < idx ? 'done' : i === idx ? 'cur' : ''}`}>
            <span className="ring" />
            <span>{p}</span>
          </span>
          {i < PHASES.length - 1 && <span className="sep" />}
        </React.Fragment>
      ))}
    </div>
  );
}

// ── FaceMesh placeholder (animated) ────────────────────────────
// Renders a faint face silhouette + ~70 mesh dots that subtly oscillate.
// Used for both the position screen and the photo-capture preview.
const MESH_NODES = (() => {
  // hand-picked points outlining a face oval, eyes, nose, mouth.
  // coords are in a 100×140 viewport, centered.
  const oval = [];
  const N = 26;
  for (let i = 0; i < N; i++) {
    const a = (i / N) * Math.PI * 2;
    const x = 50 + Math.cos(a) * 30;
    const y = 70 + Math.sin(a) * 42;
    oval.push([x, y]);
  }
  const features = [
    // eyes
    [40, 60], [42, 62], [38, 62], [36, 60], [38, 58], [42, 58],
    [60, 60], [62, 62], [64, 60], [62, 58], [58, 60], [58, 62],
    // brows
    [36, 53], [40, 51], [44, 53],
    [56, 53], [60, 51], [64, 53],
    // nose
    [50, 65], [50, 70], [48, 75], [52, 75], [46, 78], [54, 78], [50, 78],
    // mouth
    [44, 88], [47, 87], [50, 87], [53, 87], [56, 88],
    [44, 92], [47, 93], [50, 93], [53, 93], [56, 92],
    // cheeks
    [34, 76], [66, 76], [36, 84], [64, 84],
    // chin
    [50, 102], [46, 100], [54, 100],
  ];
  return [...oval, ...features];
})();

function FaceMeshView({ status = 'aligned', drift = 0 }) {
  // drift in px (visualizes "centering... +12px")
  const [tick, setTick] = useState(0);
  useEffect(() => {
    const t = setInterval(() => setTick(v => v + 1), 80);
    return () => clearInterval(t);
  }, []);
  const dx = Math.sin(tick / 8) * 0.5 + (drift || 0) * 0.08;
  const dy = Math.cos(tick / 11) * 0.4;
  // mouth is animated: opens/closes during capture
  const mouthOpen = status === 'capturing' || status === 'aligned';

  return (
    <div className="facemesh-wrap">
      <svg viewBox="0 0 100 140" preserveAspectRatio="xMidYMid meet">
        <defs>
          <radialGradient id="faceGrad" cx="50%" cy="60%" r="55%">
            <stop offset="0%"  stopColor="#fff" stopOpacity=".08"/>
            <stop offset="100%" stopColor="#fff" stopOpacity="0"/>
          </radialGradient>
        </defs>
        {/* face silhouette */}
        <g transform={`translate(${dx} ${dy})`}>
          <ellipse cx="50" cy="72" rx="30" ry="42" fill="url(#faceGrad)" stroke="rgba(255,255,255,.10)" strokeWidth=".4"/>
          {/* mesh lines (subtle connective tissue) */}
          {MESH_NODES.map((p, i) => {
            if (i === 0) return null;
            const prev = MESH_NODES[i - 1];
            // skip lines between distant clusters
            const d = Math.hypot(p[0] - prev[0], p[1] - prev[1]);
            if (d > 10) return null;
            return <line key={'l' + i} x1={prev[0]} y1={prev[1]} x2={p[0]} y2={p[1]} className="mesh-line" />;
          })}
          {/* mesh nodes */}
          {MESH_NODES.map((p, i) => {
            const ph = (i * 13) % 50;
            const r = 0.5 + Math.sin((tick + ph) / 7) * 0.15;
            return <circle key={'n' + i} cx={p[0]} cy={p[1]} r={r} className="mesh-node"
                           opacity={status === 'no-face' ? .15 : .85} />;
          })}
          {/* mouth opening */}
          {mouthOpen && (
            <ellipse cx="50" cy="90" rx="7" ry={status === 'capturing' ? 4 : 2.5}
                     fill="rgba(255,255,255,.12)" stroke="rgba(255,240,200,.4)" strokeWidth=".4"/>
          )}
          {/* gaze targets */}
          <circle cx="40" cy="60" r="1.6" fill="var(--accent-soft)" opacity=".8"/>
          <circle cx="60" cy="60" r="1.6" fill="var(--accent-soft)" opacity=".8"/>
        </g>
      </svg>
    </div>
  );
}

// ── Camera frame chrome (used inside .cap-cam / .pos-cam) ─────
function CameraChrome({ status, statusLabel, recording = true, kiosk = 'cam0' }) {
  return (
    <>
      <div className="grid-overlay" />
      <div className="reticle"><i/><i/></div>
      <div className={`pill-status ${status === 'aligned' ? 'ok' : ''}`}>
        <span className="ldot"/> {statusLabel}
      </div>
      {recording && (
        <div className="rec">
          <span className="d"/> REC · 30fps · 1080p · {kiosk}
        </div>
      )}
      <div className="timestamp">{new Date().toISOString().slice(0,19).replace('T',' ')}</div>
    </>
  );
}

// ── Countdown ring (3-2-1 capture) ────────────────────────────
function CountdownRing({ from = 3, onDone }) {
  const [n, setN] = useState(from);
  useEffect(() => {
    if (n <= 0) { onDone?.(); return; }
    const t = setTimeout(() => setN(v => v - 1), 1000);
    return () => clearTimeout(t);
  }, [n]);
  const C = 2 * Math.PI * 34;
  const offset = C * (1 - n / from);
  return (
    <div className="countdown-ring">
      <svg viewBox="0 0 78 78">
        <circle cx="39" cy="39" r="34" className="ring-bg"/>
        <circle cx="39" cy="39" r="34" className="ring-fg"
                strokeDasharray={C} strokeDashoffset={offset}/>
      </svg>
      <span>{n > 0 ? n : ''}</span>
    </div>
  );
}

// ── Voice waveform (live bars) ────────────────────────────────
function VoiceBars({ active = true }) {
  const [tick, setTick] = useState(0);
  useEffect(() => {
    if (!active) return;
    const t = setInterval(() => setTick(v => v + 1), 90);
    return () => clearInterval(t);
  }, [active]);
  const N = 32;
  return (
    <div className="voice-wave">
      {Array.from({ length: N }).map((_, i) => {
        const phase = (i / N) * Math.PI * 2 + tick * 0.4;
        const env = Math.sin((i + tick) * 0.27) * 0.5 + 0.5;
        const h = active ? 10 + (Math.abs(Math.sin(phase)) * 0.7 + env * 0.3) * 90 : 4;
        return <i key={i} style={{ height: `${h}%`, opacity: 0.5 + env * 0.5 }} />;
      })}
    </div>
  );
}

// ── Generic countdown text ────────────────────────────────────
function useCountdown(seconds, active, onDone) {
  const [t, setT] = useState(seconds);
  useEffect(() => {
    if (!active) { setT(seconds); return; }
    if (t <= 0) { onDone?.(); return; }
    const tm = setTimeout(() => setT(v => v - 1), 1000);
    return () => clearTimeout(tm);
  }, [active, t]);
  return t;
}

// ── BreathLine: live H2S reading climbing then settling ───────
function BreathClimb({ active, target = 42, onDone }) {
  const [val, setVal] = useState(0);
  useEffect(() => {
    if (!active) { setVal(0); return; }
    let v = 0;
    const t = setInterval(() => {
      v = Math.min(target + (Math.random() - 0.5) * 4, v + 6 + Math.random() * 4);
      if (v >= target) { v = target + (Math.random() - 0.5) * 2; }
      setVal(Math.max(0, v));
    }, 220);
    const done = setTimeout(() => { clearInterval(t); setVal(target); onDone?.(); }, 8200);
    return () => { clearInterval(t); clearTimeout(done); };
  }, [active]);
  return Math.round(val);
}

window.StatusBar = StatusBar;
window.Stepper = Stepper;
window.FaceMeshView = FaceMeshView;
window.CameraChrome = CameraChrome;
window.CountdownRing = CountdownRing;
window.VoiceBars = VoiceBars;
window.useCountdown = useCountdown;
window.BreathClimb = BreathClimb;
window.PHASES = PHASES;
