/* Info Diet — Followers × Following selectivity scatter (full interactive view).
   Sibling of scatter.jsx (which plots Followers × Priority Score for outreach
   targeting). This one answers a different question: how does this cohort
   *consume* X? Both axes are profile counts, log by default (both heavily
   right-skewed). Quadrants use ABSOLUTE thresholds (not cohort medians) so the
   cluster counts carry a narrative instead of a forced 25/25/25/25 split.
   Click a dot → PersonDrawer. Mirrors the Overview "Selectivity Map" card but
   full-screen + interactive (log/linear, color modes, drawer). */

function fmtDietNum(n) { return n >= 1e6 ? (n / 1e6).toFixed(1) + 'M' : n >= 1e3 ? (n / 1e3).toFixed(1) + 'K' : String(n); }

var DIET_FOLLOWING_T = 100;   /* ≥ → follows "many" (low selectivity) */
var DIET_FOLLOWERS_T = 1000;  /* ≥ → meaningful reach */
var DIET_CLUSTERS = {
  silent:      { label: 'Silent Consumer',     color: 'rgba(255,255,255,0.32)', desc: 'follows <100 · <1K followers' },
  gatherer:    { label: 'Information Gatherer', color: 'var(--accent)',          desc: 'follows ≥100 · <1K followers' },
  broadcaster: { label: 'Broadcaster',          color: '#3B82F6',                desc: 'follows <100 · ≥1K followers' },
  operator:    { label: 'Public Operator',      color: 'rgba(255,255,255,0.82)', desc: 'follows ≥100 · ≥1K followers' },
};
function dietClusterKey(m) {
  var lowDiet = (m.following || 0) < DIET_FOLLOWING_T, lowReach = (m.followers || 0) < DIET_FOLLOWERS_T;
  if (lowDiet && lowReach) return 'silent';
  if (lowDiet && !lowReach) return 'broadcaster';
  if (!lowDiet && lowReach) return 'gatherer';
  return 'operator';
}
/* log(following)/log(followers) — a single "consumer ↔ broadcaster" number.
   >1 = follows more than followed (gatherer); <1 = followed more (broadcaster). */
function dietSelectivity(m) { return Math.log((m.following || 0) + 1) / Math.log(Math.max(1, m.followers || 0) + 1); }

