/* ============================================================
   Call detail modal: quality-colored waveform, playback,
   and the full 7-dimension breakdown.
   ============================================================ */
;(function(){
const { DIMS, SUBDIMS, RISK_WARN, severityColor, severityAlpha, bandColor, qualityLabel, reviewStatus, fmtTime, fmtScore, fmtClock } = window.AIData;
const { WaveformCanvas, useAudioPlayback, useEnvelope, Sparkline } = window.AIWave;
const { Icon, Badge, Overlay, closeBtn, SeverityBar, Tooltip, useIsMobile } = window.UI;

const PH_KEY = "aic_pca_playhead";

function Legend() {
  const stops = [0, 0.25, 0.5, 0.7, 0.9, 1].map((s) => severityColor(s, severityAlpha(s)));
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
      <span style={{ fontFamily: "var(--font-mono)", fontSize: 10.5, color: "var(--text-tertiary)", letterSpacing: "0.04em" }}>CLEAN</span>
      <div style={{ width: 110, height: 6, borderRadius: 999, background: `linear-gradient(90deg, ${stops.join(",")})` }} />
      <span style={{ fontFamily: "var(--font-mono)", fontSize: 10.5, color: "var(--text-tertiary)", letterSpacing: "0.04em" }}>AT RISK</span>
    </div>
  );
}

function DimRow({ dim, value, frames, isMobile }) {
  const neutral = !!dim.neutral;
  // loudness (neutral): no color · all other dimensions: traffic-light band
  const color = neutral ? "var(--gray-40)" : bandColor(value);
  const numColor = neutral ? "var(--text-secondary)" : color;
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 14, padding: "14px 2px", borderTop: "1px solid var(--border-subtle)" }}>
      <div style={{ width: 34, height: 34, flex: "0 0 auto", borderRadius: "var(--radius-md)", background: "var(--surface-sunken)", display: "flex", alignItems: "center", justifyContent: "center" }}>
        <Icon name={dim.icon} size={17} color={neutral ? "var(--text-tertiary)" : color} />
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <span style={{ fontSize: 14, fontWeight: 600, color: "var(--text-primary)" }}>{dim.label}</span>
        </div>
        {!isMobile && <div style={{ fontSize: 12.5, color: "var(--text-tertiary)", marginTop: 2, lineHeight: 1.45 }}>{dim.desc}</div>}
        {!isMobile && dim.downstream && (
          <div style={{ fontSize: 11, fontFamily: "var(--font-mono)", color: "var(--text-tertiary)", marginTop: 5, letterSpacing: "0.01em" }}>
            <span style={{ color: "var(--text-secondary)" }}>Downstream</span> · {dim.downstream}
          </div>
        )}
      </div>
      <div style={{ flex: "0 0 auto", opacity: 0.95 }}><Sparkline series={frames} width={isMobile ? 96 : 120} height={30} /></div>
      <div style={{ width: 64, flex: "0 0 auto", textAlign: "right" }}>
        <div style={{ fontFamily: "var(--font-mono)", fontSize: 18, fontWeight: 500, color: numColor, lineHeight: 1 }}>{fmtScore(value)}</div>
        <div style={{ marginTop: 7 }}><SeverityBar value={value} neutral={neutral} color={neutral ? undefined : color} /></div>
      </div>
    </div>
  );
}

