/* ════════════════════════════════════════════════════════════
   Data viz — interactive equity curve + donut allocation
   ════════════════════════════════════════════════════════════ */

const { useState: vS, useRef: vR, useMemo: vM } = React;

function sparkPathV(points, w, h, pad = 4) {
  const min = Math.min(...points);
  const max = Math.max(...points);
  const range = max - min || 1;
  return points.map((v, i) => {
    const x = pad + (i / (points.length - 1)) * (w - pad * 2);
    const y = pad + (1 - (v - min) / range) * (h - pad * 2);
    return (i === 0 ? 'M' : 'L') + x.toFixed(1) + ',' + y.toFixed(1);
  }).join(' ');
}

function InteractiveCurve({ points, color, base, currency = '¥' }) {
  const W = 320, H = 140, PAD = 6;
  const svgRef = vR(null);
  const [hover, setHover] = vS(null);
  const min = vM(() => Math.min(...points), [points]);
  const max = vM(() => Math.max(...points), [points]);
  const range = max - min || 1;

  const xAt = (i) => PAD + (i / (points.length - 1)) * (W - PAD * 2);
  const yAt = (v) => PAD + (1 - (v - min) / range) * (H - PAD * 2);

  const onMove = (e) => {
    const svg = svgRef.current;
    if (!svg) return;
    const rect = svg.getBoundingClientRect();
    const px = (e.clientX - rect.left) / rect.width * W;
    const idx = Math.round(((px - PAD) / (W - PAD * 2)) * (points.length - 1));
    const clamped = Math.max(0, Math.min(points.length - 1, idx));
    setHover({ idx: clamped, x: xAt(clamped), y: yAt(points[clamped]), v: points[clamped] });
  };
  const onLeave = () => setHover(null);

  const lang = window.__LANG || 'zh';
  const dayLabel = (i) => {
    const daysAgo = points.length - 1 - i;
    if (daysAgo === 0) return lang === 'zh' ? '今日' : 'today';
    return lang === 'zh' ? `${daysAgo} 天前` : `${daysAgo}d ago`;
  };

  const isUp = points[points.length-1] >= (base ?? points[0]);
  const stroke = color || (isUp ? 'var(--up)' : 'var(--down)');
  const path = sparkPathV(points, W, H, PAD);

  return (
    <div style={{ position: 'relative' }}>
      <svg ref={svgRef} width="100%" height={H} viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none"
           onMouseMove={onMove} onMouseLeave={onLeave} onTouchMove={(e) => onMove(e.touches[0])} onTouchEnd={onLeave}
           style={{ cursor: 'crosshair', display: 'block' }}>
        <defs>
          <linearGradient id="ic-fill" x1="0" x2="0" y1="0" y2="1">
            <stop offset="0%"   stopColor={stroke} stopOpacity="0.28"/>
            <stop offset="100%" stopColor={stroke} stopOpacity="0"/>
          </linearGradient>
          <pattern id="ic-grid" width="32" height="35" patternUnits="userSpaceOnUse">
            <path d="M 32 0 L 0 0 0 35" fill="none" stroke="var(--border)" strokeWidth="0.4" opacity="0.4"/>
          </pattern>
        </defs>
        <rect x="0" y="0" width={W} height={H} fill="url(#ic-grid)" opacity="0.5"/>
        {/* base line */}
        {base != null && (
          <line x1={PAD} x2={W-PAD} y1={yAt(base)} y2={yAt(base)}
                stroke="var(--text-3)" strokeWidth="0.5" strokeDasharray="2 3" opacity="0.6"/>
        )}
        <path d={path + ` L ${W-PAD} ${H-PAD} L ${PAD} ${H-PAD} Z`} fill="url(#ic-fill)"/>
        <path d={path} fill="none" stroke={stroke} strokeWidth="1.6" strokeLinejoin="round" strokeLinecap="round"/>
        {/* hover crosshair */}
        {hover && (
          <g>
            <line x1={hover.x} x2={hover.x} y1={PAD} y2={H-PAD}
                  stroke="var(--text-1)" strokeWidth="0.6" strokeDasharray="2 2" opacity="0.5"/>
            <circle cx={hover.x} cy={hover.y} r="3" fill="var(--bg-1)" stroke={stroke} strokeWidth="1.5"/>
            <circle cx={hover.x} cy={hover.y} r="6" fill={stroke} opacity="0.18"/>
          </g>
        )}
      </svg>
      {hover && (
        <div className="curve-tip" style={{
          left: `${(hover.x / W) * 100}%`,
          transform: hover.x > W * 0.65 ? 'translate(-100%, 0)' : 'translate(0, 0)',
        }}>
          <div className="ct-date">{dayLabel(hover.idx)}</div>
          <div className="ct-val">{currency}{Math.round(hover.v).toLocaleString()}</div>
          {base != null && (() => {
            const delta = ((hover.v / base) - 1) * 100;
            return (
              <div className={'ct-pct ' + (delta >= 0 ? 'up' : 'down')}>
                {delta >= 0 ? '+' : ''}{delta.toFixed(2)}%
              </div>
            );
          })()}
        </div>
      )}
    </div>
  );
}

