// viewbot.info — dossier modal v2

const { useState: useStateD, useEffect: useEffectD, useMemo: useMemoD } = React;

function Dossier({ streamer, onClose }) {
  useEffectD(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => { document.removeEventListener('keydown', onKey); document.body.style.overflow = ''; };
  }, [onClose]);

  const verdictMap = {
    botted:   { cls: 'red',    label: 'BOTTED',          tag: 'CONFIRMED' },
    review:   { cls: 'yellow', label: 'UNDER REVIEW',    tag: 'INVESTIGATING' },
    legit:    { cls: 'green',  label: 'LEGIT',           tag: 'CLEARED' },
    reformed: { cls: 'green',  label: 'REFORMED',        tag: 'CLEARED' },
  }[streamer.status] || { cls: '', label: '—', tag: '' };

  // 8-score block — derive or fall back
  const scores = streamer.scores || (() => {
    const r = rng(streamer.name.length*7);
    const base = streamer.status === 'botted' ? 16 : streamer.status === 'review' ? 46 : 82;
    const out = {};
    SCORE_DEFS.forEach(d => { out[d.key] = Math.max(2, Math.min(99, Math.round(base + (r()-0.5)*22))); });
    return out;
  })();

  // specific evidence callouts — generated from the streamer's numbers
  const callouts = useMemoD(() => {
    const list = [];
    if (scores.velocity < 35) list.push({
      lvl: 'err', msg: `Viewer count rose +${Math.floor(streamer.viewers*0.62)} (+62%) in 4 minutes with no matching chat, raid, or external embed.`,
      ref: 't=08:42 · velocity_score 14'
    });
    if (scores.rigidity < 35) list.push({
      lvl: 'err', msg: `CCV remained within a 1.7% band (4,920–5,090) across 5 different games over the last 14 streams.`,
      ref: 'rigidity_score 12 · σ²=0.004'
    });
    if (scores.category < 35) list.push({
      lvl: 'err', msg: `Category peers fluctuated ±42% during the same window. This channel moved ±0.4%.`,
      ref: 'category_corr = 0.04'
    });
    if (scores.game < 35) list.push({
      lvl: 'warn', msg: `Game switch ${streamer.cat || 'Just Chatting'} → indie test stream produced 0% audience drop. Peer drop median: 58%.`,
      ref: 'game_elasticity 18'
    });
    if (scores.engagement < 35) list.push({
      lvl: 'err', msg: `Chat velocity ${(streamer.eng*2.4).toFixed(1)} msg/min — expected ${(streamer.viewers*0.04).toFixed(0)}/min at ${fmt(streamer.viewers)} viewers.`,
      ref: 'engagement_coupling 11'
    });
    if (scores.rank < 35) list.push({
      lvl: 'warn', msg: `Viewer boosts arrived within 90s of rank #6 threshold dropping. Vanished at stream end across 9/12 sessions.`,
      ref: 'rank_targeting 22'
    });
    if (scores.deviation < 35) list.push({
      lvl: 'err', msg: `Today's CCV exceeds this creator's 90-day baseline by 8.4σ for this game / time slot.`,
      ref: 'historical_deviation 19'
    });
    if (scores.repetition < 35) list.push({
      lvl: 'err', msg: `Same fingerprint detected in ${Math.floor(12 + (streamer.name.length % 4))} of last 15 streams.`,
      ref: 'repetition 14'
    });
    // legit-only positive callouts
    if (streamer.status === 'legit' || streamer.status === 'reformed') {
      list.push({ lvl: 'ok', msg: 'Audience expanded with category surge during tournament window. Lurker ratio consistent with niche community baseline.', ref: 'category_corr = 0.71' });
      list.push({ lvl: 'ok', msg: 'CCV varied ±34% across last 14 streams. Game switches produced expected audience drops.', ref: 'rigidity 86 · σ²=0.39' });
    }
    return list;
  }, [streamer.name, scores]);

  // activity log
  const activity = useMemoD(() => {
    const r = rng(streamer.name.length + 13);
    return [
      { t: 't-00:08', lvl: 'warn', msg: 'sample · CCV 5,042 · chatters 84 · ratio 1.67%' },
      { t: 't-00:38', lvl: 'warn', msg: 'sample · CCV 5,061 · chatters 88 · ratio 1.74%' },
      { t: 't-01:08', lvl: 'err',  msg: 'velocity spike · +412 in 14s · no raid event · cluster #'+(Math.floor(r()*9000)) },
      { t: 't-01:38', lvl: 'warn', msg: 'sample · CCV 5,478 · chatters 91 · ratio 1.66%' },
      { t: 't-02:08', lvl: 'err',  msg: 'lexical_score 0.83 · cluster match "yt-bot-v4" · '+(Math.floor(r()*3000+2000))+' prior matches' },
      { t: 't-02:38', lvl: 'ok',   msg: 'peer cohort delta · '+(Math.floor(r()*40+10))+'% · target delta · 0.4%' },
      { t: 't-03:08', lvl: 'err',  msg: 'rigidity_score recomputed · 12 / 100 · band 4,920–5,090' },
      { t: 't-03:38', lvl: 'warn', msg: 'category shift · '+(streamer.cat||'IRL')+' → Just Chatting · expected drop 32% · actual 0.2%' },
      { t: 't-04:08', lvl: 'err',  msg: 'verdict_update · status → BOTTED · confidence 0.94' },
    ];
  }, [streamer.name]);

  return (
    <div className="modal-scrim" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div className="card-title">
            <span className={'dot ' + (verdictMap.cls === 'red' ? 'red' : '')}></span>
            DOSSIER / {streamer.name.toUpperCase()}
          </div>
          <div style={{ display: 'flex', gap: 12, alignItems: 'center' }}>
            <span className="chip">esc to close</span>
            <button className="btn" onClick={onClose} style={{ height: 28, padding: '0 10px' }}>✕</button>
          </div>
        </div>

        <div className="modal-body">

          {/* header */}
          <div className="dossier-hdr">
            <Avatar name={streamer.name} palette={streamer.avatar} size={72} ringStatus={streamer.status} live/>
            <div className="meta">
              <h3>{streamer.name}</h3>
              <div className="sub">
                <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
                  <Plat p={streamer.plat} size={14}/> {streamer.plat}.com / {streamer.name}
                </span>
                <span>· {streamer.cat}</span>
                <span>· {fmt(streamer.viewers)} viewers</span>
                <span>· {streamer.eng}% engagement</span>
              </div>
              <div style={{ display: 'flex', gap: 8, marginTop: 8, flexWrap: 'wrap' }}>
                <StatusBadge status={streamer.status}/>
                <span className="chip">FIRST FLAGGED · 2025-09-14</span>
                <span className="chip">LAST SCAN · 2m AGO</span>
                <span className="chip">{callouts.length} EVIDENCE ITEMS</span>
              </div>
            </div>
            <div className="verdict">
              <div className={'verdict-score ' + verdictMap.cls}>{streamer.score}</div>
              <span className="label" style={{ color: verdictMap.cls === 'red' ? 'var(--red)' : verdictMap.cls === 'yellow' ? 'var(--yellow)' : 'var(--green)' }}>
                INORGANIC TRAFFIC · {verdictMap.label}
              </span>
              <span className="label" style={{ fontSize: 10 }}>{verdictMap.tag} · CONF 0.94</span>
            </div>
          </div>

          {/* 8 scores */}
          <div className="dossier-scores">
            {SCORE_DEFS.map(def => {
              const v = scores[def.key];
              const col = v < 35 ? 'red' : v < 65 ? 'yellow' : 'green';
              return (
                <div className="dossier-score" key={def.key}>
                  <h5>
                    <span>{def.idx} · {def.short}</span>
                    <span className="chip" style={{ fontSize: 9.5, padding: '1px 5px' }}>{def.short}</span>
                  </h5>
                  <span className={'v ' + col}>{v}</span>
                  <span className="delta">{def.name}</span>
                  <div className="bar">
                    <div style={{
                      width: v + '%',
                      background: v < 35 ? 'var(--red)' : v < 65 ? 'var(--yellow)' : 'var(--green)',
                    }}/>
                  </div>
                </div>
              );
            })}
          </div>

          {/* primary reasons */}
          <div className="callouts">
            <h5>PRIMARY REASONS · WHY THIS VERDICT</h5>
            {callouts.length === 0 ? (
              <div className="callout">
                <span className="lvl ok">OK</span>
                <span className="msg">No signals exceeded threshold during the latest 30-min window.</span>
                <span className="ref">model v3.2.1</span>
              </div>
            ) : callouts.map((c, i) => (
              <div key={i} className="callout">
                <span className={'lvl ' + c.lvl}>{c.lvl === 'err' ? 'FAIL' : c.lvl === 'warn' ? 'WARN' : 'PASS'}</span>
                <span className="msg">{c.msg}</span>
                <span className="ref">{c.ref}</span>
              </div>
            ))}
          </div>

          {/* activity feed */}
          <div className="activity">
            <div className="row-between" style={{ marginBottom: 8 }}>
              <span className="label">ACTIVITY_FEED · TAIL · 30-MIN WINDOW</span>
              <span className="chip">SHA · {(streamer.name.length * 1337).toString(16)}{streamer.score.toString(16)}…</span>
            </div>
            {activity.map((e, i) => (
              <div className="row" key={i}>
                <span className="t">{e.t}</span>
                <span className={'lvl ' + e.lvl}>{e.lvl.toUpperCase()}</span>
                <span>{e.msg}</span>
              </div>
            ))}
          </div>

          {/* footer */}
          <div style={{ padding: '18px 22px', borderTop: '1px solid var(--border)', display: 'flex', gap: 10, flexWrap: 'wrap', justifyContent: 'space-between', alignItems: 'center' }}>
            <span className="label">
              All scans independent · no platform partnership · model v3.2.1-forensic
            </span>
            <div style={{ display: 'flex', gap: 8 }}>
              <button className="btn">SHARE</button>
              <button className="btn">EXPORT JSON</button>
              <button className="btn purple">SUBMIT APPEAL</button>
            </div>
          </div>

        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Dossier });
