// council-feed.jsx — Live Council Vote feed.
// A streaming-style list of recent orders. Each row shows the verdict and the
// agreement count. Click any row (or it auto-cycles) to expand it — revealing
// all 25 named votes with their reason and a link to Basescan.

// ── Mock recent orders (deterministic so the page is reproducible) ──
// In production this comes from a stream over the platform's chain index.
const FEED_ORDERS = [
  {
    sym: 'AAPL', side: 'BUY',  qty:   100, value: 20542,
    broker: 'alpaca', timestamp: '14:02:17.183', latencyMs: 187,
    proof: 'a3b2-9c1f', block: 46270762,
    votes: [
      // 1-5 liquidity, 6-10 vol, 11-15 pat, 16-20 sent, 21-25 risk
      'y','y','y','y','y',  'y','y','n','y','y',  'y','y','y','y','y',  'y','y','a','y','y',  'y','y','y','y','y',
    ],
    summary: 'Clean signal · liquidity deep · no flags.',
  },
  {
    sym: 'TSLA', side: 'SELL', qty:  1000, value: 287100,
    broker: 'alpaca', timestamp: '14:01:52.901', latencyMs: 211,
    proof: '4e8a-1d77', block: 46270721,
    votes: [
      'y','y','n','y','y',  'n','n','y','y','y',  'n','y','y','y','y',  'y','a','y','y','y',  'n','y','n','y','y',
    ],
    summary: 'Borderline · oversize triggered cautions but cleared the bar.',
  },
  {
    sym: 'GME',  side: 'BUY',  qty:  5000, value: 127500,
    broker: 'alpaca', timestamp: '14:01:09.502', latencyMs: 245,
    proof: 'c8f3-7b22', block: 46270701,
    votes: [
      'n','y','n','n','y',  'n','y','n','n','n',  'y','n','n','y','n',  'n','n','a','y','n',  'n','n','n','n','y',
    ],
    summary: 'Refused · pattern + sentiment flagged simultaneously.',
  },
  {
    sym: 'NVDA', side: 'BUY',  qty:    10, value: 11479,
    broker: 'moomoo', timestamp: '14:00:33.220', latencyMs: 142,
    proof: 'f1a8-2e09', block: 46270685,
    votes: [
      'y','y','y','y','y',  'y','y','y','y','y',  'y','y','y','y','y',  'y','y','y','y','y',  'y','y','y','y','y',
    ],
    summary: 'Unanimous · all 25 agree · cleanest of the session.',
  },
  {
    sym: 'SPY',  side: 'SELL', qty:     2, value: 0,
    broker: 'alpaca', timestamp: '13:59:48.011', latencyMs: 198,
    proof: '0d2c-5fb1', block: 46270668,
    votes: [
      'n','y','n','n','y',  'y','n','y','n','y',  'n','y','n','y','n',  'y','y','a','n','n',  'n','y','n','y','y',
    ],
    summary: 'Refused · stale quote · order never reached the broker.',
  },
];

function yesCount(votes) { return votes.filter(v => v === 'y').length; }
function passOf(votes)   { return yesCount(votes) >= 17; }   // 17 of 25 = 68%

