/* book.jsx — Order Book + Recent Trades. Live-ticking, fills column height, with pop-and-float trade chips. */

const { useMemo: bkUseMemo, useState: bkUseState, useEffect: bkUseEffect, useRef: bkUseRef } = React;

function BookRow({ row, maxCum, side, flash }) {
  const pct = (row.cum / maxCum) * 100;
  const isAsk = side === 'ask';
  return (
    <div className="relative grid grid-cols-12 items-center h-[20px] px-3 hover:bg-bg-hover">
      <div
        className="absolute right-0 top-0 bottom-0 pointer-events-none transition-[width] duration-300"
        style={{
          width: `${pct}%`,
          background: isAsk ? 'rgba(236,79,101,0.10)' : 'rgba(46,189,133,0.10)'
        }}
      />
      <div className={`col-span-4 font-mono text-[11.5px] ${isAsk ? 'text-red' : 'text-green'} relative`}>
        {row.price.toFixed(4)}
      </div>
      <div
        className="col-span-4 font-mono text-[11.5px] text-text relative text-right"
        style={flash ? { background: flash === 'up' ? 'rgba(46,189,133,0.20)' : 'rgba(236,79,101,0.18)', transition: 'background 0.4s ease-out' } : undefined}
      >
        {row.size.toLocaleString()}
      </div>
      <div className="col-span-4 font-mono text-[11px] text-text-3 relative text-right">
        {row.cum.toLocaleString()}
      </div>
    </div>
  );
}

function useLiveBook(timeframe = '5m', coin) {
  const tfMid = bkUseMemo(() => {
    if (coin && window.TR.impliedYesFor) {
      return Math.round(window.TR.impliedYesFor(coin, timeframe) * 10000) / 10000;
    }
    return { '1m': 0.6420, '5m': 0.5980, '15m': 0.5440, '1h': 0.4720 }[timeframe] || 0.6420;
  }, [coin, timeframe]);

  const seed = bkUseMemo(() => {
    const b = window.TR.buildBook(timeframe);
    // Rebase prices around the coin/tf-specific mid
    const shift = tfMid - b.mid;
    return {
      asks: b.asks.map(r => ({ ...r, price: Math.round((r.price + shift) * 10000) / 10000 })),
      bids: b.bids.map(r => ({ ...r, price: Math.round((r.price + shift) * 10000) / 10000 })),
      mid: tfMid,
      spread: b.spread,
    };
  }, [timeframe, tfMid]);
  const [asks, setAsks] = bkUseState(() => seed.asks.map(r => ({ ...r })));
  const [bids, setBids] = bkUseState(() => seed.bids.map(r => ({ ...r })));
  const [mid, setMid] = bkUseState(seed.mid);
  const [flashes, setFlashes] = bkUseState({});
  const flashTimers = bkUseRef({});

  bkUseEffect(() => {
    const id = setInterval(() => {
      const mutate = (rows, sideSign) => {
        const next = rows.map(r => ({ ...r }));
        const n = 2 + Math.floor(Math.random() * 2);
        const newFlashes = {};
        for (let i = 0; i < n; i++) {
          const idx = Math.floor(Math.random() * next.length);
          const delta = Math.round((Math.random() - 0.5) * 240);
          const oldSize = next[idx].size;
          const newSize = Math.max(50, oldSize + delta);
          next[idx].size = newSize;
          newFlashes[next[idx].price.toFixed(4)] = newSize > oldSize ? 'up' : 'down';
        }
        if (sideSign === 'ask') {
          let c = 0;
          for (let i = next.length - 1; i >= 0; i--) { c += next[i].size; next[i].cum = c; }
        } else {
          let c = 0;
          for (let i = 0; i < next.length; i++) { c += next[i].size; next[i].cum = c; }
        }
        return { next, newFlashes };
      };
      const a = mutate(asks, 'ask');
      const b = mutate(bids, 'bid');
      setAsks(a.next);
      setBids(b.next);
      setMid(m => Math.round((m + (Math.random() - 0.5) * 0.0008) * 10000) / 10000);
      const allFlashes = { ...a.newFlashes, ...b.newFlashes };
      setFlashes(prev => ({ ...prev, ...allFlashes }));
      Object.keys(allFlashes).forEach(key => {
        clearTimeout(flashTimers.current[key]);
        flashTimers.current[key] = setTimeout(() => {
          setFlashes(prev => {
            const cp = { ...prev };
            delete cp[key];
            return cp;
          });
        }, 380);
      });
    }, 500);
    return () => clearInterval(id);
  }, []);

  return { asks, bids, mid, spread: seed.spread, flashes };
}

function useLiveTrades(timeframe = '5m', coin) {
  const tfMid = coin && window.TR.impliedYesFor
    ? Math.round(window.TR.impliedYesFor(coin, timeframe) * 10000) / 10000
    : ({ '1m': 0.6420, '5m': 0.5980, '15m': 0.5440, '1h': 0.4720 }[timeframe] || 0.6420);
  const [trades, setTrades] = bkUseState(() => window.TR.recentTrades.map((t, i) => ({
    ...t,
    price: t.side === 'YES' ? tfMid : Math.round((1 - tfMid) * 10000) / 10000,
    _id: -1 - i,
  })));
  const nextId = bkUseRef(0);

  bkUseEffect(() => {
    const id = setInterval(() => {
      const side = Math.random() < 0.62 ? 'YES' : 'NO';
      const basePrice = side === 'YES' ? tfMid : Math.round((1 - tfMid) * 10000) / 10000;
      const price = Math.round((basePrice + (Math.random() - 0.5) * 0.0040) * 10000) / 10000;
      const size = 80 + Math.floor(Math.random() * 1900);
      const tid = nextId.current++;
      const t = { _id: tid, side, price, size, ago: '0.2s' };

      setTrades(prev => {
        const aged = prev.map(p => ({ ...p, ago: ((parseFloat(p.ago) || 0) + 1.4).toFixed(1) + 's' }));
        return [t, ...aged].slice(0, 30);
      });

      // Broadcast for chart-pane popping chip
      window.TR.events.emit({ kind: 'trade', id: tid, side, price, size });
    }, 1400);
    return () => clearInterval(id);
  }, []);

  return { trades };
}

