// charts.jsx — custom SVG visualizations for Atlas

const { useMemo: _useMemo, useState: _useState } = React;

// Sparkline / area chart
function Sparkline({ data, w = 320, h = 64, accent = false, fill = true }) {
  const max = Math.max(...data), min = Math.min(...data);
  const pad = 2;
  const dx = (w - pad * 2) / (data.length - 1);
  const sy = v => h - pad - ((v - min) / (max - min || 1)) * (h - pad * 2);
  const pts = data.map((v, i) => `${pad + i * dx},${sy(v)}`).join(' ');
  const fillPts = `${pad},${h-pad} ${pts} ${w-pad},${h-pad}`;
  const stroke = accent ? 'var(--accent)' : 'var(--ink-2)';
  const fillC = accent ? 'var(--accent-soft)' : 'var(--bg-inset)';
  return (
    <svg viewBox={`0 0 ${w} ${h}`} width="100%" height={h} style={{display:'block'}}>
      {fill && <polygon points={fillPts} fill={fillC} />}
      <polyline points={pts} fill="none" stroke={stroke} strokeWidth="1.5" />
      <circle cx={pad + (data.length-1)*dx} cy={sy(data[data.length-1])} r="3" fill={stroke} />
    </svg>
  );
}

// Bar chart, horizontal
function HBar({ rows, w = 480, rowH = 28, max, accent = (i) => false, label = (r) => r.label, value = (r) => r.value, fmt = (v) => v }) {
  const M = max || Math.max(...rows.map(value));
  const labelW = 160;
  const barW = w - labelW - 70;
  return (
    <svg viewBox={`0 0 ${w} ${rows.length * rowH + 8}`} width="100%" height={rows.length * rowH + 8}>
      {rows.map((r, i) => {
        const v = value(r);
        const len = (v / M) * barW;
        const y = i * rowH + 4;
        return (
          <g key={i}>
            <text x={labelW - 12} y={y + rowH/2 + 4} textAnchor="end" style={{fontSize:12, fill:'var(--ink-2)', fontFamily:'var(--sans)'}}>{label(r)}</text>
            <rect x={labelW} y={y + rowH/2 - 5} width={barW} height="10" fill="var(--bg-inset)" />
            <rect x={labelW} y={y + rowH/2 - 5} width={len} height="10" fill={accent(i, r) ? 'var(--accent)' : 'var(--ink-2)'} />
            <text x={labelW + barW + 8} y={y + rowH/2 + 4} className="mono" style={{fontSize:11, fill:'var(--ink-3)', fontFamily:'var(--mono)'}}>{fmt(v)}</text>
          </g>
        );
      })}
    </svg>
  );
}

