// ─────────────────────────────────────────────────────────────
// CanvasChat — the conversation as a living VINE (matches the product):
// a central organic trunk weaves down the thread, curved branch-edges
// connect each message bubble, and where the thread forks, a branch
// spur weaves off to a SUBTLE indicator/button — tap it to jump into
// the focus graph (tree, re-rooted on that branch). The indicator grows
// with how much branched off it. With `live`, a new message's edge
// DRAWS IN with a sapwood pulse (§6.C C1) and the bubble blooms; your
// reading place is kept (D1).
// ─────────────────────────────────────────────────────────────
(function injectCanvasKf() {
  if (typeof document === 'undefined' || document.getElementById('lt-canvas-kf')) return;
  const s = document.createElement('style'); s.id = 'lt-canvas-kf';
  s.textContent = `
  @keyframes lt-pop{from{opacity:0;transform:translateY(8px) scale(.96)}to{opacity:1;transform:none}}
  @keyframes lt-vdraw{0%{stroke-dashoffset:1;opacity:0}18%{opacity:1}100%{stroke-dashoffset:0;opacity:1}}
  @keyframes lt-vsap{0%{offset-distance:0%;opacity:0}16%{opacity:1}82%{offset-distance:100%;opacity:1}100%{offset-distance:100%;opacity:0}}
  .lt-pop{animation:lt-pop .42s cubic-bezier(.32,.72,.34,1) both}
  .lt-vdraw{animation:lt-vdraw 1s ease-out both}
  .lt-vsap{animation:lt-vsap 1.05s ease-in-out both}`;
  document.head.appendChild(s);
})();

const CC = { you: '#4F8E51', them: '#A8C5A0', sun: '#D4960C', sun2: '#F4DCA0',
  vine: '#5E8048', vineHi: '#76AB78', fog: '#EDEFE6', fog2: '#C9D2BB', mute: '#586552',
  youBg: '#1F4524', youBorder: '#2C5F2E', themBg: '#12200C', themBorder: '#243319' };

