// Shared SVG chart primitives — equity curve, sparkline, rolling sharpe,
// allocation donut. No deps; pure SVG. Accept theme colors via props.

window.ApexCharts = (function () {
  const { useMemo, useState, useRef, useEffect } = React;

  function pathFromPoints(pts, w, h, pad = 0) {
    if (!pts || !pts.length) return '';
    const xs = pts.map(p => p.i);
    const ys = pts.map(p => p.v);
    const xmin = Math.min(...xs), xmax = Math.max(...xs);
    const ymin = Math.min(...ys), ymax = Math.max(...ys);
    const sx = (x) => pad + ((x - xmin) / Math.max(1e-6, xmax - xmin)) * (w - pad * 2);
    const sy = (y) => (h - pad) - ((y - ymin) / Math.max(1e-6, ymax - ymin)) * (h - pad * 2);
    let d = `M ${sx(pts[0].i).toFixed(2)} ${sy(pts[0].v).toFixed(2)}`;
    for (let k = 1; k < pts.length; k++) {
      d += ` L ${sx(pts[k].i).toFixed(2)} ${sy(pts[k].v).toFixed(2)}`;
    }
    return { d, sx, sy, xmin, xmax, ymin, ymax };
  }

  // Equity curve with optional area fill, grid, hover tooltip.
  function EquityCurve({ data, width = 800, height = 280, color = '#00D4C8', fill = 'rgba(0,212,200,0.08)', grid = 'rgba(255,255,255,0.04)', axis = 'rgba(255,255,255,0.35)', label = 'Equity', mono = 'ui-monospace, SFMono-Regular, Menlo, monospace', showAxis = true }) {
    const svgRef = useRef(null);
    const [hover, setHover] = useState(null);

    const built = useMemo(() => pathFromPoints(data, width, height, 16), [data, width, height]);
    if (!built) return null;
    const { d, sx, sy, xmin, xmax, ymin, ymax } = built;

    const areaD = d + ` L ${sx(xmax).toFixed(2)} ${height - 16} L ${sx(xmin).toFixed(2)} ${height - 16} Z`;

    // Y gridlines (5)
    const ticks = 4;
    const gridlines = [];
    for (let k = 0; k <= ticks; k++) {
      const y = 16 + ((height - 32) * k) / ticks;
      gridlines.push(y);
    }

    function handleMove(e) {
      const rect = svgRef.current.getBoundingClientRect();
      const x = ((e.clientX - rect.left) / rect.width) * width;
      // find nearest point
      let best = 0, bestDist = Infinity;
      for (let k = 0; k < data.length; k++) {
        const px = sx(data[k].i);
        const dx = Math.abs(px - x);
        if (dx < bestDist) { bestDist = dx; best = k; }
      }
      const p = data[best];
      setHover({ x: sx(p.i), y: sy(p.v), v: p.v, i: p.i });
    }

    const pctChange = ((data[data.length - 1].v / data[0].v) - 1) * 100;

    return (
      <svg ref={svgRef} viewBox={`0 0 ${width} ${height}`} width="100%" height={height} style={{ display: 'block', overflow: 'visible' }}
        onMouseMove={handleMove} onMouseLeave={() => setHover(null)}>
        <defs>
          <linearGradient id={`eq-fill-${color.replace('#','')}`} x1="0" x2="0" y1="0" y2="1">
            <stop offset="0%" stopColor={color} stopOpacity="0.25" />
            <stop offset="100%" stopColor={color} stopOpacity="0" />
          </linearGradient>
        </defs>
        {gridlines.map((y, k) => (
          <line key={k} x1="0" x2={width} y1={y} y2={y} stroke={grid} strokeWidth="1" />
        ))}
        <path d={areaD} fill={`url(#eq-fill-${color.replace('#','')})`} />
        <path d={d} fill="none" stroke={color} strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="round" />

        {showAxis && (
          <>
            <text x={6} y={20} fill={axis} fontSize="10" fontFamily={mono}>{ymax.toFixed(1)}</text>
            <text x={6} y={height - 6} fill={axis} fontSize="10" fontFamily={mono}>{ymin.toFixed(1)}</text>
          </>
        )}

        {hover && (
          <g pointerEvents="none">
            <line x1={hover.x} x2={hover.x} y1="0" y2={height} stroke={color} strokeOpacity="0.35" strokeDasharray="3 3" />
            <circle cx={hover.x} cy={hover.y} r="3.5" fill={color} stroke="#0A0B0D" strokeWidth="1.5" />
            <g transform={`translate(${Math.min(width - 120, Math.max(8, hover.x + 10))}, ${Math.max(8, hover.y - 36)})`}>
              <rect width="112" height="34" rx="4" fill="#0A0B0D" stroke="rgba(255,255,255,0.12)" />
              <text x="8" y="14" fill="rgba(255,255,255,0.55)" fontSize="9" fontFamily={mono}>D+{hover.i}</text>
              <text x="8" y="27" fill="#fff" fontSize="11" fontFamily={mono}>{hover.v.toFixed(2)}  ({((hover.v/100-1)*100).toFixed(2)}%)</text>
            </g>
          </g>
        )}
      </svg>
    );
  }

  function Sparkline({ data, width = 120, height = 32, color = '#00C389', strokeW = 1.2 }) {
    const built = useMemo(() => pathFromPoints(data, width, height, 2), [data, width, height]);
    if (!built) return null;
    const up = data[data.length - 1].v >= data[0].v;
    const stroke = color || (up ? '#00C389' : '#E5484D');
    return (
      <svg viewBox={`0 0 ${width} ${height}`} width={width} height={height} style={{ display: 'block' }}>
        <path d={built.d} fill="none" stroke={stroke} strokeWidth={strokeW} strokeLinejoin="round" strokeLinecap="round" />
      </svg>
    );
  }

  function RollingSharpe({ data, width = 420, height = 120, color = '#00D4C8', grid = 'rgba(255,255,255,0.05)', mono = 'ui-monospace, SFMono-Regular, Menlo, monospace' }) {
    const built = useMemo(() => pathFromPoints(data, width, height, 10), [data, width, height]);
    if (!built) return null;
    const lastVal = data[data.length - 1].v;
    // Horizontal reference lines at 1.0, 2.0
    const refY1 = built.sy(1.0), refY2 = built.sy(2.0);
    return (
      <svg viewBox={`0 0 ${width} ${height}`} width="100%" height={height} style={{ display: 'block' }}>
        <line x1="0" x2={width} y1={refY2} y2={refY2} stroke={grid} strokeDasharray="2 3" />
        <line x1="0" x2={width} y1={refY1} y2={refY1} stroke={grid} strokeDasharray="2 3" />
        <path d={built.d} fill="none" stroke={color} strokeWidth="1.4" />
        <text x={width - 4} y={refY2 - 3} fill="rgba(255,255,255,0.35)" fontSize="9" fontFamily={mono} textAnchor="end">2.0</text>
        <text x={width - 4} y={refY1 - 3} fill="rgba(255,255,255,0.35)" fontSize="9" fontFamily={mono} textAnchor="end">1.0</text>
        <circle cx={built.sx(data[data.length - 1].i)} cy={built.sy(lastVal)} r="2.5" fill={color} />
      </svg>
    );
  }

  // Allocation donut
  function AllocationDonut({ segments, size = 180, stroke = 22, colors = ['#00D4C8','#3B82F6','#A78BFA','#F59E0B','#EC4899','#22C55E','#EAB308','#06B6D4','#F97316','#84CC16'], bg = 'rgba(255,255,255,0.05)' }) {
    const total = segments.reduce((s, x) => s + x.v, 0);
    const r = (size - stroke) / 2;
    const cx = size / 2, cy = size / 2;
    const C = 2 * Math.PI * r;
    let acc = 0;
    return (
      <svg viewBox={`0 0 ${size} ${size}`} width={size} height={size} style={{ display: 'block' }}>
        <circle cx={cx} cy={cy} r={r} fill="none" stroke={bg} strokeWidth={stroke} />
        {segments.map((seg, i) => {
          const frac = seg.v / total;
          const len = C * frac;
          const offset = C * (acc / total);
          acc += seg.v;
          return (
            <circle key={i} cx={cx} cy={cy} r={r} fill="none"
              stroke={colors[i % colors.length]} strokeWidth={stroke}
              strokeDasharray={`${len.toFixed(2)} ${(C - len).toFixed(2)}`}
              strokeDashoffset={-offset}
              transform={`rotate(-90 ${cx} ${cy})`} />
          );
        })}
      </svg>
    );
  }

  return { EquityCurve, Sparkline, RollingSharpe, AllocationDonut, pathFromPoints };
})();
