/* global React, Icon, fmtTime, speakerColor, speakerLabel, signalColor */
const { useState, useEffect, useRef } = React;

function highlightPhrase(text, phrases) {
  if (!phrases || phrases.length === 0) return text;
  // Greedy match — find the longest substring overlap
  let result = [text];
  for (const p of phrases) {
    const needle = p.toLowerCase().slice(0, 40);
    const next = [];
    for (const chunk of result) {
      if (typeof chunk !== "string") { next.push(chunk); continue; }
      const idx = chunk.toLowerCase().indexOf(needle);
      if (idx >= 0) {
        if (idx > 0) next.push(chunk.slice(0, idx));
        // find end — match up to length of needle, extended to word boundary
        let end = idx + needle.length;
        while (end < chunk.length && /\w/.test(chunk[end])) end++;
        next.push(<mark key={`${idx}-${end}`}>{chunk.slice(idx, end)}</mark>);
        if (end < chunk.length) next.push(chunk.slice(end));
      } else {
        next.push(chunk);
      }
    }
    result = next;
  }
  return result;
}

function Transcript({ timeline, roles, evidence, activeId, onSelect, hoverId }) {
  const listRef = useRef(null);
  const itemRefs = useRef({});

  useEffect(() => {
    if (activeId != null && itemRefs.current[activeId]) {
      const el = itemRefs.current[activeId];
      const list = listRef.current;
      if (list) {
        const elTop = el.offsetTop;
        const elBot = elTop + el.offsetHeight;
        const lTop = list.scrollTop;
        const lBot = lTop + list.clientHeight;
        if (elTop < lTop || elBot > lBot) {
          list.scrollTo({ top: elTop - 40, behavior: "smooth" });
        }
      }
    }
  }, [activeId]);

  const phrases = evidence.map(e => e.phrase);

  return (
    <div className="card transcript">
      <div className="section-head" style={{padding: "16px 20px 4px"}}>
        <div className="section-title">
          <span className="num">04</span>
          Transcript · diarized
        </div>
        <div className="section-sub">{timeline.length} utterances · 2 speakers</div>
      </div>
      <div className="transcript-list" ref={listRef}>
        {timeline.map((u) => {
          const isScammer = roles.scammer === u.speaker;
          const isVictim = roles.victim === u.speaker;
          const sc = speakerColor(u.speaker);
          return (
            <div
              key={u.id}
              ref={(el) => itemRefs.current[u.id] = el}
              className={`utter ${u.is_flagged ? "flagged" : ""} ${activeId === u.id ? "active" : ""} ${hoverId === u.id ? "active" : ""}`}
              onClick={() => onSelect(u.id)}
            >
              <div className="utter-rail">
                <div className={`utter-av ${sc}`}>{speakerLabel(u.speaker)}</div>
                <div className="utter-tick"></div>
              </div>
              <div>
                <div className="utter-meta">
                  <span className={`utter-spk ${sc}`}>{u.speaker === "speaker_0" ? "Speaker 0" : "Speaker 1"}</span>
                  {isScammer && <span className="utter-role scammer">Scammer</span>}
                  {isVictim && <span className="utter-role victim">Target</span>}
                  <span className="utter-time">{fmtTime(u.start)} – {fmtTime(u.end)}</span>
                </div>
                <div className="utter-text">{highlightPhrase(u.text, phrases)}</div>
                {u.is_flagged && (
                  <div className="utter-tags">
                    <span className="utter-tag danger">{u.tactic}</span>
                    <span className="utter-tag">intent: {u.intent.toLowerCase()}</span>
                    <span className="utter-tag">signal {(u.scam_signal*100).toFixed(0)}%</span>
                  </div>
                )}
              </div>
            </div>
          );
        })}
      </div>
      <div className="transcript-foot">
        <span className="audio-pos">{activeId != null ? fmtTime(timeline.find(t=>t.id===activeId)?.start || 0) : "0:00"} / {fmtTime(timeline[timeline.length-1].end)}</span>
        <div className="audio-controls">
          <button title="-15s"><Icon.back size={11}/></button>
          <button className="play"><Icon.play size={11}/></button>
          <button title="+15s"><Icon.fwd size={11}/></button>
        </div>
        <span style={{color:"var(--text-4)"}}>1.0×</span>
      </div>
    </div>
  );
}

function RolesPanel({ roles }) {
  return (
    <div className="card section">
      <div className="section-head">
        <div className="section-title">
          <span className="num">05</span>
          Role inference
        </div>
        <div className="section-sub">{roles.confidence != null && !isNaN(roles.confidence) && roles.confidence !== 0 ? Math.round(roles.confidence * 100) + "%" : "--"} conf</div>
      </div>
      <div className="roles-grid">
        <div className="role-card scammer">
          <div className="role-tag">Scammer</div>
          <div className="role-name">
            <div className="role-av">S0</div>
            <span>Speaker 0</span>
          </div>
        </div>
        <div className="role-card victim">
          <div className="role-tag">Target</div>
          <div className="role-name">
            <div className="role-av">S1</div>
            <span>Speaker 1</span>
          </div>
        </div>
      </div>
      <div className="kv">
        <span className="kv-l">Caller</span>
        <span className="kv-r mono">speaker_0</span>
      </div>
      <div className="kv">
        <span className="kv-l">Receiver</span>
        <span className="kv-r mono">speaker_1</span>
      </div>
      <div className="role-reason">
        “{roles.reasoning}”
      </div>
    </div>
  );
}