// Adoption ribbon: large area chart over time with annotations
function AdoptionRibbon({ data, w = 880, h = 220, total = 98 }) {
  const pad = { l: 40, r: 24, t: 28, b: 36 };
  const ww = w - pad.l - pad.r, hh = h - pad.t - pad.b;
  const max = total;
  const dx = ww / (data.length - 1);
  const sy = v => pad.t + hh - (v / max) * hh;
  const sx = i => pad.l + i * dx;
  const pts = data.map((v, i) => `${sx(i)},${sy(v)}`).join(' ');
  const fillPts = `${pad.l},${pad.t + hh} ${pts} ${pad.l + ww},${pad.t + hh}`;
  const last = data[data.length - 1];
  const first = data[0];
  return (
    <svg viewBox={`0 0 ${w} ${h}`} width="100%" height={h} style={{display:'block'}}>
      {/* gridlines */}
      {[0, .25, .5, .75, 1].map((g, i) => (
        <g key={i}>
          <line className="gridline" x1={pad.l} x2={pad.l + ww} y1={sy(max * g)} y2={sy(max * g)} strokeDasharray={i === 0 || i === 4 ? '' : '2 4'} />
          <text x={pad.l - 10} y={sy(max * g) + 4} textAnchor="end" style={{fontSize:10, fill:'var(--ink-3)', fontFamily:'var(--mono)', letterSpacing:'.04em'}}>{Math.round(max * g)}</text>
        </g>
      ))}
      {/* fill */}
      <polygon points={fillPts} fill="var(--accent-soft)" />
      <polyline points={pts} fill="none" stroke="var(--accent)" strokeWidth="1.6" />
      {/* dots */}
      <circle cx={sx(data.length - 1)} cy={sy(last)} r="4" fill="var(--accent)" />
      <circle cx={sx(data.length - 1)} cy={sy(last)} r="9" fill="none" stroke="var(--accent)" strokeOpacity=".25" />
      {/* x labels */}
      {data.map((v, i) => {
        if (i % 3 !== 0 && i !== data.length - 1) return null;
        return <text key={i} x={sx(i)} y={pad.t + hh + 18} textAnchor="middle" style={{fontSize:10, fill:'var(--ink-3)', fontFamily:'var(--mono)', letterSpacing:'.06em'}}>W{i + 1}</text>;
      })}
      {/* baseline marker */}
      <line x1={pad.l} x2={pad.l + ww} y1={sy(first)} y2={sy(first)} stroke="var(--ink-3)" strokeDasharray="2 3" strokeOpacity=".5" />
      <text x={pad.l + 4} y={sy(first) - 4} style={{fontSize:10, fill:'var(--ink-3)', fontFamily:'var(--mono)'}}>baseline {first}</text>
    </svg>
  );
}

// Workflow Strands — novel viz
// Stages laid out vertically as columns; each workflow is a strand passing through its stages.
// Strand thickness ~ sessions; color ~ rank (best/good/waste).
function WorkflowStrands({ flows, w = 880, h = 360, onHover }) {
  const stages = ['Architecture', 'Code gen', 'Refactor', 'Debug', 'Test gen', 'PR review', 'SQL', 'Verify', 'Merge', 'Done', 'Abandon'];
  // Use only stages actually appearing
  const used = Array.from(new Set(flows.flatMap(f => f.stages)));
  // Order them in a sensible flow
  const order = ['Architecture', 'Code gen', 'Refactor', 'Debug', 'SQL', 'Test gen', 'PR review', 'Verify', 'Merge', 'Done', 'Abandon']
    .filter(s => used.includes(s));
  const pad = { l: 24, r: 24, t: 36, b: 60 };
  const ww = w - pad.l - pad.r, hh = h - pad.t - pad.b;
  const colW = ww / (order.length - 1 || 1);
  const stageX = order.reduce((m, s, i) => (m[s] = pad.l + i * colW, m), {});

  // Map each flow to a vertical track
  const ranked = flows.slice().sort((a,b) => b.sessions - a.sessions);
  const trackH = hh / ranked.length;

  const colorFor = (rank) => rank === 'best' ? 'var(--accent)' : rank === 'good' ? 'var(--cat-2)' : 'var(--ink-3)';
  const strokeFor = (rank) => rank === 'waste' ? '#a23a2a' : (rank === 'best' ? 'var(--accent)' : 'var(--cat-2)');

  return (
    <svg viewBox={`0 0 ${w} ${h}`} width="100%" height={h} style={{display:'block'}}>
      {/* stage columns */}
      {order.map((s, i) => (
        <g key={s}>
          <line x1={stageX[s]} x2={stageX[s]} y1={pad.t - 8} y2={pad.t + hh + 8} stroke="var(--rule)" />
          <text x={stageX[s]} y={pad.t + hh + 28} textAnchor="middle" style={{fontSize:10, fill:'var(--ink-3)', fontFamily:'var(--mono)', letterSpacing:'.08em', textTransform:'uppercase'}}>{s}</text>
        </g>
      ))}
      {/* strands */}
      {ranked.map((f, i) => {
        const cy = pad.t + (i + 0.5) * trackH;
        const thick = 4 + Math.sqrt(f.sessions) / 6;
        // Build a smooth path through stage X positions, with a slight wave
        const xs = f.stages.map(s => stageX[s]);
        // For repeated stages, offset Y a bit
        const seen = {};
        const pts = f.stages.map((s, k) => {
          seen[s] = (seen[s] || 0);
          const off = seen[s] * 12;
          seen[s]++;
          return [stageX[s], cy + (k % 2 === 0 ? -off : off)];
        });
        // Build a smooth path using cubic bezier between consecutive points
        let d = `M ${pts[0][0]} ${pts[0][1]}`;
        for (let k = 1; k < pts.length; k++) {
          const [x0, y0] = pts[k-1], [x1, y1] = pts[k];
          const cx = (x0 + x1) / 2;
          d += ` C ${cx} ${y0}, ${cx} ${y1}, ${x1} ${y1}`;
        }
        const col = strokeFor(f.rank);
        return (
          <g key={f.id}
             onMouseEnter={(e) => onHover?.(f, e)}
             onMouseMove={(e) => onHover?.(f, e)}
             onMouseLeave={() => onHover?.(null)}>
            <path d={d} fill="none" stroke={col} strokeWidth={thick} strokeOpacity={f.rank === 'waste' ? 0.55 : 0.75} strokeLinecap="round" strokeLinejoin="round" style={{cursor:'pointer'}} />
            {pts.map(([x, y], k) => (
              <circle key={k} cx={x} cy={y} r={thick * 0.55} fill="var(--paper)" stroke={col} strokeWidth="1.4" />
            ))}
            {/* label at start */}
            <text x={pts[0][0] - 8} y={pts[0][1] + 4} textAnchor="end" style={{fontSize:11, fill:'var(--ink-2)', fontFamily:'var(--sans)'}}>
              {f.label}
            </text>
            {/* sessions at end */}
            <text x={pts[pts.length-1][0] + 10} y={pts[pts.length-1][1] + 4} style={{fontSize:10.5, fill:'var(--ink-3)', fontFamily:'var(--mono)', letterSpacing:'.04em'}}>
              {f.sessions.toLocaleString()}×
            </text>
          </g>
        );
      })}
    </svg>
  );
}

