// viewbot.info — for creators (self-scan)

const { useState: useStateC, useEffect: useEffectC, useMemo: useMemoC, useRef: useRefC } = React;

// ─── sample profiles for the demo (mock) ───
const CREATOR_SAMPLES = {
  pass: {
    handle: 'case-051',
    plat: 'twitch',
    cat: 'VALORANT',
    medianViewers: 1840,
    streams: 47,
    fileName: 'twitch-analytics-export-case-051.csv',
    scores: {
      velocity: 84, rigidity: 91, category: 78,
      game: 86, engagement: 88, rank: 92,
      deviation: 81, repetition: 89,
    },
    headline: 'Your audience looks real.',
    body: 'Across 47 streams, your viewer counts moved with category traffic, your engagement scaled with viewers, and your historical baseline matched today within tolerance.',
    seal: '✓ ELIGIBLE FOR VERIFIED · BRAND DIRECTORY',
  },
  watch: {
    handle: 'case-052',
    plat: 'kick',
    cat: 'Just Chatting',
    medianViewers: 920,
    streams: 32,
    fileName: 'kick-creator-data-case-052.json',
    scores: {
      velocity: 58, rigidity: 38, category: 54,
      game: 62, engagement: 48, rank: 51,
      deviation: 44, repetition: 56,
    },
    headline: 'Borderline. We need a second pass.',
    body: 'Two signals — Audience Rigidity and Historical Deviation — flagged anomalies but did not breach the fail threshold. This usually means a third-party promotion service or a recent algorithmic boost. Submit context and we will re-score.',
    seal: '? UNDER REVIEW · SECOND-PASS REQUIRED',
  },
  fail: {
    handle: 'case-053',
    plat: 'kick',
    cat: 'Slots & Casino',
    medianViewers: 4980,
    streams: 22,
    fileName: 'kick-creator-data-case-053.json',
    scores: {
      velocity: 14, rigidity: 12, category: 18,
      game: 22, engagement: 11, rank: 28,
      deviation: 19, repetition: 16,
    },
    headline: 'Your audience does not look real.',
    body: 'Across 22 streams your CCV held within a 1.7% band, your chat velocity decoupled from your viewer count, and your audience did not respond to category surges or dead hours. This is the rigidity fingerprint of a paid floor.',
    seal: '! HIGH RISK · NOT BRAND-SAFE',
  },
};

const SCAN_STEPS = [
  { id: 1, lbl: 'INGEST',   nm: 'Reading export file headers and schema' },
  { id: 2, lbl: 'NORMALIZE',nm: 'Reconciling timestamps · UTC' },
  { id: 3, lbl: 'SAMPLE',   nm: 'Re-sampling CCV at 30s intervals' },
  { id: 4, lbl: 'BASELINE', nm: 'Joining historical category baselines' },
  { id: 5, lbl: 'CORRELATE',nm: 'Computing peer co-movement window' },
  { id: 6, lbl: 'SCORE',    nm: 'Running 8-score model · v3.2.1' },
  { id: 7, lbl: 'VERDICT',  nm: 'Issuing report' },
];

function ResultEmpty() {
  return (
    <div className="result-empty">
      <div className="glyph">◇</div>
      <div className="card-title" style={{ color: 'var(--text-2)' }}>Awaiting input</div>
      <span className="label">
        Upload an export · connect a platform · or pick a sample below
      </span>
    </div>
  );
}

function ResultScanning({ steps, currentStep, sample }) {
  return (
    <div className="result-scanning">
      <div className="row-between" style={{ marginBottom: 4 }}>
        <span className="card-title"><span className="dot"></span>SCANNING / {sample?.handle?.toUpperCase()}</span>
        <span className="chip">model v3.2.1</span>
      </div>
      {steps.map((s, i) => {
        const cls = i < currentStep ? 'done' : i === currentStep ? 'run' : '';
        return (
          <div className={'step ' + cls} key={s.id}>
            <span className="g">{i < currentStep ? '✓' : i === currentStep ? '▸' : i+1}</span>
            <span className="lbl">{s.lbl}</span>
            <span className="nm">{s.nm}</span>
            <span className="v">{i < currentStep ? 'OK' : i === currentStep ? '…' : ''}</span>
          </div>
        );
      })}
    </div>
  );
}