function EvidencePanel({ evidence, onSelect }) {
  return (
    <div className="card section">
      <div className="section-head">
        <div className="section-title">
          <span className="num">06</span>
          Key evidence
        </div>
        <div className="section-sub">{evidence.length} indicators</div>
      </div>
      <div className="evidence-list">
        {evidence.map((e) => (
          <div key={e.id} className="ev-item" onClick={() => onSelect(e.segment_id)}>
            <span className={`ev-bullet ${e.severity}`}></span>
            <div>
              <div className="ev-cat">{e.category} · seg {String(e.segment_id).padStart(2,"0")}</div>
              <div className="ev-phrase">“{e.phrase}”</div>
            </div>
            <span className="ev-arrow">↗</span>
          </div>
        ))}
      </div>
    </div>
  );
}

function AudioPanel({ audio }) {
  const synth = audio.scripted_delivery_score;
  const cons = audio.consistency_score;
  const synthLevel = synth > 0.7 ? "high" : synth > 0.4 ? "med" : "low";
  const consLevel = cons > 0.85 ? "low" : cons > 0.6 ? "med" : "high";
  return (
    <div className="card section">
      <div className="section-head">
        <div className="section-title">
          <span className="num">07</span>
          Voice forensics
        </div>
        <div className="section-sub">{Math.round(audio.confidence*100)}% conf</div>
      </div>
      <div className="gauge-row">
        <div className="gauge">
          <div className="gauge-label" title="Measures how natural vs scripted the speech sounds">Scripted Delivery</div>
          <div className={`gauge-val ${synthLevel}`}>{(synth*100).toFixed(0)}<span style={{fontSize:12, color:"var(--text-3)"}}>%</span></div>
          <div className="gauge-bar"><div style={{width:`${synth*100}%`, background: synthLevel === "high" ? "var(--danger)" : synthLevel === "med" ? "var(--warn)" : "var(--safe)"}}/></div>
        </div>
        <div className="gauge">
          <div className="gauge-label">Consistency</div>
          <div className="gauge-val low">{(cons*100).toFixed(0)}<span style={{fontSize:12, color:"var(--text-3)"}}>%</span></div>
          <div className="gauge-bar"><div style={{width:`${cons*100}%`, background:"var(--safe)"}}/></div>
        </div>
      </div>
      <div style={{fontSize: 10.5, letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--text-3)", marginBottom: 6}}>Anomalies</div>
      {audio.anomalies.map((a, i) => (
        <div key={i} className="anomaly">
          <span className="ic">!</span>
          <span>{a}</span>
        </div>
      ))}
    </div>
  );
}

function ReliabilityPanel({ summary, audio, roles }) {
  const overall = summary.confidence;
  const items = [
    { label: "Verdict confidence", val: overall, color: "var(--safe)" },
    { label: "Role inference",     val: roles.confidence, color: "var(--safe)" },
    { label: "Voice forensics",    val: audio.confidence, color: "var(--warn)" },
    { label: "Coverage",           val: 1 - summary.missing_segment_ratio, color: "var(--safe)" },
  ];
  return (
    <div className="card section">
      <div className="section-head">
        <div className="section-title">
          <span className="num">08</span>
          System reliability
        </div>
        <div className="section-sub mono">{Math.round(overall*100)}%</div>
      </div>
      {items.map((it) => (
        <div key={it.label} className="relia-row">
          <span style={{color:"var(--text-3)"}}>{it.label}</span>
          <span className="relia-bar"><div style={{width:`${it.val*100}%`, background: it.color}}/></span>
          <span className="mono" style={{color:"var(--text-1)", fontWeight: 500, fontSize: 12}}>
            {it.val != null && !isNaN(it.val) && it.val !== 0 ? (it.val*100).toFixed(0) + "%" : "--"}
          </span>
        </div>
      ))}
      <div style={{
        marginTop: 12, padding: "10px 12px",
        background: "oklch(0.74 0.14 155 / 0.06)",
        border: "1px solid oklch(0.74 0.14 155 / 0.2)",
        borderRadius: 8, fontSize: 11.5, color: "var(--text-2)", lineHeight: 1.5,
      }}>
        <span style={{color: "var(--safe)", fontWeight: 500}}>● No missing data.</span>{" "}
        All segments transcribed and analyzed. Verdict ready for human review.
      </div>
    </div>
  );
}

window.Transcript = Transcript;
window.RolesPanel = RolesPanel;
window.EvidencePanel = EvidencePanel;
window.AudioPanel = AudioPanel;
window.ReliabilityPanel = ReliabilityPanel;