// ── Live Council Vote feed ────────────────────────────────────
function LiveCouncilFeed() {
  const [openIdx, setOpenIdx] = React.useState(0);
  const [pinned, setPinned]   = React.useState(false);

  // Auto-rotate the expanded order every 5s unless pinned
  React.useEffect(() => {
    if (pinned) return;
    const id = setInterval(() => setOpenIdx(i => (i + 1) % FEED_ORDERS.length), 5500);
    return () => clearInterval(id);
  }, [pinned]);

  return (
    <div>
      <div style={{ marginBottom: 22, maxWidth: 760 }}>
        <Mono color={T.allow} weight={500}>§ 05 · LIVE</Mono>
        <h2 style={{
          fontFamily: GEIST, fontWeight: 600, fontSize: 36, letterSpacing: -1.2, lineHeight: 1.05,
          margin: '10px 0 6px', color: T.textInv,
        }}>Watch the Council vote.</h2>
        <p style={{
          margin: 0, fontSize: 15, lineHeight: 1.55,
          color: T.muteInv, letterSpacing: -0.1,
        }}>
          Each row is a recent order. Expand any one to see all 25 named votes — who agreed, who refused, who abstained, and why. Every receipt anchors to a Base block; nothing here is rendered without a corresponding on-chain entry.
        </p>
      </div>

      <div style={{ border: `1px solid ${T.inkBorder}`, background: 'rgba(244,244,240,0.02)' }}>
        {FEED_ORDERS.map((o, i) => (
          <FeedRow key={o.proof} order={o} idx={i}
            open={openIdx === i}
            onToggle={() => {
              setPinned(true);
              setOpenIdx(openIdx === i ? -1 : i);
            }}
            last={i === FEED_ORDERS.length - 1}/>
        ))}
      </div>

      <div style={{ marginTop: 16, display: 'flex', alignItems: 'center', gap: 10 }}>
        <Pulse color={pinned ? T.muteInv : T.allow} size={6}/>
        <Mono color={T.muteInv}>
          {pinned ? 'PAUSED · TAP A ROW TO EXPAND' : 'AUTO-CYCLING · TAP TO PIN'}
        </Mono>
      </div>
    </div>
  );
}

// ── One row in the feed ───────────────────────────────────────
function FeedRow({ order, idx, open, onToggle, last }) {
  const ys = yesCount(order.votes);
  const pass = passOf(order.votes);
  const ratio = ys / 25;
  const seed = (typeof orderSeed === 'function') ? orderSeed(order.proof, order.block) : 0;
  const sigilColors = pass
    ? { ring: '#42f977', field: '#24956b', core: '#42f977' }
    : { ring: '#e72020', field: '#b05222', core: '#e72020' };

  return (
    <div style={{ borderBottom: last ? 'none' : `1px solid ${T.inkBorder}` }}>
      <button onClick={onToggle} style={{
        width: '100%', textAlign: 'left', background: open ? 'rgba(244,244,240,0.03)' : 'transparent',
        border: 'none', cursor: 'pointer', padding: '16px 20px',
        display: 'grid', alignItems: 'center', gap: 14,
        gridTemplateColumns: '32px 110px 80px 1fr 220px 100px 90px 32px',
        transition: 'background .12s ease',
      }}>
        <div title={`Receipt sigil · seed ${seed.toString(16)}`}>
          {typeof SeedSigil === 'function' && (
            <SeedSigil seed={seed} size={28} variant="mark" colors={sigilColors}/>
          )}
        </div>
        <Mono color={T.muteInv} size={10}>§ {String(idx + 1).padStart(2, '0')} · {order.timestamp}</Mono>
        <span style={{
          fontFamily: GMONO, fontSize: 16, fontWeight: 500,
          color: T.textInv, letterSpacing: 0.4,
        }}>{order.sym}</span>
        <span style={{
          fontFamily: GMONO, fontSize: 12, color: T.muteInv, letterSpacing: 0.3,
        }}>
          <span style={{ color: order.side === 'BUY' ? T.allow : T.caution }}>{order.side}</span>
          {'  ·  '}{order.qty.toLocaleString()} shares
          {'  ·  '}{order.value > 0 ? '$' + order.value.toLocaleString() : 'stale quote'}
          {'  ·  '}{order.broker}
        </span>

        {/* mini-bar — one row of 25 cells */}
        <div style={{
          display: 'grid', gridTemplateColumns: 'repeat(25, 1fr)', gap: 1,
          height: 14, position: 'relative',
        }}>
          {order.votes.map((v, i) => (
            <span key={i} style={{
              background: v === 'y' ? T.allow : v === 'n' ? T.refuse : T.caution,
              opacity: 0.9,
            }}/>
          ))}
          {/* pass-bar line */}
          <span style={{
            position: 'absolute', left: `${(17 / 25) * 100}%`,
            top: -3, bottom: -3, width: 1,
            background: T.caution, marginLeft: -0.5, pointerEvents: 'none',
          }}/>
        </div>

        <span style={{
          display: 'inline-flex', alignItems: 'center', gap: 6,
          padding: '5px 10px',
          background: pass ? 'rgba(45,216,129,0.10)' : 'rgba(255,86,117,0.10)',
          border: `1px solid ${pass ? T.allow : T.refuse}`,
        }}>
          <span style={{ width: 7, height: 7, background: pass ? T.allow : T.refuse }}/>
          <Mono color={pass ? T.allow : T.refuse} weight={600} size={10}>
            {pass ? 'CLEARED' : 'REFUSED'}
          </Mono>
        </span>

        <Mono color={T.muteInv}>
          <span style={{ color: T.textInv }}>{ys}</span>/25 · {Math.round(ratio*100)}%
        </Mono>

        <span style={{
          fontFamily: GMONO, fontSize: 14, color: T.muteInv, transition: 'transform .2s',
          transform: open ? 'rotate(45deg)' : 'rotate(0deg)',
        }}>+</span>
      </button>

      {open && <FeedRowExpanded order={order}/>}
    </div>
  );
}