function CanvasChat({ data, onOpenBranch, live, threadTo }) {
  const D = data || window.LT;
  const scrollRef = React.useRef(null);
  const contentRef = React.useRef(null);
  const bubbleRefs = React.useRef({});
  const targetRef = React.useRef(null);
  const wasBottom = React.useRef(true);
  const [extra, setExtra] = React.useState([]);
  const [unseen, setUnseen] = React.useState(0);
  const [vine, setVine] = React.useState({ trunk: '', spurs: [], branches: [], w: 360, h: 0 });
  const [newIds, setNewIds] = React.useState(() => new Set());
  const [tick, setTick] = React.useState(0);

  // the visible thread = path root → (threadTo or tip), then live messages
  const activeId = (threadTo != null) ? threadTo : D.tip;
  const apath = D.pathTo(activeId);
  const msgs = apath.map((id, i) => {
    const n = D.byId[id], next = apath[i + 1];
    const side = n.kids.filter((k) => k !== next);
    return { _k: 'n' + id, id, author: n.author, text: n.text, time: n.time,
      branchN: side.reduce((s, k) => s + D.byId[k].size, 0), branchC: side.length,
      branchId: side.length ? id : null, isTarget: id === activeId && threadTo != null };
  });
  const all = [...msgs, ...extra.map((e) => ({ ...e, branchN: 0, branchC: 0, branchId: null }))];

  // ---- measure bubble positions → build the weaving vine ----
  React.useLayoutEffect(() => {
    const content = contentRef.current; if (!content) return;
    const W = content.clientWidth, trunkX = W * 0.53;
    const pts = [];
    all.forEach((m, i) => {
      const el = bubbleRefs.current[m._k]; if (!el) return;
      const cy = el.offsetTop + el.offsetHeight / 2, mine = m.author === 'you';
      pts.push({ id: m._k, cy, mine, branchN: m.branchN, branchC: m.branchC, branchId: m.branchId,
        nearX: mine ? el.offsetLeft : el.offsetLeft + el.offsetWidth, tx: trunkX + Math.sin(i * 0.8) * 11 });
    });
    let trunk = '';
    if (pts.length) {
      const head = { tx: pts[0].tx, cy: Math.max(0, pts[0].cy - 46) };
      trunk = `M ${head.tx} ${head.cy}`;
      let prev = head;
      for (const b of pts) { const my = (prev.cy + b.cy) / 2; trunk += ` C ${prev.tx} ${my}, ${b.tx} ${my}, ${b.tx} ${b.cy}`; prev = b; }
      trunk += ` C ${prev.tx} ${prev.cy + 40}, ${prev.tx} ${prev.cy + 40}, ${prev.tx} ${prev.cy + 70}`;
    }
    const spurs = pts.map((b) => { const cx = (b.tx + b.nearX) / 2; return { id: b.id, d: `M ${b.tx} ${b.cy} C ${cx} ${b.cy - 7}, ${cx} ${b.cy + 7}, ${b.nearX} ${b.cy}` }; });
    const branches = pts.filter((b) => b.branchN > 0).map((b) => {
      const dir = b.mine ? -1 : 1, reach = 70 + Math.min(40, b.branchN / 6), ex = b.tx + dir * reach, ey = b.cy + 46;
      return { id: b.id, branchId: b.branchId, n: b.branchN, c: b.branchC, x: ex, y: ey, mine: b.mine, big: b.branchN >= 140,
        w: 0.8 + Math.min(1.6, b.branchN / 120),
        d: `M ${b.tx} ${b.cy} C ${b.tx + dir * 26} ${b.cy + 26}, ${ex - dir * 14} ${ey - 14}, ${ex} ${ey}` };
    });
    setVine({ trunk, spurs, branches, w: W, h: content.scrollHeight });
  }, [all.length, threadTo, tick]);

  React.useEffect(() => { let on = true; (document.fonts ? document.fonts.ready : Promise.resolve()).then(() => { if (on) setTick((t) => t + 1); }); return () => { on = false; }; }, []);

  // scroll to target (View in chat) or to the tip
  React.useEffect(() => {
    const el = scrollRef.current; if (!el) return;
    if (threadTo != null && targetRef.current) el.scrollTop = Math.max(0, targetRef.current.offsetTop - 130);
    else el.scrollTop = el.scrollHeight;
  }, [threadTo, vine.h]);

  // ---- live arrivals (C1 edge-grow + sapwood pulse + bloom; D1 anchor) ----
  React.useEffect(() => {
    if (!live) { setExtra([]); setUnseen(0); setNewIds(new Set()); return; }
    let timer;
    const tickFn = () => {
      const el = scrollRef.current;
      wasBottom.current = el ? (el.scrollHeight - el.scrollTop - el.clientHeight < 80) : true;
      const au = Math.random() < 0.5 ? 'you' : 'them';
      const txt = au === 'you' ? ['oh wait', 'yes exactly', 'I’ll come by', 'tell me more', 'that’s perfect', 'haha stop'][Math.floor(Math.random() * 6)]
                               : ['right??', 'I knew it', 'omg', 'come over', 'I’ll send it', 'love you'][Math.floor(Math.random() * 6)];
      const k = 'x' + Date.now() + Math.random();
      setExtra((e) => [...e, { _k: k, author: au, text: txt, time: 'now' }]);
      setNewIds((s) => new Set(s).add(k));
      setTimeout(() => setNewIds((s) => { const n = new Set(s); n.delete(k); return n; }), 1400);
      timer = setTimeout(tickFn, 2600 + Math.random() * 1900);
    };
    timer = setTimeout(tickFn, 1600);
    return () => clearTimeout(timer);
  }, [live]);

  React.useLayoutEffect(() => {
    const el = scrollRef.current; if (!el || !extra.length) return;
    if (wasBottom.current) el.scrollTop = el.scrollHeight; else setUnseen((u) => u + 1);
  }, [extra.length]);

  return (
    <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', background: '#07100A' }}>
      <div ref={scrollRef} style={{ flex: 1, overflowY: 'auto' }}>
        <div ref={contentRef} style={{ position: 'relative', padding: '16px 18px 28px' }}>

          {/* the weaving vine (behind bubbles) */}
          <svg width={vine.w} height={vine.h} style={{ position: 'absolute', top: 0, left: 18, pointerEvents: 'none', overflow: 'visible', zIndex: 0 }}>
            <path d={vine.trunk} stroke={CC.vine} strokeOpacity={0.5} strokeWidth={1.5} fill="none" strokeLinecap="round"/>
            {vine.spurs.map((s) => {
              const fresh = newIds.has(s.id);
              return <path key={s.id} d={s.d} className={fresh ? 'lt-vdraw' : undefined} pathLength={fresh ? 1 : undefined}
                style={fresh ? { strokeDasharray: 1 } : undefined} stroke={fresh ? CC.vineHi : CC.vine} strokeOpacity={fresh ? 0.9 : 0.5} strokeWidth={1.1} fill="none" strokeLinecap="round"/>;
            })}
            {vine.spurs.filter((s) => newIds.has(s.id)).map((s) => (
              <circle key={'sap' + s.id} className="lt-vsap" r={2.6} fill={CC.sun2} style={{ offsetPath: `path('${s.d}')` }}/>
            ))}
            {vine.branches.map((b) => (
              <path key={'br' + b.id} d={b.d} stroke={b.big ? CC.sun : CC.vine} strokeOpacity={b.big ? 0.34 : 0.3} strokeWidth={b.w} strokeDasharray="2 3" fill="none" strokeLinecap="round"/>
            ))}
          </svg>

          {/* branch indicators — subtle, sized by how much branched; tap → focus graph */}
          {vine.branches.map((b) => (
            <button key={'bc' + b.id} onClick={() => b.branchId != null && onOpenBranch(b.branchId)}
              title="Open this branch in the tree"
              style={{ position: 'absolute', left: 18 + b.x, top: b.y, transform: `translate(${b.mine ? '-100%' : '0'}, -50%)`, zIndex: 2,
                cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 5, padding: '3px 9px', borderRadius: 999, whiteSpace: 'nowrap',
                background: b.big ? 'rgba(58,42,7,.82)' : 'rgba(7,16,10,.82)',
                border: `0.5px ${b.big ? 'solid' : 'dashed'} ${b.big ? 'rgba(212,150,12,.55)' : '#3A4A30'}`,
                font: `500 ${b.big ? 10.5 : 9.5}px var(--font-mono)`, color: b.big ? CC.sun2 : '#76AB78' }}>
              <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke={b.big ? CC.sun2 : '#76AB78'} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                <polyline points="15 10 20 15 15 20"/><path d="M4 4v7a4 4 0 0 0 4 4h12"/></svg>
              {b.n} <span style={{ opacity: 0.7 }}>▸</span>
            </button>
          ))}

          {/* messages */}
          <div style={{ position: 'relative', zIndex: 1, display: 'flex', flexDirection: 'column', gap: 14 }}>
            {all.map((m) => {
              const mine = m.author === 'you', fresh = newIds.has(m._k);
              return (
                <div key={m._k} ref={m.isTarget ? targetRef : null}
                  style={{ display: 'flex', flexDirection: 'column', alignItems: mine ? 'flex-end' : 'flex-start' }}>
                  <div style={{ font: '400 9.5px var(--font-mono)', color: CC.mute, margin: '0 4px 3px' }}>
                    {mine ? 'you' : 'marina_k'} · {m.time}{m.time === 'now' ? '' : ' ago'}
                  </div>
                  <div ref={(el) => (bubbleRefs.current[m._k] = el)} className={fresh ? 'lt-pop' : undefined}
                    style={{ maxWidth: 250, padding: '9px 13px', borderRadius: 16,
                      borderBottomRightRadius: mine ? 5 : 16, borderBottomLeftRadius: mine ? 16 : 5,
                      background: mine ? CC.youBg : CC.themBg,
                      border: `0.5px solid ${m.isTarget ? CC.sun : (mine ? CC.youBorder : CC.themBorder)}`,
                      boxShadow: m.isTarget ? '0 0 0 3px rgba(212,150,12,.16)' : 'none',
                      font: '400 14px/1.4 var(--font-sans)', color: CC.fog }}>{m.text}</div>
                </div>
              );
            })}
          </div>
        </div>
      </div>

      {/* D1 unseen pill */}
      {unseen > 0 && (
        <button onClick={() => { const el = scrollRef.current; if (el) el.scrollTop = el.scrollHeight; setUnseen(0); }}
          style={{ position: 'absolute', left: '50%', bottom: 76, transform: 'translateX(-50%)', cursor: 'pointer',
            display: 'inline-flex', alignItems: 'center', gap: 7, padding: '6px 13px', borderRadius: 999,
            background: 'rgba(58,42,7,.92)', border: `0.5px solid ${CC.sun}`, font: '500 11px var(--font-sans)', color: CC.sun2 }}>
          <svg width="11" height="11" viewBox="0 0 12 12" fill="none"><path d="M2 4l4 4 4-4" stroke={CC.sun2} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/></svg>
          {unseen} new · your place is kept
        </button>
      )}

      {/* composer */}
      <div style={{ flexShrink: 0, padding: '8px 12px 12px', borderTop: '0.5px solid #14210C', display: 'flex', alignItems: 'center', gap: 9 }}>
        <div style={{ flex: 1, padding: '11px 15px', borderRadius: 999, background: '#0F1A09', border: '0.5px solid #2D3A22',
          font: '400 13.5px var(--font-sans)', color: CC.mute }}>Plant a leaf…</div>
        <button style={{ width: 40, height: 40, borderRadius: '50%', flexShrink: 0, cursor: 'pointer', background: '#2C5F2E',
          border: '0.5px solid #4F8E51', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#F2EDE4" strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round">
            <path d="M12 19V5"/><path d="m5 12 7-7 7 7"/></svg>
        </button>
      </div>
    </div>
  );
}

window.CanvasChat = CanvasChat;
