/* cst-share-card.jsx — the viral unit: a branded, auto-generated RESULT CARD
   rendered to canvas in two formats (1080×1080 square + 1080×1920 story).
   Console aesthetic: ink + JetBrains Mono + procedural graph field + accent.
   Exported to window.CST_CARD. Pure drawing — no React. */

const _CC = window.CST;

// deterministic RNG so a given result always draws the same graph field
function seeded(seed) {
  let s = (seed >>> 0) || 1;
  return () => { s = (s * 1664525 + 1013904223) >>> 0; return s / 4294967296; };
}
function hashStr(str) {
  let h = 2166136261 >>> 0;
  for (let i = 0; i < (str || '').length; i++) { h ^= str.charCodeAt(i); h = Math.imul(h, 16777619); }
  return h >>> 0;
}

// ensure Bricolage Grotesque is available to canvas before drawing
async function ensureFont() {
  try {
    if (document.fonts && document.fonts.load) {
      await Promise.all([
        document.fonts.load('800 200px "Bricolage Grotesque"'),
        document.fonts.load('700 48px "Bricolage Grotesque"'),
        document.fonts.load('600 32px "Bricolage Grotesque"'),
        document.fonts.load('500 26px "Bricolage Grotesque"'),
      ]);
      await document.fonts.ready;
    }
  } catch (e) { /* fall back to whatever's available */ }
}

const FT = "'Bricolage Grotesque', ui-sans-serif, system-ui, sans-serif";

function wrap(ctx, text, maxW) {
  const words = (text || '').split(/\s+/);
  const lines = []; let line = '';
  for (const w of words) {
    const test = line ? line + ' ' + w : w;
    if (ctx.measureText(test).width > maxW && line) { lines.push(line); line = w; }
    else line = test;
  }
  if (line) lines.push(line);
  return lines;
}

function roundRect(ctx, x, y, w, h, r) {
  ctx.beginPath();
  ctx.moveTo(x + r, y);
  ctx.arcTo(x + w, y, x + w, y + h, r);
  ctx.arcTo(x + w, y + h, x, y + h, r);
  ctx.arcTo(x, y + h, x, y, r);
  ctx.arcTo(x, y, x + w, y, r);
  ctx.closePath();
}

// --- procedural graph background (low-key, sits behind a center scrim) ---
function drawField(ctx, W, H, accent, seed) {
  const rnd = seeded(seed);
  const N = Math.round((W * H) / 42000);
  const nodes = [];
  for (let i = 0; i < N; i++) nodes.push({ x: rnd() * W, y: rnd() * H, r: 2 + rnd() * 5 });
  // edges to nearest-ish neighbours
  ctx.lineWidth = 1.4;
  for (let i = 0; i < nodes.length; i++) {
    let best = -1, bd = 1e9;
    for (let j = 0; j < nodes.length; j++) {
      if (i === j) continue;
      const d = (nodes[i].x - nodes[j].x) ** 2 + (nodes[i].y - nodes[j].y) ** 2;
      if (d < bd) { bd = d; best = j; }
    }
    if (best >= 0 && bd < (W * 0.34) ** 2) {
      ctx.strokeStyle = 'rgba(236,237,241,0.07)';
      ctx.beginPath(); ctx.moveTo(nodes[i].x, nodes[i].y); ctx.lineTo(nodes[best].x, nodes[best].y); ctx.stroke();
    }
  }
  for (const n of nodes) {
    const lit = rnd() > 0.74;
    ctx.fillStyle = lit ? accent : 'rgba(236,237,241,0.22)';
    if (lit) { ctx.shadowColor = accent; ctx.shadowBlur = 16; } else { ctx.shadowBlur = 0; }
    ctx.beginPath(); ctx.arc(n.x, n.y, n.r, 0, Math.PI * 2); ctx.fill();
  }
  ctx.shadowBlur = 0;
}