function CallModal({ call, onClose, riskMetric = "p95" }) {
  const isMobile = useIsMobile();
  const { playing, currentTime, duration, toggle, seek } = useAudioPlayback(call);
  const envelope = useEnvelope(call);

  // restore / persist playhead for this call (survives refresh during review)
  React.useEffect(() => {
    try {
      const saved = JSON.parse(localStorage.getItem(PH_KEY) || "{}");
      if (saved && String(saved.id) === String(call.id) && saved.t) seek(saved.t);
    } catch (e) {}
  }, [call]);
  React.useEffect(() => {
    try { localStorage.setItem(PH_KEY, JSON.stringify({ id: call.id, t: currentTime })); } catch (e) {}
  }, [call, currentTime]);

  const q = riskMetric === "p95" ? call.metrics.p95 : call.scores.risk_score; // match the table's metric
  const qColor = severityColor(Math.max(0.3, q));
  const rs = reviewStatus(q);
  // "why does it fail?": the dominant dimension (per-dimension argmax) + its downstream risk
  const drv = call.driver;
  const driverRisk = drv
    ? (drv.low ? "quiet speech may be missed by VAD/STT" : (DIMS.find((d) => d.key === drv.key) || {}).downstream)
    : "";
  const interp = q < RISK_WARN
    ? "Clean input. Safe for every downstream model."
    : (drv && drv.value > 0.12)
      ? `Risk driven by ${drv.label.toLowerCase()}${driverRisk ? `: ${driverRisk}` : ""}.`
      : "Minor degradation. Low downstream risk.";

  return (
    <Overlay onClose={onClose}>
      <div style={{ width: isMobile ? "100%" : "min(940px, 95vw)" }}>
        {/* header */}
        <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 16, marginBottom: 18 }}>
          <div style={{ minWidth: 0 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
              <Icon name="waveform" size={18} color="var(--blue-40)" style={{ flex: "0 0 auto" }} />
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 17, color: "var(--text-primary)", minWidth: 0, overflowWrap: "anywhere" }}>{call.file}</span>
            </div>
            <div style={{ fontSize: 13, color: "var(--text-secondary)", marginTop: 6 }}>
              {fmtClock(call.started)} · {fmtTime(call.durationSec)}
            </div>
          </div>
          <div style={{ display: "flex", alignItems: "center", gap: 12, flex: "0 0 auto" }}>
            <span style={{ display: "inline-flex", alignItems: "center", gap: 9 }}>
              <span style={{ width: 10, height: 10, borderRadius: "50%", background: rs.color, boxShadow: rs.key !== "ok" ? `0 0 0 4px ${rs.glow}` : "none", flex: "0 0 auto" }} />
              <span style={{ fontSize: 13.5, fontWeight: 600, color: rs.color }}>{rs.label}</span>
            </span>
            <button onClick={onClose} style={closeBtn} aria-label="Close"><Icon name="xmark" size={16} color="var(--text-secondary)" /></button>
          </div>
        </div>

        {/* waveform */}
        <div style={{ background: "var(--surface-sunken)", border: "1px solid var(--border-subtle)", borderRadius: "var(--radius-md)", padding: "16px 18px 14px" }}>
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 8 }}>
            <span style={{ fontFamily: "var(--font-mono)", fontSize: 10.5, letterSpacing: "0.07em", textTransform: "uppercase", color: "var(--text-tertiary)" }}>Risk over time</span>
            <Legend />
          </div>
          <WaveformCanvas call={call} currentTime={currentTime} duration={duration} onSeek={seek} height={168} envelope={envelope} />
          {/* controls */}
          <div style={{ display: "flex", alignItems: "center", gap: 16, marginTop: 12 }}>
            <button onClick={toggle} style={{
              width: 50, height: 50, borderRadius: "50%", flex: "0 0 auto", cursor: "pointer",
              border: "none", background: "var(--blue-50)", display: "flex", alignItems: "center", justifyContent: "center",
              boxShadow: "var(--shadow-md)", transition: "background var(--dur-fast)",
            }}
              onMouseEnter={(e) => (e.currentTarget.style.background = "var(--blue-60)")}
              onMouseLeave={(e) => (e.currentTarget.style.background = "var(--blue-50)")}>
              <Icon name={playing ? "pause.fill" : "play.fill"} size={20} color="#fff" style={{ marginLeft: playing ? 0 : 2 }} />
            </button>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 14, color: "var(--text-primary)" }}>
              {fmtTime(currentTime)} <span style={{ color: "var(--text-tertiary)" }}>/ {fmtTime(duration)}</span>
            </div>
            <div style={{ flex: 1 }} />
            <span style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 12, color: "var(--text-tertiary)" }}>
              <Icon name="info.circle.fill" size={13} color="var(--text-tertiary)" />
              {call.audioUrl ? "Playing source audio" : "Click the waveform to scrub"}
            </span>
          </div>
        </div>

        {/* headline quality */}
        <div style={{ display: "flex", flexDirection: isMobile ? "column" : "row", alignItems: isMobile ? "flex-start" : "center", gap: isMobile ? 12 : 20, marginTop: 18, padding: isMobile ? "16px" : "18px 20px", borderRadius: "var(--radius-md)", border: `1px solid var(--border-subtle)`, background: `linear-gradient(90deg, ${severityColor(Math.max(0.3, q), 0.1)}, transparent 70%)` }}>
          <div style={{ flex: "0 0 auto" }}>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 10.5, letterSpacing: "0.07em", textTransform: "uppercase", color: "var(--text-tertiary)", marginBottom: 6 }}>Tyto Risk Score · {riskMetric === "p95" ? "p95" : "mean"}</div>
            <div style={{ display: "flex", alignItems: "baseline", gap: 12 }}>
              <span style={{ fontFamily: "var(--font-display)", fontSize: isMobile ? 40 : 52, lineHeight: 1, letterSpacing: "-0.02em", color: qColor }}>{fmtScore(q)}</span>
              <span style={{ fontSize: 15, fontWeight: 600, color: qColor }}>{qualityLabel(q)}</span>
            </div>
          </div>
          {!isMobile && <div style={{ width: 1, alignSelf: "stretch", background: "var(--border-subtle)" }} />}
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 14.5, color: "var(--text-primary)", lineHeight: 1.5 }}>{interp}</div>
            <div style={{ fontSize: 12.5, color: "var(--text-tertiary)", marginTop: 6 }}>Predicts downstream failure likelihood across STT, VAD, turn-taking and speech-to-speech. Lower is better.</div>
          </div>
        </div>

        {/* breakdown */}
        <div style={{ marginTop: 20 }}>
          <div style={{ fontFamily: "var(--font-mono)", fontSize: 10.5, letterSpacing: "0.07em", textTransform: "uppercase", color: "var(--text-tertiary)", marginBottom: 2 }}>Dimension breakdown</div>
          <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr" : "1fr 1fr", columnGap: 28 }}>
            {SUBDIMS.map((d) => (
              <DimRow key={d.key} dim={d} value={call.scores[d.key]} frames={call.frames[d.key]} isMobile={isMobile} />
            ))}
          </div>
        </div>
      </div>
    </Overlay>
  );
}

window.AIModal = { CallModal };
})();