function DietScatterView() {
  var [hovered, setHovered] = React.useState(null);
  var [selected, setSelected] = React.useState(null);
  var [logScale, setLogScale] = React.useState(true);
  var [colorBy, setColorBy] = React.useState('cluster'); /* cluster | selectivity | none */

  var members = window.COHORT.members;
  var personal = React.useMemo(function () {
    return members.filter(function (m) { return !m.isOfficial && m.status === 'ok'; });
  }, []);
  var total = personal.length;
  function pct(n) { return Math.round(n / Math.max(total, 1) * 100); }

  var counts = React.useMemo(function () {
    var c = { silent: 0, gatherer: 0, broadcaster: 0, operator: 0 };
    personal.forEach(function (m) { c[dietClusterKey(m)]++; });
    return c;
  }, [personal]);
  var maxFollowers = React.useMemo(function () { return Math.max.apply(null, personal.map(function (m) { return m.followers || 0; })); }, [personal]);
  var maxFollowing = React.useMemo(function () { return Math.max.apply(null, personal.map(function (m) { return m.following || 0; })); }, [personal]);

  var W = 1400, H = 760;
  var PAD = { top: 30, right: 30, bottom: 56, left: 66 };
  var plotW = W - PAD.left - PAD.right, plotH = H - PAD.top - PAD.bottom;
  function scaleX(v) {
    if (logScale) return PAD.left + (Math.log10(Math.max(0, v) + 1) / Math.log10(maxFollowing + 2)) * plotW;
    return PAD.left + (v / Math.max(maxFollowing, 1)) * plotW;
  }
  function scaleY(v) {
    if (logScale) return PAD.top + plotH - (Math.log10(Math.max(0, v) + 1) / Math.log10(maxFollowers + 2)) * plotH;
    return PAD.top + plotH - (v / Math.max(maxFollowers, 1)) * plotH;
  }

  var xTicks = logScale
    ? [0, 10, 100, 1000, 5000].filter(function (t) { return t <= maxFollowing * 1.1; })
    : (function () { var s = maxFollowing > 4000 ? 1000 : 500; var a = []; for (var i = 0; i <= maxFollowing; i += s) a.push(i); return a; })();
  var yTicks = logScale
    ? [0, 100, 1000, 10000, 100000].filter(function (t) { return t <= maxFollowers * 1.1; })
    : (function () { var s = maxFollowers > 40000 ? 10000 : 5000; var a = []; for (var i = 0; i <= maxFollowers; i += s) a.push(i); return a; })();

  var divX = scaleX(DIET_FOLLOWING_T), divY = scaleY(DIET_FOLLOWERS_T);

  function selBin(m) { var r = dietSelectivity(m); return r < 0.78 ? 'low' : r > 1.06 ? 'high' : 'mid'; }
  function dotColor(m) {
    if (colorBy === 'cluster') return DIET_CLUSTERS[dietClusterKey(m)].color;
    if (colorBy === 'selectivity') { var b = selBin(m); return b === 'high' ? 'var(--accent)' : b === 'low' ? '#3B82F6' : 'rgba(255,255,255,0.55)'; }
    return 'rgba(255,255,255,0.40)';
  }
  function dotRadius(m) {
    if (m.external) return 6;
    if ((m.followers || 0) > 10000) return 5;
    if ((m.followers || 0) > 1000) return 4;
    return 3;
  }

  var qLabels = [
    { k: 'silent',      x: PAD.left + 8,         y: PAD.top + plotH - 10, anchor: 'start' },
    { k: 'gatherer',    x: PAD.left + plotW - 8, y: PAD.top + plotH - 10, anchor: 'end' },
    { k: 'broadcaster', x: PAD.left + 8,         y: PAD.top + 16,         anchor: 'start' },
    { k: 'operator',    x: PAD.left + plotW - 8, y: PAD.top + 16,         anchor: 'end' },
  ];

  var hovPerson = hovered ? personal.find(function (m) { return m.handle === hovered; }) : null;
  var selPerson = selected ? members.find(function (m) { return m.handle === selected; }) : null;

  function segBtn(active) {
    return { padding: '5px 14px', border: 'none', fontSize: 12, fontWeight: active ? 600 : 400, background: active ? 'var(--bg-elevated)' : 'transparent', color: active ? 'var(--text-primary)' : 'var(--text-tertiary)', cursor: 'pointer', fontFamily: 'var(--sans)', transition: 'all .12s' };
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden' }}>
      {/* Toolbar */}
      <div style={{ padding: '10px 28px', borderBottom: '1px solid var(--border-subtle)', display: 'flex', alignItems: 'center', gap: 12, flexShrink: 0, background: 'var(--bg-surface)', flexWrap: 'wrap' }}>
        <div style={{ display: 'flex', background: 'var(--bg-card)', borderRadius: 10, border: '1px solid var(--border-default)', overflow: 'hidden' }}>
          {[{ v: true, l: 'Log' }, { v: false, l: 'Linear' }].map(function (s) {
            return <button key={s.l} onClick={function () { setLogScale(s.v); }} style={segBtn(logScale === s.v)}>{s.l}</button>;
          })}
        </div>
        <span style={{ fontSize: 12, color: 'var(--text-tertiary)' }}>Color:</span>
        <div style={{ display: 'flex', background: 'var(--bg-card)', borderRadius: 10, border: '1px solid var(--border-default)', overflow: 'hidden' }}>
          {[{ v: 'cluster', l: 'Cluster' }, { v: 'selectivity', l: 'Selectivity' }, { v: 'none', l: 'None' }].map(function (s) {
            return <button key={s.v} onClick={function () { setColorBy(s.v); }} style={segBtn(colorBy === s.v)}>{s.l}</button>;
          })}
        </div>
        <div style={{ flex: 1 }}></div>
        <div style={{ display: 'flex', gap: 12, alignItems: 'center', flexWrap: 'wrap' }}>
          {['silent', 'gatherer', 'operator', 'broadcaster'].map(function (k) {
            return (
              <span key={k} style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 11, color: 'var(--text-tertiary)' }}>
                <span style={{ width: 8, height: 8, borderRadius: '50%', background: DIET_CLUSTERS[k].color, flexShrink: 0 }}></span>
                {DIET_CLUSTERS[k].label} <span style={{ fontFamily: 'var(--mono)', color: 'var(--text-secondary)', fontFeatureSettings: "'tnum' 1" }}>{pct(counts[k])}%</span>
              </span>
            );
          })}
        </div>
      </div>

      {/* Chart + drawer */}
      <div style={{ flex: 1, display: 'flex', overflow: 'hidden' }}>
        <div style={{ flex: 1, overflowY: 'auto', padding: '20px 28px' }}>
          <svg viewBox={'0 0 ' + W + ' ' + H} preserveAspectRatio="xMidYMid meet" style={{ width: '100%', height: 'auto', display: 'block' }}>
            <rect x={PAD.left} y={PAD.top} width={plotW} height={plotH} fill="var(--bg-card)" rx="4" />

            {yTicks.map(function (t) { var y = scaleY(t); return (
              <React.Fragment key={'y' + t}>
                <line x1={PAD.left} y1={y} x2={PAD.left + plotW} y2={y} stroke="var(--border-subtle)" strokeWidth="0.5" />
                <text x={PAD.left - 8} y={y + 4} fill="var(--text-disabled)" fontSize="11" fontFamily="var(--mono)" textAnchor="end">{fmtDietNum(t)}</text>
              </React.Fragment>); })}
            {xTicks.map(function (t) { var x = scaleX(t); return (
              <React.Fragment key={'x' + t}>
                <line x1={x} y1={PAD.top} x2={x} y2={PAD.top + plotH} stroke="var(--border-subtle)" strokeWidth="0.5" />
                <text x={x} y={PAD.top + plotH + 18} fill="var(--text-disabled)" fontSize="11" fontFamily="var(--mono)" textAnchor="middle">{fmtDietNum(t)}</text>
              </React.Fragment>); })}

            {/* quadrant dividers at the absolute thresholds */}
            <line x1={divX} y1={PAD.top} x2={divX} y2={PAD.top + plotH} stroke="var(--border-strong)" strokeWidth="1" strokeDasharray="5,4" />
            <line x1={PAD.left} y1={divY} x2={PAD.left + plotW} y2={divY} stroke="var(--border-strong)" strokeWidth="1" strokeDasharray="5,4" />

            {qLabels.map(function (q) { return (
              <text key={q.k} x={q.x} y={q.y} fill="var(--text-tertiary)" fontSize="12" fontFamily="var(--sans)" fontWeight="600" textAnchor={q.anchor}>
                {DIET_CLUSTERS[q.k].label} · {counts[q.k]} ({pct(counts[q.k])}%)
              </text>); })}

            <text x={PAD.left + plotW / 2} y={H - 6} fill="var(--text-tertiary)" fontSize="13" fontFamily="var(--sans)" textAnchor="middle" fontWeight="500">Following (information diet) →</text>
            <text x={16} y={PAD.top + plotH / 2} fill="var(--text-tertiary)" fontSize="13" fontFamily="var(--sans)" textAnchor="middle" fontWeight="500" transform={'rotate(-90,16,' + (PAD.top + plotH / 2) + ')'}>Followers (reach) →</text>

            {personal.map(function (m) {
              var cx = scaleX(m.following || 0), cy = scaleY(m.followers || 0);
              var r = dotRadius(m), isHov = hovered === m.handle, isExt = !!m.external;
              return <circle key={m.handle} cx={cx} cy={cy} r={isHov ? r + 2 : r}
                fill={dotColor(m)} stroke={isExt ? 'var(--accent)' : isHov ? '#fff' : 'none'} strokeWidth={isExt ? 1.5 : isHov ? 1 : 0}
                opacity={hovered && !isHov ? 0.22 : 0.85}
                style={{ cursor: 'pointer', transition: 'opacity .15s' }}
                onMouseEnter={function () { setHovered(m.handle); }}
                onMouseLeave={function () { setHovered(null); }}
                onClick={function () { setSelected(m.handle); }} />;
            })}

            {hovPerson && (function () {
              var cx = scaleX(hovPerson.following || 0), cy = scaleY(hovPerson.followers || 0);
              var tw = 232, th = 96, tx = cx + 12, ty = cy - 12;
              if (tx + tw > W) tx = cx - tw - 12;
              if (ty < PAD.top + 6) ty = cy + 12;
              if (ty + th > PAD.top + plotH) ty = cy - th - 12;
              var ck = dietClusterKey(hovPerson);
              var bio = (hovPerson.bio || '').replace(/\s+/g, ' ').trim();
              if (bio.length > 40) bio = bio.slice(0, 40) + '…';
              return (
                <g style={{ pointerEvents: 'none' }}>
                  <rect x={tx} y={ty} width={tw} height={th} rx="8" fill="var(--bg-elevated)" stroke="var(--border-strong)" strokeWidth="1" />
                  <text x={tx + 12} y={ty + 20} fill="var(--text-primary)" fontSize="13" fontFamily="var(--mono)" fontWeight="600">@{hovPerson.handle}</text>
                  {hovPerson.name && hovPerson.name !== hovPerson.handle && <text x={tx + 12} y={ty + 36} fill="var(--text-tertiary)" fontSize="11" fontFamily="var(--sans)">{hovPerson.name.length > 30 ? hovPerson.name.slice(0, 30) + '…' : hovPerson.name}</text>}
                  <text x={tx + 12} y={ty + 54} fill="var(--text-secondary)" fontSize="11" fontFamily="var(--mono)">{fmtDietNum(hovPerson.following || 0)} following · {fmtDietNum(hovPerson.followers || 0)} followers</text>
                  <text x={tx + 12} y={ty + 71} fill={ck === 'gatherer' ? 'var(--accent)' : ck === 'broadcaster' ? '#3B82F6' : 'var(--text-secondary)'} fontSize="11" fontFamily="var(--sans)" fontWeight="600">{DIET_CLUSTERS[ck].label}</text>
                  <text x={tx + 12} y={ty + 87} fill={bio ? 'var(--text-tertiary)' : 'var(--text-disabled)'} fontSize="10" fontFamily="var(--sans)">{bio || 'no bio'}</text>
                </g>
              );
            })()}
          </svg>

          {/* Legend */}
          <div style={{ display: 'flex', gap: 16, marginTop: 12, flexWrap: 'wrap', alignItems: 'center' }}>
            {colorBy === 'cluster' && ['silent', 'gatherer', 'operator', 'broadcaster'].map(function (k) {
              return (
                <span key={k} style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 11, color: 'var(--text-tertiary)' }}>
                  <span style={{ width: 8, height: 8, borderRadius: '50%', background: DIET_CLUSTERS[k].color }}></span> {DIET_CLUSTERS[k].label} <span style={{ color: 'var(--text-disabled)' }}>· {DIET_CLUSTERS[k].desc}</span>
                </span>
              );
            })}
            {colorBy === 'selectivity' && (
              <React.Fragment>
                <span style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 11, color: 'var(--text-tertiary)' }}><span style={{ width: 8, height: 8, borderRadius: '50%', background: '#3B82F6' }}></span> Broadcasts (followed &gt; follows)</span>
                <span style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 11, color: 'var(--text-tertiary)' }}><span style={{ width: 8, height: 8, borderRadius: '50%', background: 'rgba(255,255,255,0.55)' }}></span> Balanced</span>
                <span style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 11, color: 'var(--text-tertiary)' }}><span style={{ width: 8, height: 8, borderRadius: '50%', background: 'var(--accent)' }}></span> Gathers (follows &gt; followed)</span>
              </React.Fragment>
            )}
            <span style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 11, color: 'var(--text-tertiary)', marginLeft: 'auto' }}>
              <span style={{ width: 10, height: 10, borderRadius: '50%', border: '1.5px solid var(--accent)', background: 'transparent' }}></span> External target
            </span>
            <span style={{ fontSize: 11, color: 'var(--text-disabled)', fontStyle: 'italic' }}>Click a dot to open profile · {total} profiles</span>
          </div>
        </div>

        {selPerson && <PersonDrawer person={selPerson} onClose={function () { setSelected(null); }} />}
      </div>
    </div>
  );
}

window.DietScatterView = DietScatterView;