// Tool overlap — symmetric matrix
function OverlapMatrix({ tools, overlap, w = 360, cell = 44 }) {
  const N = tools.length;
  const get = (a, b) => {
    if (a === b) return 1;
    const k1 = `${a}-${b}`, k2 = `${b}-${a}`;
    return overlap[k1] ?? overlap[k2] ?? 0;
  };
  const labelW = 110;
  const W = labelW + N * cell + 30;
  const H = labelW + N * cell + 30;
  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={H} style={{display:'block'}}>
      {/* column labels */}
      {tools.map((t, i) => (
        <text key={`c${t.id}`}
              transform={`translate(${labelW + i * cell + cell/2}, ${labelW - 8}) rotate(-50)`}
              style={{fontSize:10.5, fill:'var(--ink-3)', fontFamily:'var(--mono)', letterSpacing:'.04em'}}
              textAnchor="start">{t.name}</text>
      ))}
      {/* row labels & cells */}
      {tools.map((row, ri) => (
        <g key={row.id}>
          <text x={labelW - 10} y={labelW + ri * cell + cell/2 + 4} textAnchor="end" style={{fontSize:11, fill:'var(--ink-2)', fontFamily:'var(--sans)'}}>{row.name}</text>
          {tools.map((col, ci) => {
            const v = get(row.id, col.id);
            const isDiag = ri === ci;
            const intensity = Math.max(0.04, Math.min(1, v));
            return (
              <g key={col.id}>
                <rect x={labelW + ci * cell} y={labelW + ri * cell} width={cell - 4} height={cell - 4}
                      fill={isDiag ? 'var(--ink)' : 'var(--accent)'}
                      fillOpacity={isDiag ? 0.92 : intensity * 0.85}
                      stroke="var(--paper)" strokeWidth="1.5" />
                {!isDiag && (
                  <text x={labelW + ci * cell + (cell - 4)/2} y={labelW + ri * cell + (cell - 4)/2 + 4} textAnchor="middle"
                        style={{fontSize:10, fill: intensity > 0.5 ? 'var(--paper)' : 'var(--ink-2)', fontFamily:'var(--mono)'}}>
                    {Math.round(v * 100)}
                  </text>
                )}
              </g>
            );
          })}
        </g>
      ))}
    </svg>
  );
}