// ── Expanded panel showing all 25 named votes ─────────────────
function FeedRowExpanded({ order }) {
  const grouped = ALL_SPECS.map(spec => ({
    spec,
    spec_meta: SPEC[spec],
    agents: agentsBySpec(spec).map(a => ({ a, vote: order.votes[a.id - 1] })),
  }));
  const pass = passOf(order.votes);
  const seed = (typeof orderSeed === 'function') ? orderSeed(order.proof, order.block) : 0;
  const sigilColors = pass
    ? { ring: '#42f977', field: '#24956b', core: '#42f977' }
    : { ring: '#e72020', field: '#b05222', core: '#e72020' };

  return (
    <div style={{
      padding: '4px 20px 22px', background: 'rgba(244,244,240,0.015)',
      borderTop: `1px dashed ${T.inkBorder}`, animation: 'fade-up .25s ease both',
    }}>
      {/* Receipt strip — now anchored by the big generative receipt sigil */}
      <div style={{
        margin: '14px 0 16px', padding: '14px 18px',
        background: T.ink, border: `1px solid ${T.inkBorder}`,
        display: 'grid', gridTemplateColumns: '64px repeat(5, 1fr)', gap: 16, alignItems: 'center',
      }}>
        <div title="Per-order generative receipt — verifiable from proof + block">
          {typeof SeedSigil === 'function' && (
            <SeedSigil seed={seed} size={56} variant="seal" colors={sigilColors}/>
          )}
        </div>
        <ReceiptCell k="VERDICT"      v={pass ? 'CLEARED' : 'REFUSED'}
                     color={pass ? T.allow : T.refuse}/>
        <ReceiptCell k="AGREEMENT"    v={`${yesCount(order.votes)} / 25 · ${Math.round(yesCount(order.votes)/25*100)}%`}/>
        <ReceiptCell k="RESPONSE"     v={`${order.latencyMs} ms`}/>
        <ReceiptCell k="RECEIPT ID"   v={`ord_${order.proof}`}/>
        <ReceiptCell k="BASE BLOCK"   v={
          <a href={`${BASE_CHAIN.explorer}/block/${order.block}`} target="_blank" rel="noopener"
             style={{ color: T.allow }}>#{order.block.toLocaleString()} ↗</a>
        }/>
      </div>

      {/* Compute proof — pinned to the real GPU dispatcher commit */}
      <div style={{
        margin: '0 0 16px', padding: '10px 14px',
        background: 'rgba(35,200,233,0.04)', border: `1px solid rgba(35,200,233,0.20)`,
        display: 'grid', gridTemplateColumns: 'auto 1fr auto', gap: 14, alignItems: 'center',
      }}>
        <Mono color="#23c8e9" weight={600} size={9.5}>COMPUTE PROOF</Mono>
        <span style={{
          fontFamily: GMONO, fontSize: 11.5, color: T.textInv, letterSpacing: 0.3,
        }}>
          backend=cusv · {order.latencyMs}ms · dispatcher@5e504bfd
        </span>
        <a href="https://github.com/QuantumSwarms/epochcore-cusv-dispatcher/tree/5e504bfd"
           target="_blank" rel="noopener" onClick={e => e.stopPropagation()}
           style={{ fontFamily: GMONO, fontSize: 9.5, color: '#23c8e9', letterSpacing: 0.6 }}>
          REPLAY ↗
        </a>
      </div>

      <div style={{ marginBottom: 10, display: 'flex', alignItems: 'baseline', gap: 12 }}>
        <Mono color={T.allow} weight={500}>VERIFIER VOTES</Mono>
        <Mono color={T.muteInv}>{order.summary}</Mono>
      </div>

      {/* Voters grouped by specialty */}
      <div style={{ display: 'grid', gap: 12, gridTemplateColumns: 'repeat(5, 1fr)' }}>
        {grouped.map(g => (
          <div key={g.spec} style={{
            border: `1px solid ${T.inkBorder}`, background: g.spec_meta.soft,
            padding: '10px 12px 6px',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 8 }}>
              <Mono color={g.spec_meta.color} weight={500} size={10}>{g.spec_meta.label.toUpperCase()}</Mono>
              <Mono color={T.muteInv} size={9}>
                {g.agents.filter(x => x.vote === 'y').length}/5
              </Mono>
            </div>
            {g.agents.map(({ a, vote }) => (
              <VoteLine key={a.id} agent={a} vote={vote} color={g.spec_meta.color}/>
            ))}
          </div>
        ))}
      </div>
    </div>
  );
}

