/* Screen I — Scoring Methodology (Phase 2)
   Editorial transparency page: pipeline funnel, sub-score explainers,
   interactive weight tuning, honest disclosure. */

var METH_DIMS = [
  {
    key: 'relevance', label: 'Relevance', weight: 0.35,
    blurb: 'Does their bio show they work on what Howard cares about?',
    formula: 'match_count(bio, domain_keywords) / 5, clamped [0,1]',
    plain: 'How many AI/ML domain keywords appear in the bio, capped at 5 hits.',
    field: 'bio + domain dictionary',
    xsignal: 'Content Signal',
    examples: [
      { lvl: 'HIGH', who: '@francis_yao_', detail: '"Scaling @xAI. Previously Gemini 3 perception @GoogleDeepMind"', val: '0.80' },
      { lvl: 'MID', who: '@billyuchenlin', detail: '"RL for coding @xAI @SpaceX. Ex: @allen_ai; Google, Meta FAIR"', val: '0.60' },
      { lvl: 'LOW', who: '@zhang_yunzhi', detail: 'empty bio', val: '0.00' },
    ],
  },
  {
    key: 'amplification', label: 'Amplification', weight: 0.25,
    blurb: 'How many people can they reach — is there a multiplier if Howard engages?',
    formula: 'log10(followers + 1) / log10(cohort_max_followers)',
    plain: 'Follower reach on a log scale, normalized against the cohort max (44,983).',
    field: 'followers',
    xsignal: 'Author Quality',
    examples: [
      { lvl: 'HIGH', who: '@milichab', detail: '44,983 followers', val: '1.00' },
      { lvl: 'MID', who: '@gtr32x', detail: '231 followers', val: '0.51' },
      { lvl: 'LOW', who: '@suyan_', detail: '1 follower', val: '0.07' },
    ],
  },
  {
    key: 'reciprocity', label: 'Reciprocity', weight: 0.20,
    blurb: 'Is the cohort talking about them — are they a high-value node?',
    formula: 'in_cohort_edges / 50',
    plain: 'How many cohort members interact with them (replies, quotes, RTs, mentions).',
    field: 'xai-graph-7d in-cohort edges',
    xsignal: 'Real Graph W_ij',
    examples: [
      { lvl: 'HIGH', who: '@stepango', detail: '49 in-cohort edges', val: '0.98' },
      { lvl: 'MID', who: '@parsatajik', detail: '2 in-cohort edges', val: '0.04' },
      { lvl: 'LOW', who: 'cohort-isolated', detail: '0 edges', val: '0.00' },
    ],
  },
  {
    key: 'approachability', label: 'Approachability', weight: 0.10,
    blurb: 'Can Howard realistically start a conversation?',
    formula: '1 − log10(followers+1)/log10(50k), boosted if "DMs open" / "hiring"',
    plain: 'Inverse of reach — smaller accounts and explicit openness score higher.',
    field: 'bio + followers',
    xsignal: 'Author Diversity (inverse)',
    examples: [
      { lvl: 'HIGH', who: '@garyzhao9012', detail: '138 followers, MTS', val: '1.00' },
      { lvl: 'MID', who: '@hexiang', detail: '4.4k followers', val: '0.62' },
      { lvl: 'LOW', who: '@milichab', detail: '45k followers', val: '0.18' },
    ],
  },
  {
    key: 'recency', label: 'Recency', weight: 0.10,
    blurb: 'Are they still active in this space right now?',
    formula: '0.4 + 0.6 × log10(posts_30d+1)/log10(101), 0 if silent',
    plain: 'Posting volume over the last 30 days — dormant accounts score zero.',
    field: 'tweets[30d]',
    xsignal: 'Engagement freshness',
    examples: [
      { lvl: 'HIGH', who: '@stepango', detail: '391 posts / 30d', val: '1.00' },
      { lvl: 'MID', who: '@yuvrajlakh', detail: '4 posts / 30d', val: '0.61' },
      { lvl: 'LOW', who: 'dormant', detail: '0 posts / 30d', val: '0.00' },
    ],
  },
];