// --- CS Tech mark (brackets + CS) ---
function drawLogo(ctx, x, y, scale, accent) {
  ctx.save();
  ctx.translate(x, y); ctx.scale(scale, scale);
  ctx.strokeStyle = '#FFB454'; ctx.lineWidth = 3.4; ctx.lineCap = 'round'; ctx.lineJoin = 'round';
  ctx.beginPath(); ctx.moveTo(23, 9); ctx.lineTo(15, 9); ctx.quadraticCurveTo(11, 9, 11, 13); ctx.lineTo(11, 20); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(33, 38); ctx.lineTo(41, 38); ctx.quadraticCurveTo(45, 38, 45, 34); ctx.lineTo(45, 27); ctx.stroke();
  ctx.fillStyle = '#ECEDF1'; ctx.font = `800 17px ${FT}`; ctx.textAlign = 'center'; ctx.textBaseline = 'middle';
  ctx.fillText('CS', 28, 25);
  ctx.restore();
}

// --- main draw ---
// spec: { tool, accent, heroValue, heroUnit, heroKind:'ring'|'plain', ringPct,
//         badge, verdict, subject, leaderboard, challenge, shortlink }
async function drawCard(canvas, spec, opts = {}) {
  const story = !!opts.story;
  const W = 1080, H = story ? 1920 : 1080;
  canvas.width = W; canvas.height = H;
  await ensureFont();
  const ctx = canvas.getContext('2d');
  const accent = spec.accent || '#FFB454';
  const seed = hashStr((spec.tool || '') + (spec.verdict || '') + (spec.heroValue || ''));

  // background
  ctx.fillStyle = '#0B0D11'; ctx.fillRect(0, 0, W, H);
  let g = ctx.createRadialGradient(W / 2, story ? 560 : 360, 40, W / 2, story ? 560 : 360, W * 0.9);
  g.addColorStop(0, accent + '24'); g.addColorStop(0.5, 'rgba(15,17,21,0.2)'); g.addColorStop(1, 'rgba(11,13,17,0)');
  ctx.fillStyle = g; ctx.fillRect(0, 0, W, H);
  drawField(ctx, W, H, accent, seed);
  // center scrim for legibility
  const cs = ctx.createLinearGradient(0, 0, 0, H);
  cs.addColorStop(0, 'rgba(11,13,17,0.55)'); cs.addColorStop(0.35, 'rgba(11,13,17,0.78)');
  cs.addColorStop(0.7, 'rgba(11,13,17,0.78)'); cs.addColorStop(1, 'rgba(11,13,17,0.92)');
  ctx.fillStyle = cs; ctx.fillRect(0, 0, W, H);
  // accent frame
  ctx.strokeStyle = accent + '55'; ctx.lineWidth = 3; roundRect(ctx, 22, 22, W - 44, H - 44, 34); ctx.stroke();

  const M = 96;
  const L = story
    ? { logoY: 110, heroCY: 600, ring: 196, heroF: 230, badgeY: 880, verdictY: 1020, verdictF: 54, verdictLH: 72, lbY: 1280, divY: 1560, chalY: 1640, chalF: 46, linkY: 1740, wmY: 1858 }
    : { logoY: 92, heroCY: 392, ring: 150, heroF: 176, badgeY: 590, verdictY: 686, verdictF: 41, verdictLH: 54, lbY: 858, divY: 922, chalY: 968, chalF: 35, linkY: 1024, wmY: 1024 };

  // header
  drawLogo(ctx, M - 8, L.logoY - 26, 1.5, accent);
  ctx.textBaseline = 'alphabetic';
  ctx.textAlign = 'left'; ctx.fillStyle = '#ECEDF1'; ctx.font = `700 30px ${FT}`;
  ctx.fillText('CS Tech', M + 78, L.logoY - 4);
  ctx.fillStyle = 'rgba(236,237,241,0.5)'; ctx.font = `600 16px ${FT}`;
  ctx.fillText('OPERATING PARTNER', M + 78, L.logoY + 22);
  ctx.textAlign = 'right'; ctx.fillStyle = accent; ctx.font = `700 22px ${FT}`;
  ctx.fillText((spec.tool || '').toUpperCase(), W - M, L.logoY + 4);

  // hero
  ctx.textAlign = 'center';
  if (spec.heroKind === 'ring') {
    const cx = W / 2, cy = L.heroCY, R = L.ring, sw = R * 0.135;
    ctx.lineWidth = sw; ctx.lineCap = 'round';
    ctx.strokeStyle = 'rgba(236,237,241,0.12)';
    ctx.beginPath(); ctx.arc(cx, cy, R, 0, Math.PI * 2); ctx.stroke();
    ctx.strokeStyle = accent; ctx.shadowColor = accent; ctx.shadowBlur = 26;
    const a0 = -Math.PI / 2, a1 = a0 + (Math.PI * 2) * (_CC.clamp(spec.ringPct) / 100);
    ctx.beginPath(); ctx.arc(cx, cy, R, a0, a1); ctx.stroke(); ctx.shadowBlur = 0;
    ctx.fillStyle = '#ECEDF1'; ctx.font = `800 ${L.heroF}px ${FT}`; ctx.textBaseline = 'middle';
    ctx.fillText(String(spec.heroValue), cx, cy - R * 0.04);
    ctx.fillStyle = 'rgba(236,237,241,0.55)'; ctx.font = `600 ${Math.round(L.heroF * 0.16)}px ${FT}`;
    ctx.fillText(spec.heroUnit || '', cx, cy + R * 0.42);
    ctx.textBaseline = 'alphabetic';
  } else {
    ctx.fillStyle = accent; ctx.shadowColor = accent; ctx.shadowBlur = 30;
    ctx.font = `800 ${L.heroF}px ${FT}`; ctx.textBaseline = 'middle';
    ctx.fillText(String(spec.heroValue), W / 2, L.heroCY); ctx.shadowBlur = 0;
    if (spec.heroUnit) { ctx.fillStyle = 'rgba(236,237,241,0.6)'; ctx.font = `600 ${Math.round(L.heroF * 0.22)}px ${FT}`; ctx.fillText(spec.heroUnit, W / 2, L.heroCY + L.heroF * 0.62); }
    ctx.textBaseline = 'alphabetic';
  }

  // identity badge pill
  if (spec.badge) {
    ctx.font = `700 ${story ? 30 : 24}px ${FT}`;
    const bt = spec.badge.toUpperCase();
    const bw = ctx.measureText(bt).width + (story ? 64 : 52);
    const bh = story ? 64 : 52; const bx = (W - bw) / 2;
    ctx.fillStyle = accent + '1f'; roundRect(ctx, bx, L.badgeY - bh / 2, bw, bh, bh / 2); ctx.fill();
    ctx.strokeStyle = accent + '88'; ctx.lineWidth = 2; roundRect(ctx, bx, L.badgeY - bh / 2, bw, bh, bh / 2); ctx.stroke();
    ctx.fillStyle = accent; ctx.textAlign = 'center'; ctx.textBaseline = 'middle';
    // letterspace the badge
    ctx.fillText(bt.split('').join('\u200a'), W / 2, L.badgeY + 1);
    ctx.textBaseline = 'alphabetic';
  }

  // verdict (candid one-liner)
  ctx.fillStyle = '#ECEDF1'; ctx.font = `700 ${L.verdictF}px ${FT}`; ctx.textAlign = 'center';
  const vlines = wrap(ctx, '“' + (spec.verdict || '') + '”', W - M * 2).slice(0, story ? 4 : 3);
  vlines.forEach((ln, i) => ctx.fillText(ln, W / 2, L.verdictY + i * L.verdictLH));

  // leaderboard / compare line
  if (spec.leaderboard) {
    ctx.fillStyle = 'rgba(236,237,241,0.6)'; ctx.font = `500 ${story ? 30 : 24}px ${FT}`;
    const lb = wrap(ctx, spec.leaderboard, W - M * 2);
    lb.slice(0, 2).forEach((ln, i) => ctx.fillText(ln, W / 2, L.lbY + i * (story ? 40 : 32)));
  }

  // divider + challenge + link
  ctx.strokeStyle = 'rgba(236,237,241,0.12)'; ctx.lineWidth = 2;
  ctx.beginPath(); ctx.moveTo(M, L.divY); ctx.lineTo(W - M, L.divY); ctx.stroke();
  if (!story) {
    // square: challenge left, link chip right
    if (spec.hookCaps) {
      ctx.textAlign = 'left'; ctx.fillStyle = accent; ctx.font = `800 ${L.chalF + 4}px ${FT}`;
      if ('letterSpacing' in ctx) ctx.letterSpacing = '-1.5px';
      ctx.fillText((spec.challenge || '').toUpperCase(), M, L.chalY + 8);
      if ('letterSpacing' in ctx) ctx.letterSpacing = '0px';
    } else {
      ctx.textAlign = 'left'; ctx.fillStyle = accent; ctx.font = `700 ${L.chalF}px ${FT}`;
      ctx.fillText(spec.challenge || '', M, L.chalY + 8);
    }
    ctx.textAlign = 'right'; ctx.fillStyle = 'rgba(236,237,241,0.66)'; ctx.font = `600 24px ${FT}`;
    ctx.fillText(spec.shortlink || '', W - M, L.chalY + 44);
  } else {
    ctx.textAlign = 'center'; ctx.fillStyle = accent;
    if (spec.hookCaps) {
      ctx.font = `800 ${L.chalF + 4}px ${FT}`;
      if ('letterSpacing' in ctx) ctx.letterSpacing = '-1.5px';
      wrap(ctx, (spec.challenge || '').toUpperCase(), W - M * 2).slice(0, 2).forEach((ln, i) => ctx.fillText(ln, W / 2, L.chalY + i * 56));
      if ('letterSpacing' in ctx) ctx.letterSpacing = '0px';
    } else {
      ctx.font = `700 ${L.chalF}px ${FT}`;
      wrap(ctx, spec.challenge || '', W - M * 2).slice(0, 2).forEach((ln, i) => ctx.fillText(ln, W / 2, L.chalY + i * 56));
    }
    ctx.fillStyle = 'rgba(236,237,241,0.66)'; ctx.font = `600 30px ${FT}`;
    ctx.fillText(spec.shortlink || '', W / 2, L.linkY);
  }

  return canvas;
}