function VoteLine({ agent, vote, color }) {
  const symbol = vote === 'y' ? '✓' : vote === 'n' ? '✗' : '⊘';
  const sColor = vote === 'y' ? T.allow : vote === 'n' ? T.refuse : T.caution;
  const tba = tbaFor(agent.id);
  return (
    <a href={basescanAddr(tba)} target="_blank" rel="noopener"
       style={{
         display: 'grid', gridTemplateColumns: '14px 1fr auto', gap: 8, alignItems: 'center',
         padding: '6px 0', borderTop: `1px dashed rgba(244,244,240,0.06)`,
       }}>
      <span style={{
        fontFamily: GMONO, fontSize: 12, color: sColor, fontWeight: 600,
        textAlign: 'center', lineHeight: 1,
      }}>{symbol}</span>
      <span style={{ display: 'flex', alignItems: 'baseline', gap: 8, minWidth: 0 }}>
        <span style={{
          fontFamily: GMONO, fontSize: 11, fontWeight: 500,
          color: T.textInv, letterSpacing: 0.4,
        }}>#{String(agent.id).padStart(2, '0')}</span>
        <span style={{
          fontFamily: GMONO, fontSize: 11, fontWeight: 500,
          color: T.textInv, letterSpacing: 0.4,
        }}>{agent.name}</span>
      </span>
      <Mono color={T.muteInv} size={9}>{fmtAddr(tba, 4, 4)} ↗</Mono>
    </a>
  );
}

function ReceiptCell({ k, v, color }) {
  return (
    <div>
      <Mono color={T.muteInv} size={9}>{k}</Mono>
      <div style={{
        marginTop: 4, fontFamily: GMONO, fontSize: 13, fontWeight: 500,
        color: color || T.textInv, letterSpacing: 0.4,
      }}>{v}</div>
    </div>
  );
}

Object.assign(window, { LiveCouncilFeed, FEED_ORDERS });