/* ── Expandable Sub-score Card ── */
function SubScoreCard({ dim }) {
  var [open, setOpen] = React.useState(false);
  var [hov, setHov] = React.useState(false);
  return (
    <div
      onMouseEnter={function () { setHov(true); }} onMouseLeave={function () { setHov(false); }}
      style={{
        background: 'var(--bg-card)', border: '1px solid var(--border-subtle)',
        borderLeft: hov || open ? '2px solid var(--accent)' : '2px solid var(--border-subtle)',
        borderRadius: 12, padding: '18px 22px', marginBottom: 10, transition: 'border-color .15s',
      }}>
      <div onClick={function () { setOpen(!open); }} style={{ display: 'flex', alignItems: 'center', gap: 12, cursor: 'pointer' }}>
        <div style={{ flex: 1 }}>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 10 }}>
            <span style={{ fontSize: 15, fontWeight: 600, color: 'var(--text-primary)' }}>{dim.label}</span>
            <span style={{ fontSize: 12, fontFamily: 'var(--mono)', color: 'var(--accent)', fontFeatureSettings: "'tnum' 1" }}>w = {dim.weight.toFixed(2)}</span>
          </div>
          <div style={{ fontSize: 13, color: 'var(--text-secondary)', marginTop: 3 }}>{dim.blurb}</div>
        </div>
        <span style={{ fontSize: 11, color: 'var(--text-tertiary)', fontFamily: 'var(--mono)' }}>{open ? '− collapse' : '↗ explain'}</span>
      </div>

      {open && (
        <div style={{ marginTop: 16, paddingTop: 16, borderTop: '1px solid var(--border-subtle)' }}>
          {/* Formula */}
          <div style={{ marginBottom: 14 }}>
            <div style={{ fontSize: 10, fontWeight: 600, color: 'var(--text-tertiary)', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 6 }}>Formula</div>
            <div style={{ fontSize: 13, fontFamily: 'var(--mono)', color: 'var(--accent)', background: 'var(--bg-base)', padding: '8px 12px', borderRadius: 8, border: '1px solid var(--border-subtle)' }}>{dim.formula}</div>
            <div style={{ fontSize: 12, color: 'var(--text-tertiary)', marginTop: 6 }}>{dim.plain}</div>
          </div>
          {/* Examples */}
          <div style={{ marginBottom: 12 }}>
            <div style={{ fontSize: 10, fontWeight: 600, color: 'var(--text-tertiary)', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 8 }}>Real cohort cases</div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
              {dim.examples.map(function (ex) {
                var c = ex.lvl === 'HIGH' ? 'var(--accent)' : ex.lvl === 'MID' ? 'var(--text-secondary)' : 'var(--text-tertiary)';
                return (
                  <div key={ex.lvl} style={{ display: 'flex', alignItems: 'center', gap: 10, fontSize: 12 }}>
                    <span style={{ width: 38, fontSize: 10, fontWeight: 700, color: c, fontFamily: 'var(--mono)', flexShrink: 0 }}>{ex.lvl}</span>
                    <span style={{ fontFamily: 'var(--mono)', color: 'var(--text-primary)', flexShrink: 0, width: 130 }}>{ex.who}</span>
                    <span style={{ color: 'var(--text-tertiary)', flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{ex.detail}</span>
                    <span style={{ fontFamily: 'var(--mono)', color: c, fontWeight: 600, flexShrink: 0, fontFeatureSettings: "'tnum' 1" }}>{ex.val}</span>
                  </div>
                );
              })}
            </div>
          </div>
          <div style={{ fontSize: 11, color: 'var(--text-disabled)' }}>
            From <span style={{ fontFamily: 'var(--mono)' }}>{dim.field}</span> · maps to X's <span style={{ color: 'var(--text-tertiary)' }}>{dim.xsignal}</span>
          </div>
        </div>
      )}
    </div>
  );
}

/* ── Weight Slider ── */
function WeightSlider({ label, value, pct, onChange }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 14 }}>
      <span style={{ width: 130, fontSize: 13, color: 'var(--text-secondary)', flexShrink: 0 }}>{label}</span>
      <input type="range" min="0" max="100" value={Math.round(value * 100)}
        onChange={function (e) { onChange(parseInt(e.target.value) / 100); }}
        className="twk-slider"
        style={{ flex: 1, height: 4, borderRadius: 2, appearance: 'none', WebkitAppearance: 'none', background: 'var(--bg-elevated)', cursor: 'pointer', accentColor: 'var(--accent)' }} />
      <span style={{ width: 44, fontSize: 13, fontFamily: 'var(--mono)', color: 'var(--text-primary)', textAlign: 'right', fontFeatureSettings: "'tnum' 1", flexShrink: 0 }}>{pct}%</span>
    </div>
  );
}