// Layered Efficiency Score ribbon
// Show 5 component scores stacked horizontally for a team.
function ScoreRibbon({ row, w = 520, h = 86 }) {
  const components = [
    { k: 'delivery', label: 'Delivery' },
    { k: 'quality',  label: 'Quality' },
    { k: 'retention',label: 'Retention' },
    { k: 'cost',     label: 'Cost eff.' },
    { k: 'rework',   label: 'Anti-rework' },
  ];
  const pad = { l: 0, r: 0, t: 16, b: 24 };
  const ww = w, hh = h - pad.t - pad.b;
  const segW = ww / components.length;
  return (
    <svg viewBox={`0 0 ${w} ${h}`} width="100%" height={h} style={{display:'block'}}>
      {components.map((c, i) => {
        const v = row[c.k];
        const fillH = (v / 100) * hh;
        const x = i * segW;
        const isWeak = v < 60;
        return (
          <g key={c.k}>
            <rect x={x + 2} y={pad.t} width={segW - 4} height={hh} fill="var(--bg-inset)" />
            <rect x={x + 2} y={pad.t + (hh - fillH)} width={segW - 4} height={fillH}
                  fill={isWeak ? '#a23a2a' : 'var(--accent)'} fillOpacity={isWeak ? 0.5 : 0.85} />
            <text x={x + segW/2} y={pad.t + hh + 14} textAnchor="middle" style={{fontSize:10, fill:'var(--ink-3)', fontFamily:'var(--mono)', letterSpacing:'.06em', textTransform:'uppercase'}}>{c.label}</text>
            <text x={x + segW/2} y={pad.t - 4} textAnchor="middle" style={{fontSize:11, fill:'var(--ink-2)', fontFamily:'var(--mono)'}}>{v}</text>
          </g>
        );
      })}
    </svg>
  );
}

// Scatter: tool effectiveness — cost vs merge rate
function ToolScatter({ tools, metrics, w = 600, h = 360, accentTool }) {
  const pad = { l: 50, r: 32, t: 32, b: 44 };
  const ww = w - pad.l - pad.r, hh = h - pad.t - pad.b;
  const xMax = 5, yMin = 0.6, yMax = 0.95;
  const sx = v => pad.l + (v / xMax) * ww;
  const sy = v => pad.t + (1 - (v - yMin) / (yMax - yMin)) * hh;
  const rOf = m => 6 + Math.sqrt(m.users) * 2;
  return (
    <svg viewBox={`0 0 ${w} ${h}`} width="100%" height={h} style={{display:'block'}}>
      {/* gridlines */}
      {[0.6,0.7,0.8,0.9].map(v => (
        <g key={v}>
          <line className="gridline" x1={pad.l} x2={pad.l + ww} y1={sy(v)} y2={sy(v)} />
          <text x={pad.l - 8} y={sy(v) + 3} textAnchor="end" style={{fontSize:10, fill:'var(--ink-3)', fontFamily:'var(--mono)'}}>{Math.round(v*100)}%</text>
        </g>
      ))}
      {[0,1,2,3,4,5].map(v => (
        <g key={v}>
          <line className="gridline" x1={sx(v)} x2={sx(v)} y1={pad.t} y2={pad.t + hh} />
          <text x={sx(v)} y={pad.t + hh + 16} textAnchor="middle" style={{fontSize:10, fill:'var(--ink-3)', fontFamily:'var(--mono)'}}>${v}</text>
        </g>
      ))}
      {/* axis labels */}
      <text x={pad.l + ww/2} y={h - 6} textAnchor="middle" style={{fontSize:10, fill:'var(--ink-3)', fontFamily:'var(--mono)', letterSpacing:'.12em', textTransform:'uppercase'}}>Cost per merged PR</text>
      <text transform={`translate(14, ${pad.t + hh/2}) rotate(-90)`} textAnchor="middle" style={{fontSize:10, fill:'var(--ink-3)', fontFamily:'var(--mono)', letterSpacing:'.12em', textTransform:'uppercase'}}>Merge acceptance</text>
      {/* "ideal" zone */}
      <rect x={sx(0)} y={sy(0.95)} width={sx(2)-sx(0)} height={sy(0.78)-sy(0.95)} fill="var(--accent-soft)" stroke="var(--accent-line)" strokeDasharray="2 3" />
      <text x={sx(2) - 6} y={sy(0.78) - 6} textAnchor="end" style={{fontSize:10, fill:'var(--accent)', fontFamily:'var(--mono)', letterSpacing:'.08em', textTransform:'uppercase'}}>High-value zone</text>
      {/* points */}
      {metrics.map(m => {
        const t = tools.find(x => x.id === m.tool);
        const isAcc = accentTool === m.tool;
        return (
          <g key={m.tool}>
            <circle cx={sx(m.cost_per_pr)} cy={sy(m.merge)} r={rOf(m)}
                    fill={t.color} fillOpacity={isAcc ? 0.85 : 0.55}
                    stroke={isAcc ? 'var(--ink)' : 'transparent'} strokeWidth="1.5" />
            <text x={sx(m.cost_per_pr) + rOf(m) + 6} y={sy(m.merge) + 4} style={{fontSize:11.5, fill:'var(--ink-2)', fontFamily:'var(--sans)'}}>{t.name}</text>
          </g>
        );
      })}
    </svg>
  );
}