function ResultVerdict({ sample, scores }) {
  // overall = weighted avg approx
  const weights = { velocity: 18, rigidity: 16, category: 14, game: 14, engagement: 12, rank: 10, deviation: 8, repetition: 8 };
  const totalW = Object.values(weights).reduce((a,b)=>a+b,0);
  const overall = Math.round(SCORE_DEFS.reduce((sum, def) => sum + (scores[def.key] * weights[def.key]), 0) / totalW);
  const tier = overall < 35 ? 'fail' : overall < 65 ? 'watch' : 'pass';
  const tierLabel = tier === 'pass' ? 'PASS' : tier === 'watch' ? 'WATCH' : 'FAIL';

  return (
    <>
      <div className={'result-verdict ' + tier}>
        <div className="ring">
          <ScoreRing value={overall} size={84}/>
        </div>
        <div>
          <span className={'label'} style={{
            color: tier === 'pass' ? 'var(--green)' : tier === 'watch' ? 'var(--yellow)' : 'var(--red)'
          }}>
            VERDICT · {tierLabel}
          </span>
          <h4 className={tier}>{sample.headline}</h4>
          <p>{sample.body}</p>
        </div>
        <div className="seal">{sample.seal}</div>
      </div>

      <div className="result-scores">
        {SCORE_DEFS.map(def => {
          const v = scores[def.key];
          const cls = v < 35 ? 'red' : v < 65 ? 'yellow' : 'green';
          return (
            <div className="result-score" key={def.key}>
              <span className="nm">{def.idx} · {def.short}</span>
              <span className={'v ' + cls}>{v}</span>
              <div className="bar"><div style={{ width: v + '%', background: `var(--${cls === 'red' ? 'red' : cls === 'yellow' ? 'yellow' : 'green'})` }}/></div>
            </div>
          );
        })}
      </div>

      <div className="result-actions">
        <span className="label">
          Snapshot · {new Date().toISOString().slice(0,16).replace('T',' ')} UTC · MODEL v3.2.1
        </span>
        <div style={{ display: 'flex', gap: 8 }}>
          {tier === 'pass' && <button className="btn green">REQUEST VERIFIED BADGE</button>}
          {tier === 'watch' && <button className="btn">SUBMIT CONTEXT</button>}
          {tier === 'fail' && <button className="btn">REQUEST APPEAL</button>}
          <button className="btn">EXPORT PDF</button>
          <button className="btn">SHARE</button>
        </div>
      </div>
    </>
  );
}