/* ── Funnel Stage ── */
function FunnelStage({ count, label, note, width, last }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', flex: 1, position: 'relative' }}>
      <div style={{ width: '100%', maxWidth: width, height: 72, background: last ? 'var(--accent-muted)' : 'var(--bg-elevated)', border: last ? '1px solid var(--accent)' : '1px solid var(--border-default)', borderRadius: 10, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', transition: 'all .3s' }}>
        <div style={{ fontSize: 26, fontWeight: 600, fontFamily: 'var(--mono)', color: last ? 'var(--accent)' : 'var(--text-primary)', fontFeatureSettings: "'tnum' 1", lineHeight: 1 }}>{count}</div>
        <div style={{ fontSize: 11, color: 'var(--text-secondary)', marginTop: 4 }}>{label}</div>
      </div>
      {note && <div style={{ fontSize: 10, color: 'var(--text-disabled)', marginTop: 8, fontStyle: 'italic', textAlign: 'center', maxWidth: 130, lineHeight: 1.4 }}>{note}</div>}
    </div>
  );
}

/* ══════════ MAIN METHODOLOGY VIEW ══════════ */
function MethodologyView({ onOpenPerson }) {
  var [weights, setWeights] = React.useState(window.SCORING.DEFAULT_WEIGHTS);
  var result = React.useMemo(function () {
    /* Normalize weights to sum 1.0 for compute */
    var sum = Object.values(weights).reduce(function (a, b) { return a + b; }, 0) || 1;
    var norm = {};
    Object.keys(weights).forEach(function (k) { norm[k] = weights[k] / sum; });
    return window.SCORING.compute(norm);
  }, [weights]);

  var rawSum = Object.values(weights).reduce(function (a, b) { return a + b; }, 0);
  var rawPct = Math.round(rawSum * 100);

  function setW(key, v) {
    setWeights(function (p) { var n = Object.assign({}, p); n[key] = v; return n; });
  }
  function reset() { setWeights(window.SCORING.DEFAULT_WEIGHTS); }

  var top30 = result.scored.slice(0, 30);
  var defaultResult = window.SCORING.getDefault();
  var defaultOverlap = defaultResult.overlap.inTop30;
  var curOverlap = result.overlap.inTop30;
  var overlapDelta = curOverlap - defaultOverlap;

  var lastGen = new Date(window.COHORT.lastUpdated);

  return (
    <div style={{ height: '100%', overflowY: 'auto' }}>
      <div style={{ maxWidth: 1000, margin: '0 auto', padding: '28px 32px 48px' }}>

        {/* ── Hero ── */}
        <div style={{ marginBottom: 32 }}>
          <div style={{ fontSize: 26, fontWeight: 700, color: 'var(--text-primary)', letterSpacing: '-0.02em', marginBottom: 8 }}>How we rank cohort members</div>
          <div style={{ fontSize: 14, color: 'var(--text-secondary)', lineHeight: 1.6, maxWidth: 680 }}>
            A three-layer filter plus ML-inspired scoring, modeled on the multi-stage structure of X's open-source For You algorithm. Five interpretable signals, hand-tunable weights — not a black box.
          </div>
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginTop: 14 }}>
            {METH_DIMS.map(function (d) {
              return <span key={d.key} style={{ padding: '4px 12px', borderRadius: 6, background: 'var(--bg-elevated)', color: 'var(--text-secondary)', fontSize: 12, fontFamily: 'var(--mono)' }}>{d.label}</span>;
            })}
          </div>
          <a href="https://github.com/xai-org/x-algorithm" target="_blank" rel="noopener" style={{ display: 'inline-flex', alignItems: 'center', gap: 5, marginTop: 14, fontSize: 12, color: 'var(--accent)', textDecoration: 'none', fontFamily: 'var(--mono)' }}>
            github.com/xai-org/x-algorithm ↗
          </a>
        </div>

        {/* ── Pipeline Funnel ── */}
        <div style={{ background: 'var(--bg-card)', border: '1px solid var(--border-subtle)', borderRadius: 12, padding: '24px', marginBottom: 32 }}>
          <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--text-tertiary)', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 20 }}>Three-Layer Pipeline</div>
          <div style={{ display: 'flex', alignItems: 'flex-start', gap: 8 }}>
            <FunnelStage count={result.funnel.active} label="active handles" note="30d activity or bio present" width={150} />
            <div style={{ alignSelf: 'center', color: 'var(--text-disabled)', fontSize: 18, paddingTop: 4 }}>→</div>
            <FunnelStage count={result.funnel.candidates} label="candidates" note="Layer 1: dropped silent, no-signal accounts" width={150} />
            <div style={{ alignSelf: 'center', color: 'var(--text-disabled)', fontSize: 18, paddingTop: 4 }}>→</div>
            <FunnelStage count={result.funnel.top100} label="light-scored top" note="Layer 2: 5-dim Light Score ranks the field" width={150} />
            <div style={{ alignSelf: 'center', color: 'var(--text-disabled)', fontSize: 18, paddingTop: 4 }}>→</div>
            <FunnelStage count={result.funnel.final} label="final T1 / T2" note="Layer 3: Heavy Score re-ranks top-100" width={150} last />
          </div>
        </div>

        {/* ── Sub-score Explainers ── */}
        <div style={{ marginBottom: 32 }}>
          <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--text-tertiary)', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 14 }}>Light Score · 5 Dimensions</div>
          {METH_DIMS.map(function (d) { return <SubScoreCard key={d.key} dim={d} />; })}
        </div>

        {/* ── Weight Tuning ── */}
        <div style={{ background: 'var(--bg-card)', border: '1px solid var(--border-subtle)', borderRadius: 12, padding: '24px', marginBottom: 32 }}>
          <div style={{ display: 'flex', alignItems: 'center', marginBottom: 20 }}>
            <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--text-tertiary)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Tune the Weights</div>
            <div style={{ flex: 1 }}></div>
            <button onClick={reset} style={{ background: 'var(--bg-elevated)', border: '1px solid var(--border-default)', borderRadius: 8, color: 'var(--text-secondary)', cursor: 'pointer', fontSize: 11, padding: '5px 12px', fontFamily: 'var(--sans)' }}>Reset to defaults</button>
          </div>

          {METH_DIMS.map(function (d) {
            var pct = rawSum > 0 ? Math.round(weights[d.key] / rawSum * 100) : 0;
            return <WeightSlider key={d.key} label={d.label} value={weights[d.key]} pct={pct} onChange={function (v) { setW(d.key, v); }} />;
          })}

          <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginTop: 18, paddingTop: 16, borderTop: '1px solid var(--border-subtle)' }}>
            <span style={{ fontSize: 12, color: 'var(--text-tertiary)' }}>Normalized to 100% automatically · raw total {rawPct}%</span>
            <div style={{ flex: 1 }}></div>
            {/* Overlap badge */}
            <div style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '5px 12px', borderRadius: 999, background: 'var(--accent-muted)' }}>
              <span style={{ fontSize: 12, color: 'var(--accent)', fontFamily: 'var(--mono)', fontWeight: 600 }}>{curOverlap}/{result.overlap.total}</span>
              <span style={{ fontSize: 11, color: 'var(--text-secondary)' }}>external overlap in top-30</span>
              {overlapDelta !== 0 && <span style={{ fontSize: 11, fontFamily: 'var(--mono)', color: overlapDelta > 0 ? 'var(--accent)' : 'var(--text-tertiary)' }}>{overlapDelta > 0 ? '↑' : '↓'}{Math.abs(overlapDelta)}</span>}
            </div>
          </div>

          {/* Top-30 live preview */}
          <div style={{ marginTop: 18 }}>
            <div style={{ fontSize: 10, fontWeight: 600, color: 'var(--text-tertiary)', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 10 }}>Live preview · top 30</div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 5 }}>
              {top30.map(function (s, i) {
                var isExt = !!s.m.external;
                return (
                  <div key={s.m.handle} onClick={function () { onOpenPerson && onOpenPerson(s.m.handle); }}
                    title={'priority ' + s.priorityScore.toFixed(3) + ' · T' + s.tier}
                    style={{
                      display: 'flex', alignItems: 'center', gap: 5, padding: '4px 9px', borderRadius: 6,
                      background: isExt ? 'var(--accent-muted)' : 'var(--bg-elevated)',
                      border: isExt ? '1px solid rgba(249, 115, 22,0.3)' : '1px solid transparent',
                      cursor: 'pointer', transition: 'all .12s',
                    }}>
                    <span style={{ fontSize: 10, fontFamily: 'var(--mono)', color: 'var(--text-disabled)', fontFeatureSettings: "'tnum' 1" }}>{i + 1}</span>
                    <span style={{ fontSize: 11, fontFamily: 'var(--mono)', color: isExt ? 'var(--accent)' : 'var(--text-secondary)' }}>@{s.m.handle}</span>
                    <span style={{ fontSize: 10, fontFamily: 'var(--mono)', color: 'var(--text-tertiary)', fontFeatureSettings: "'tnum' 1" }}>{s.priorityScore.toFixed(2)}</span>
                  </div>
                );
              })}
            </div>
          </div>
        </div>

        {/* ── Why These 5 ── */}
        <div style={{ background: 'var(--bg-card)', borderLeft: '3px solid var(--accent)', borderRadius: 8, padding: '20px 24px', marginBottom: 16 }}>
          <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--text-primary)', marginBottom: 12 }}>Why these five, not others</div>
          <div style={{ fontSize: 13, color: 'var(--text-secondary)', lineHeight: 1.6, marginBottom: 14 }}>
            Each dimension answers one concrete question Howard asks when sizing up a target. We deliberately left out signals that look sophisticated but don't fit this problem:
          </div>
          {[
            ['Time-of-day decay', 'cohort posts ~94/day — too sparse and noisy for hourly weighting'],
            ["Personalized to Howard's history", "system limit — we don't know who Howard has replied to or read"],
            ['Policy / spam signals', "can't judge, and shouldn't predict block/mute — that's Howard's call"],
            ['Account age / seniority', 'xAI hired en masse in 2023–24, so signup date is uncorrelated with quality'],
          ].map(function (x) {
            return (
              <div key={x[0]} style={{ display: 'flex', gap: 10, marginBottom: 8, fontSize: 12 }}>
                <span style={{ color: 'var(--text-tertiary)', flexShrink: 0 }}>✗</span>
                <span style={{ color: 'var(--text-secondary)', fontWeight: 500, width: 220, flexShrink: 0 }}>{x[0]}</span>
                <span style={{ color: 'var(--text-tertiary)' }}>{x[1]}</span>
              </div>
            );
          })}
        </div>

        {/* ── CANNOT do ── */}
        <div style={{ background: 'rgba(220,74,83,0.06)', border: '1px solid rgba(220,74,83,0.20)', borderRadius: 12, padding: '20px 24px' }}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--rose)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 14 }}>What this score cannot do</div>
          {[
            ['Predict who will reply to Howard', 'engagement depends on his content, timing, network effects'],
            ['Guarantee high-scorers will hire', "it's an outreach-efficiency ranking, not a fit prediction"],
            ['Replace domain expertise', 'manual override is always allowed — bump anyone you know personally'],
            ['Stay accurate forever', 'cohort drifts — retune the weights roughly every 2 weeks'],
          ].map(function (x) {
            return (
              <div key={x[0]} style={{ display: 'flex', gap: 10, marginBottom: 8, fontSize: 12 }}>
                <span style={{ color: 'var(--rose)', flexShrink: 0 }}>−</span>
                <span style={{ color: 'var(--text-secondary)', fontWeight: 500, width: 240, flexShrink: 0 }}>{x[0]}</span>
                <span style={{ color: 'var(--text-tertiary)' }}>{x[1]}</span>
              </div>
            );
          })}
          <div style={{ marginTop: 14, paddingTop: 14, borderTop: '1px solid rgba(220,74,83,0.12)', fontSize: 11, color: 'var(--text-disabled)', fontFamily: 'var(--mono)' }}>
            Last generated: {lastGen.toLocaleString('sv-SE', { timeZone: 'Asia/Taipei', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' })} UTC+8 · Data freshness: 7d · {result.funnel.active} active · 2,825 tweets
          </div>
        </div>

      </div>
    </div>
  );
}

window.MethodologyView = MethodologyView;