// Donut for use cases
function UseCaseDonut({ rows, w = 280, hole = 0.62 }) {
  const total = rows.reduce((s, r) => s + r.share, 0);
  const r = w/2 - 6;
  const cx = w/2, cy = w/2;
  let a = -Math.PI/2;
  const colors = ['var(--cat-1)','var(--cat-2)','var(--cat-3)','var(--cat-4)','var(--cat-5)','var(--cat-6)','var(--ink-3)','var(--ink-4)'];
  return (
    <svg viewBox={`0 0 ${w} ${w}`} width="100%" height={w} style={{display:'block'}}>
      {rows.map((row, i) => {
        const ang = (row.share / total) * Math.PI * 2;
        const a0 = a, a1 = a + ang;
        a = a1;
        const x0 = cx + r * Math.cos(a0), y0 = cy + r * Math.sin(a0);
        const x1 = cx + r * Math.cos(a1), y1 = cy + r * Math.sin(a1);
        const xi0 = cx + r * hole * Math.cos(a0), yi0 = cy + r * hole * Math.sin(a0);
        const xi1 = cx + r * hole * Math.cos(a1), yi1 = cy + r * hole * Math.sin(a1);
        const large = ang > Math.PI ? 1 : 0;
        const d = `M ${x0} ${y0} A ${r} ${r} 0 ${large} 1 ${x1} ${y1} L ${xi1} ${yi1} A ${r*hole} ${r*hole} 0 ${large} 0 ${xi0} ${yi0} Z`;
        return <path key={i} d={d} fill={colors[i % colors.length]} stroke="var(--paper)" strokeWidth="1.5" />;
      })}
      <text x={cx} y={cy - 4} textAnchor="middle" style={{fontFamily:'var(--sans)', fontWeight:600, fontSize:32, fill:'var(--ink)'}}>{rows[0].share}%</text>
      <text x={cx} y={cy + 16} textAnchor="middle" style={{fontFamily:'var(--mono)', fontSize:10, fill:'var(--ink-3)', letterSpacing:'.08em', textTransform:'uppercase'}}>{rows[0].name}</text>
    </svg>
  );
}

Object.assign(window, {
  Sparkline, HBar, AdoptionRibbon, WorkflowStrands, OverlapMatrix, ScoreRibbon, ToolScatter, UseCaseDonut,
});