function toBlob(canvas) {
  return new Promise((res) => canvas.toBlob((b) => res(b), 'image/png', 0.95));
}

// ---- full report image (polished portrait one-pager) ----------------------
// spec: { tool, accent, score, ringUnit, verdict, summary, factors:[{label,value}],
//         sections:[{ title, kind:'para'|'list', body|items }], shortlink }
async function drawReport(canvas, spec) {
  const W = 1080, H = 1920, M = 92;
  canvas.width = W; canvas.height = H;
  await ensureFont();
  const ctx = canvas.getContext('2d');
  const accent = spec.accent || '#FFB454';
  const seed = hashStr((spec.tool || '') + (spec.verdict || ''));

  ctx.fillStyle = '#0B0D11'; ctx.fillRect(0, 0, W, H);
  const g = ctx.createRadialGradient(W / 2, 300, 40, W / 2, 300, W);
  g.addColorStop(0, accent + '1f'); g.addColorStop(0.55, 'rgba(15,17,21,0.15)'); g.addColorStop(1, 'rgba(11,13,17,0)');
  ctx.fillStyle = g; ctx.fillRect(0, 0, W, H);
  drawField(ctx, W, H, accent, seed);
  const sc = ctx.createLinearGradient(0, 0, 0, H);
  sc.addColorStop(0, 'rgba(11,13,17,0.74)'); sc.addColorStop(0.4, 'rgba(11,13,17,0.86)'); sc.addColorStop(1, 'rgba(11,13,17,0.93)');
  ctx.fillStyle = sc; ctx.fillRect(0, 0, W, H);
  ctx.strokeStyle = accent + '44'; ctx.lineWidth = 3; roundRect(ctx, 22, 22, W - 44, H - 44, 34); ctx.stroke();

  // header
  drawLogo(ctx, M - 8, 100, 1.5, accent);
  ctx.textAlign = 'left'; ctx.fillStyle = '#ECEDF1'; ctx.font = `700 30px ${FT}`;
  ctx.fillText('CS Tech', M + 78, 122);
  ctx.fillStyle = 'rgba(236,237,241,0.5)'; ctx.font = `600 16px ${FT}`; ctx.fillText('OPERATING PARTNER', M + 78, 148);
  ctx.textAlign = 'right'; ctx.fillStyle = accent; ctx.font = `700 22px ${FT}`;
  ctx.fillText((spec.tool || '') + ' · FULL REPORT', W - M, 128);

  // score ring + verdict
  const cy = 320, R = 96;
  ctx.lineWidth = 16; ctx.lineCap = 'round';
  ctx.strokeStyle = 'rgba(236,237,241,0.12)'; ctx.beginPath(); ctx.arc(M + R, cy, R, 0, Math.PI * 2); ctx.stroke();
  ctx.strokeStyle = accent; ctx.shadowColor = accent; ctx.shadowBlur = 22;
  ctx.beginPath(); ctx.arc(M + R, cy, R, -Math.PI / 2, -Math.PI / 2 + Math.PI * 2 * (_CC.clamp(spec.score) / 100)); ctx.stroke(); ctx.shadowBlur = 0;
  ctx.textAlign = 'center'; ctx.fillStyle = '#ECEDF1'; ctx.font = `800 78px ${FT}`; ctx.textBaseline = 'middle';
  ctx.fillText(String(spec.score), M + R, cy - 6);
  ctx.fillStyle = 'rgba(236,237,241,0.55)'; ctx.font = `600 18px ${FT}`; ctx.fillText(spec.ringUnit || '/ 100', M + R, cy + 34);
  ctx.textBaseline = 'alphabetic';
  // verdict text to the right
  const vx = M + R * 2 + 40, vw = W - M - vx;
  ctx.textAlign = 'left'; ctx.fillStyle = '#ECEDF1'; ctx.font = `700 34px ${FT}`;
  let yy = cy - 40;
  wrap(ctx, spec.verdict || '', vw).slice(0, 4).forEach((ln) => { ctx.fillText(ln, vx, yy); yy += 42; });

  // factor bars
  let y = 500;
  if (spec.factors && spec.factors.length) {
    ctx.textAlign = 'left'; ctx.fillStyle = accent; ctx.font = `700 20px ${FT}`;
    ctx.fillText('HOW IT SCORES', M, y); y += 34;
    spec.factors.forEach((f) => {
      ctx.fillStyle = '#ECEDF1'; ctx.font = `600 24px ${FT}`; ctx.textAlign = 'left'; ctx.fillText(f.label, M, y);
      ctx.fillStyle = accent; ctx.textAlign = 'right'; ctx.font = `700 24px ${FT}`; ctx.fillText(String(f.value), W - M, y);
      y += 14;
      ctx.fillStyle = 'rgba(236,237,241,0.10)'; roundRect(ctx, M, y, W - M * 2, 12, 6); ctx.fill();
      ctx.fillStyle = accent; roundRect(ctx, M, y, (W - M * 2) * _CC.clamp(f.value) / 100, 12, 6); ctx.fill();
      y += 40;
    });
    y += 16;
  }

  // text sections
  (spec.sections || []).forEach((s) => {
    if (y > H - 220) return;
    ctx.textAlign = 'left'; ctx.fillStyle = accent; ctx.font = `700 20px ${FT}`;
    ctx.fillText(s.title.toUpperCase(), M, y); y += 32;
    ctx.fillStyle = 'rgba(236,237,241,0.86)'; ctx.font = `400 23px ${FT}`;
    if (s.kind === 'list') {
      (s.items || []).slice(0, 4).forEach((it) => {
        const lines = wrap(ctx, '•  ' + it, W - M * 2 - 8);
        lines.slice(0, 3).forEach((ln, i) => { if (y > H - 180) return; ctx.fillText(i === 0 ? ln : '   ' + ln, M, y); y += 30; });
        y += 6;
      });
    } else {
      wrap(ctx, s.body || '', W - M * 2).slice(0, 4).forEach((ln) => { if (y > H - 180) return; ctx.fillText(ln, M, y); y += 30; });
    }
    y += 22;
  });

  // footer
  ctx.fillStyle = 'rgba(236,237,241,0.10)'; ctx.fillRect(M, H - 130, W - M * 2, 1);
  ctx.textAlign = 'left'; ctx.fillStyle = accent; ctx.font = `700 24px ${FT}`;
  ctx.fillText('Decide easier, better, faster.', M, H - 90);
  ctx.textAlign = 'right'; ctx.fillStyle = 'rgba(236,237,241,0.6)'; ctx.font = `600 22px ${FT}`;
  ctx.fillText(spec.shortlink || '', W - M, H - 90);
  return canvas;
}

window.CST_CARD = { drawCard, drawReport, toBlob, ensureFont };