function DonutAllocation({ segments, currency = '¥' }) {
  const [hoverIdx, setHoverIdx] = vS(null);
  const total = segments.reduce((s, x) => s + x.v, 0);
  const C = 2 * Math.PI * 38;
  let acc = 0;
  return (
    <div className="donut-wrap">
      <div className="donut-svg-wrap">
        <svg width="120" height="120" viewBox="0 0 120 120" style={{ overflow: 'visible' }}>
          <circle cx="60" cy="60" r="38" fill="none" stroke="var(--bg-3)" strokeWidth="12"/>
          {segments.map((s, i) => {
            const frac = s.v / total;
            const len = C * frac;
            const isHover = hoverIdx === i;
            const node = (
              <circle key={i}
                      cx="60" cy="60" r="38" fill="none"
                      stroke={s.c} strokeWidth={isHover ? 16 : 12}
                      strokeDasharray={`${len - 1.5} ${C}`} strokeDashoffset={-acc}
                      transform="rotate(-90 60 60)"
                      style={{ cursor: 'pointer', transition: 'stroke-width 0.16s var(--ease-out)' }}
                      onMouseEnter={() => setHoverIdx(i)}
                      onMouseLeave={() => setHoverIdx(null)}/>
            );
            acc += len;
            return node;
          })}
        </svg>
        <div className="donut-center">
          {hoverIdx == null ? (
            <>
              <div className="dc-lab">{(window.__LANG||'zh')==='zh' ? '配置' : 'TOTAL'}</div>
              <div className="dc-val">{currency}{total.toLocaleString()}</div>
              <div className="dc-sub">{segments.length} {(window.__LANG||'zh')==='zh' ? '市场' : 'markets'}</div>
            </>
          ) : (
            <>
              <div className="dc-lab" style={{ color: segments[hoverIdx].c }}>{segments[hoverIdx].lab}</div>
              <div className="dc-val">{((segments[hoverIdx].v / total) * 100).toFixed(0)}%</div>
              <div className="dc-sub">{currency}{segments[hoverIdx].v.toLocaleString()}</div>
            </>
          )}
        </div>
      </div>
      <div className="donut-legend">
        {segments.map((s, i) => {
          const pct = ((s.v / total) * 100).toFixed(0);
          const isHover = hoverIdx === i;
          return (
            <div key={i}
                 className={'dl-row' + (isHover ? ' hot' : '')}
                 onMouseEnter={() => setHoverIdx(i)}
                 onMouseLeave={() => setHoverIdx(null)}>
              <span className="dl-sw" style={{ background: s.c }}/>
              <span className="dl-lab">{s.lab}</span>
              <span className="dl-pct">{pct}%</span>
              <span className="dl-bar"><span className="fill" style={{ width: pct + '%', background: s.c }}/></span>
            </div>
          );
        })}
      </div>
    </div>
  );
}

window.InteractiveCurve = InteractiveCurve;
window.DonutAllocation = DonutAllocation;