function ForCreators() {
  const [stage, setStage] = useStateC('idle'); // idle | scanning | done
  const [sample, setSample] = useStateC(null);
  const [step, setStep] = useStateC(0);
  const [drag, setDrag] = useStateC(false);

  // run scan animation
  useEffectC(() => {
    if (stage !== 'scanning') return;
    setStep(0);
    let i = 0;
    const id = setInterval(() => {
      i++;
      setStep(i);
      if (i >= SCAN_STEPS.length) {
        clearInterval(id);
        setTimeout(() => setStage('done'), 350);
      }
    }, 420);
    return () => clearInterval(id);
  }, [stage]);

  const start = (sampleKey) => {
    setSample(CREATOR_SAMPLES[sampleKey]);
    setStage('scanning');
  };

  const reset = () => { setStage('idle'); setSample(null); setStep(0); };

  const previewSnippet = useMemoC(() => {
    if (!sample) return null;
    const isCsv = sample.fileName.endsWith('.csv');
    if (isCsv) {
      return (
`<span class="k">stream_id,timestamp,ccv,chatters,messages</span>
01,2026-05-18T19:00:00Z,<span class="n">1842</span>,<span class="n">124</span>,<span class="n">228</span>
01,2026-05-18T19:00:30Z,<span class="n">1908</span>,<span class="n">131</span>,<span class="n">241</span>
01,2026-05-18T19:01:00Z,<span class="n">2014</span>,<span class="n">142</span>,<span class="n">266</span>
01,2026-05-18T19:01:30Z,<span class="n">2188</span>,<span class="n">156</span>,<span class="n">281</span>
… <span class="s">47 streams · 22,140 rows ingested</span>`);
    } else {
      return (
`{
  <span class="k">"channel"</span>: <span class="s">"${sample.handle}"</span>,
  <span class="k">"platform"</span>: <span class="s">"${sample.plat}"</span>,
  <span class="k">"streams"</span>: <span class="n">${sample.streams}</span>,
  <span class="k">"median_ccv"</span>: <span class="n">${sample.medianViewers}</span>,
  <span class="k">"samples"</span>: [
    { <span class="k">"t"</span>: <span class="n">0</span>,   <span class="k">"ccv"</span>: <span class="n">${sample.medianViewers - 60}</span>, <span class="k">"chat"</span>: <span class="n">12</span> },
    { <span class="k">"t"</span>: <span class="n">30</span>,  <span class="k">"ccv"</span>: <span class="n">${sample.medianViewers + 10}</span>, <span class="k">"chat"</span>: <span class="n">14</span> },
    <span class="s">… 22,140 rows ingested</span>
  ]
}`);
    }
  }, [sample]);

  return (
    <section className="section" id="creators">
      <div className="section-inner">
        <div className="section-head">
          <span className="eyebrow">FOR CREATORS · BETA</span>
          <h2>Sponsors will ask. <span className="accent">Get ahead of it.</span></h2>
          <p>
            Pull your analytics export from Twitch, Kick, or Rumble — drop it in and run the same eight-score model brands run against you. Pass and you can apply for a verified badge. Fail and you'll see exactly what the model saw, with enough detail to fix it or appeal it.
          </p>
        </div>

        <div className="creator-grid">
          {/* upload panel */}
          <div className="card upload-panel">
            <div className="card-head" style={{ padding: 0, paddingBottom: 14, borderBottom: 'none' }}>
              <span className="card-title"><span className="dot"></span>SELF_SCAN.UPLOAD</span>
              <span className="card-aux">CSV · JSON · ZIP &lt; 25MB</span>
            </div>

            <div
              className={'dropzone ' + (drag ? 'drag' : '')}
              onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
              onDragLeave={() => setDrag(false)}
              onDrop={(e) => { e.preventDefault(); setDrag(false); start('pass'); }}
              onClick={() => start('pass')}
            >
              <div className="drop-glyph">↥</div>
              <div className="drop-title">Drop your analytics export here</div>
              <div className="drop-sub">
                <span style={{color:'var(--text-2)'}}>or </span>
                <span style={{color:'var(--green)', textDecoration:'underline', textUnderlineOffset: 3}}>browse files</span>
              </div>
              <div className="drop-sub" style={{ marginTop: 6 }}>
                Twitch · Analytics → Export CSV &nbsp;·&nbsp;
                Kick · Creator Dashboard → Data &nbsp;·&nbsp;
                Rumble · Studio → Export JSON
              </div>
            </div>

            <div>
              <span className="label" style={{ display: 'block', marginBottom: 8 }}>OR CONNECT YOUR ACCOUNT</span>
              <div className="platform-row">
                <button className="plat-btn" onClick={() => start('pass')}>
                  <Plat p="twitch" size={14}/> TWITCH
                </button>
                <button className="plat-btn" onClick={() => start('watch')}>
                  <Plat p="kick" size={14}/> KICK
                </button>
                <button className="plat-btn" onClick={() => start('fail')}>
                  <Plat p="rumble" size={14}/> RUMBLE
                </button>
              </div>
              <div className="muted-3" style={{ fontSize: 11, letterSpacing: '0.08em', textTransform: 'uppercase', marginTop: 10 }}>
                READ-ONLY · ANALYTICS SCOPE ONLY · YOU CAN DISCONNECT ANY TIME
              </div>
            </div>

            <div>
              <span className="label" style={{ display: 'block', marginBottom: 8 }}>OR TRY A SAMPLE PROFILE</span>
              <div className="sample-row">
                <button className="sample-btn pass" onClick={() => start('pass')}>
                  <span className="nm">▸ case-051 · valorant · twitch</span>
                  <span className="ds">expected verdict · pass · 87 overall</span>
                </button>
                <button className="sample-btn fail" onClick={() => start('fail')}>
                  <span className="nm">▸ case-053 · slots · kick</span>
                  <span className="ds">expected verdict · fail · 18 overall</span>
                </button>
              </div>
              <button className="sample-btn" style={{ marginTop: 8, width: '100%' }} onClick={() => start('watch')}>
                <span className="nm">▸ case-052 · just chatting · kick</span>
                <span className="ds">expected verdict · watch · 52 overall · borderline second-pass case</span>
              </button>
            </div>

            <div className="muted-3" style={{ fontSize: 11, letterSpacing: '0.06em', textTransform: 'uppercase', borderTop: '1px solid var(--border)', paddingTop: 14, lineHeight: 1.6 }}>
              ※ Your file never leaves your account. Reports are private until you choose to share. Verified status, once granted, is published in the brand directory.
            </div>
          </div>

          {/* result panel */}
          <div className="card result-panel">
            <div className="card-head">
              <span className="card-title">
                <span className={'dot ' + (stage === 'done' && sample ? (sample === CREATOR_SAMPLES.fail ? 'red' : sample === CREATOR_SAMPLES.watch ? '' : '') : '')}></span>
                SELF_SCAN.RESULT {sample ? '/ ' + sample.handle.toUpperCase() : ''}
              </span>
              <span className="card-aux">
                {stage === 'idle' && 'READY'}
                {stage === 'scanning' && 'SCANNING · ' + Math.min(step+1, SCAN_STEPS.length) + '/' + SCAN_STEPS.length}
                {stage === 'done' && (
                  <button className="btn" onClick={reset} style={{ height: 26, padding: '0 10px', fontSize: 10.5 }}>
                    ↺ NEW SCAN
                  </button>
                )}
              </span>
            </div>

            {stage === 'idle' && <ResultEmpty/>}

            {stage === 'scanning' && (
              <>
                <ResultScanning steps={SCAN_STEPS} currentStep={step} sample={sample}/>
                <div style={{ padding: '14px 24px 20px', borderTop: '1px solid var(--border)' }}>
                  <div className="label" style={{ marginBottom: 8 }}>FILE · {sample.fileName}</div>
                  <div className="preview-pre" dangerouslySetInnerHTML={{ __html: previewSnippet }}/>
                </div>
              </>
            )}

            {stage === 'done' && sample && (
              <ResultVerdict sample={sample} scores={sample.scores}/>
            )}
          </div>
        </div>

        {/* tier callouts */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12, marginTop: 24 }}
             className="creator-tiers">
          <div className="card" style={{ padding: 22 }}>
            <div className="card-title" style={{ color: 'var(--green)' }}><span className="dot"></span>IF YOU PASS</div>
            <p className="muted" style={{ fontSize: 14, lineHeight: 1.6, marginTop: 14 }}>
              You can request a verified badge on your dossier, opt into the brand-safety directory, and link the report from your media kit.
            </p>
          </div>
          <div className="card" style={{ padding: 22, borderColor: 'var(--yellow-line)' }}>
            <div className="card-title" style={{ color: 'var(--yellow)' }}><span className="dot" style={{ background: 'var(--yellow)', boxShadow: '0 0 8px var(--yellow)' }}></span>IF YOU'RE BORDERLINE</div>
            <p className="muted" style={{ fontSize: 14, lineHeight: 1.6, marginTop: 14 }}>
              You'll see exactly which two or three signals tripped. Submit context — promotions, raids, embeds — and we'll re-score within 48 hours.
            </p>
          </div>
          <div className="card" style={{ padding: 22, borderColor: 'var(--red-line)' }}>
            <div className="card-title" style={{ color: 'var(--red)' }}><span className="dot red"></span>IF YOU FAIL</div>
            <p className="muted" style={{ fontSize: 14, lineHeight: 1.6, marginTop: 14 }}>
              You'll get the same evidence dossier brands and reporters get — every failed signal, the threshold, your number, and the specific time windows. Appeals are public.
            </p>
          </div>
        </div>
      </div>
    </section>
  );
}

Object.assign(window, { ForCreators });