function OrderBook({ timeframe = '5m', coin }) {
  const book = useLiveBook(timeframe, coin);
  const { trades } = useLiveTrades(timeframe, coin);

  const maxCum = bkUseMemo(() => {
    return Math.max(...book.asks.map(r => r.cum), ...book.bids.map(r => r.cum));
  }, [book.asks, book.bids]);

  const spreadPct = (book.spread / book.mid) * 100;

  return (
    <div className="flex flex-col h-full bg-panel">
      {/* Title */}
      <div className="h-[36px] px-3 flex items-center justify-between hl-b shrink-0">
        <span className="font-mono text-[10.5px] tracking-[0.18em] uppercase text-text">ORDER BOOK</span>
        <span className="font-mono text-[9.5px] tracking-[0.12em] uppercase text-text-3 inline-flex items-center gap-1.5 h-[20px] px-2 rounded-full bg-bg-3 border border-panel-3">USDC</span>
      </div>

      <div className="grid grid-cols-12 h-[20px] px-3 items-center hl-b shrink-0 font-mono text-[9.5px] tracking-[0.14em] uppercase text-text-3">
        <div className="col-span-4">Price</div>
        <div className="col-span-4 text-right">Size</div>
        <div className="col-span-4 text-right">Cum</div>
      </div>

      {/* Asks */}
      <div className="flex flex-col-reverse shrink-0">
        {book.asks.map(r => (
          <BookRow key={`a${r.price.toFixed(4)}`} row={r} maxCum={maxCum} side="ask" flash={book.flashes[r.price.toFixed(4)]} />
        ))}
      </div>

      {/* Mid / spread */}
      <div className="h-[36px] hl-t hl-b shrink-0 px-3 flex items-center justify-between bg-bg-2">
        <div className="flex items-center gap-2.5">
          <span className="font-mono text-[10px] tracking-[0.14em] uppercase text-text-3">Mid</span>
          <span className="font-mono text-[14px] text-text">{book.mid.toFixed(4)}</span>
        </div>
        <div className="flex items-center gap-2.5">
          <span className="font-mono text-[10px] tracking-[0.14em] uppercase text-text-3">Spread</span>
          <span className="font-mono text-[12px] text-text-2">{book.spread.toFixed(4)} · {spreadPct.toFixed(2)}%</span>
        </div>
      </div>

      {/* Bids */}
      <div className="flex flex-col shrink-0">
        {book.bids.map(r => (
          <BookRow key={`b${r.price.toFixed(4)}`} row={r} maxCum={maxCum} side="bid" flash={book.flashes[r.price.toFixed(4)]} />
        ))}
      </div>

      {/* Trades section — fills remaining */}
      <div className="flex-1 min-h-0 flex flex-col hl-t mt-1">
        <div className="h-[34px] px-3 flex items-center justify-between hl-b shrink-0">
          <span className="font-mono text-[10.5px] tracking-[0.18em] uppercase text-text">RECENT TRADES</span>
          <span className="font-mono text-[9.5px] tracking-[0.12em] uppercase text-text-3">TAKER</span>
        </div>
        <div className="grid grid-cols-12 h-[20px] px-3 items-center hl-b font-mono text-[9.5px] tracking-[0.14em] uppercase text-text-3 shrink-0">
          <div className="col-span-3">Side</div>
          <div className="col-span-3">Price</div>
          <div className="col-span-3 text-right">Size</div>
          <div className="col-span-3 text-right">Age</div>
        </div>

        {/* The trades list itself */}
        <div className="flex-1 min-h-0 overflow-hidden relative">
          {trades.map((t) => (
            <TradeRow key={t._id} trade={t} />
          ))}
        </div>
      </div>
    </div>
  );
}

function TradeRow({ trade }) {
  const isFresh = parseFloat(trade.ago) < 1;
  return (
    <div
      className="grid grid-cols-12 h-[22px] px-3 items-center hover:bg-bg-hover"
      style={isFresh ? { background: trade.side === 'YES' ? 'rgba(46,189,133,0.10)' : 'rgba(236,79,101,0.10)', transition: 'background 0.8s ease-out' } : undefined}
    >
      <div className={`col-span-3 font-mono text-[11.5px] ${trade.side === 'YES' ? 'text-green' : 'text-red'}`}>{trade.side}</div>
      <div className="col-span-3 font-mono text-[11.5px] text-text">{trade.price.toFixed(4)}</div>
      <div className="col-span-3 font-mono text-[11.5px] text-text text-right">{trade.size.toLocaleString()}</div>
      <div className="col-span-3 font-mono text-[11px] text-text-3 text-right">{trade.ago}</div>
    </div>
  );
}

Object.assign(window, { OrderBook, BookRow });
