/* ============================================================
   FINAZ — Kit de gráficos SVG reutilizables
   Todos aceptan props de tema (colores/tipos) para adaptarse a
   cada estilo. Sin librerías externas.
   ============================================================ */
const { useState: useStateC, useMemo } = React;

/* -- helpers -- */
function minMax(arr) {
  let lo = Infinity, hi = -Infinity;
  for (const v of arr) { if (v < lo) lo = v; if (v > hi) hi = v; }
  return [lo, hi];
}
function fmt(n, d = 2) {
  return n.toLocaleString("es-ES", { minimumFractionDigits: d, maximumFractionDigits: d });
}
function pctStr(n) { return (n >= 0 ? "+" : "") + fmt(n, 2) + "%"; }

/* ---- Línea intradía con relleno de área y anotaciones ---- */
function LineChart({ data, labels = [], w = 640, h = 240, color = "#e8b339", grid = "#222", text = "#888",
                     fill = true, baseline = null, annotations = [], strokeW = 2.5, dot = true, pad = 28, pulseIndex = null }) {
  const [lo, hi] = minMax(baseline != null ? [...data, baseline] : data);
  const range = (hi - lo) || 1;
  const padTop = 16, padBot = 24, padL = pad, padR = pad;
  const iw = w - padL - padR, ih = h - padTop - padBot;
  const x = i => padL + (i / (data.length - 1)) * iw;
  const y = v => padTop + ih - ((v - lo) / range) * ih;
  const pts = data.map((v, i) => `${x(i)},${y(v)}`).join(" ");
  const areaPts = `${padL},${padTop + ih} ${pts} ${padL + iw},${padTop + ih}`;
  const gid = "lg" + Math.random().toString(36).slice(2, 7);
  return (
    <svg viewBox={`0 0 ${w} ${h}`} width="100%" style={{ display: "block" }}>
      <defs>
        <linearGradient id={gid} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={color} stopOpacity="0.28" />
          <stop offset="100%" stopColor={color} stopOpacity="0" />
        </linearGradient>
      </defs>
      {[0, 0.25, 0.5, 0.75, 1].map((g, i) => (
        <line key={i} x1={padL} x2={padL + iw} y1={padTop + ih * g} y2={padTop + ih * g} stroke={grid} strokeWidth="1" />
      ))}
      {baseline != null && (
        <line x1={padL} x2={padL + iw} y1={y(baseline)} y2={y(baseline)} stroke={text} strokeWidth="1" strokeDasharray="4 4" opacity="0.6" />
      )}
      {fill && <polygon points={areaPts} fill={`url(#${gid})`} />}
      <polyline points={pts} fill="none" stroke={color} strokeWidth={strokeW} strokeLinejoin="round" strokeLinecap="round" />
      {dot && <circle cx={x(data.length - 1)} cy={y(data[data.length - 1])} r="4" fill={color} />}
      {pulseIndex != null && data[pulseIndex] != null && (
        <g>
          <circle cx={x(pulseIndex)} cy={y(data[pulseIndex])} r="11" fill={color} opacity="0.18">
            <animate attributeName="r" values="7;15;7" dur="1.4s" repeatCount="indefinite" />
            <animate attributeName="opacity" values="0.3;0.05;0.3" dur="1.4s" repeatCount="indefinite" />
          </circle>
          <circle cx={x(pulseIndex)} cy={y(data[pulseIndex])} r="5" fill={color} stroke="#fff" strokeWidth="1.5" />
        </g>
      )}
      {annotations.map((a, i) => (
        <g key={i}>
          <line x1={x(a.i)} x2={x(a.i)} y1={padTop} y2={padTop + ih} stroke={text} strokeWidth="1" strokeDasharray="2 3" opacity="0.5" />
          <circle cx={x(a.i)} cy={y(data[a.i])} r="4.5" fill="none" stroke={color} strokeWidth="2" />
          <text x={x(a.i)} y={padTop - 4} fontSize="10.5" fill={text} textAnchor={a.i > data.length / 2 ? "end" : "start"}
                style={{ fontFamily: "inherit", fontWeight: 600 }}>{a.t}</text>
        </g>
      ))}
      {labels.length > 0 && [0, Math.floor((labels.length - 1) / 2), labels.length - 1].map((li, k) => (
        <text key={k} x={x(li)} y={h - 6} fontSize="10" fill={text} textAnchor={k === 0 ? "start" : k === 2 ? "end" : "middle"}
              style={{ fontFamily: "inherit" }}>{labels[li]}</text>
      ))}
    </svg>
  );
}

/* ---- Velas japonesas ---- */
function Candles({ data, w = 640, h = 260, up = "#3fb950", down = "#f85149", grid = "#1b232c", text = "#7d8590", level = null, levelColor = "#e8b339" }) {
  const highs = data.map(d => d[2]), lows = data.map(d => d[3]);
  let lo = Math.min(...lows), hi = Math.max(...highs);
  if (level != null) { lo = Math.min(lo, level); hi = Math.max(hi, level); }
  const range = (hi - lo) || 1;
  const padT = 12, padB = 22, padL = 8, padR = 52;
  const iw = w - padL - padR, ih = h - padT - padB;
  const slot = iw / data.length;
  const cw = Math.min(slot * 0.58, 18);
  const y = v => padT + ih - ((v - lo) / range) * ih;
  return (
    <svg viewBox={`0 0 ${w} ${h}`} width="100%" style={{ display: "block" }}>
      {[0, 0.25, 0.5, 0.75, 1].map((g, i) => {
        const yy = padT + ih * g; const val = hi - g * range;
        return (<g key={i}>
          <line x1={padL} x2={padL + iw} y1={yy} y2={yy} stroke={grid} strokeWidth="1" />
          <text x={w - padR + 6} y={yy + 3} fontSize="9.5" fill={text} style={{ fontFamily: "inherit" }}>{Math.round(val)}</text>
        </g>);
      })}
      {level != null && (
        <g>
          <line x1={padL} x2={padL + iw} y1={y(level)} y2={y(level)} stroke={levelColor} strokeWidth="1.2" strokeDasharray="5 4" />
          <text x={w - padR + 6} y={y(level) - 3} fontSize="9.5" fill={levelColor} style={{ fontFamily: "inherit", fontWeight: 700 }}>{level}</text>
        </g>
      )}
      {data.map((d, i) => {
        const [, o, hT, lT, c] = d;
        const cx = padL + slot * i + slot / 2;
        const col = c >= o ? up : down;
        const bodyTop = y(Math.max(o, c)), bodyBot = y(Math.min(o, c));
        return (<g key={i}>
          <line x1={cx} x2={cx} y1={y(hT)} y2={y(lT)} stroke={col} strokeWidth="1.4" />
          <rect x={cx - cw / 2} y={bodyTop} width={cw} height={Math.max(1.5, bodyBot - bodyTop)} fill={col} rx="1" />
        </g>);
      })}
      {data.map((d, i) => i % 2 === 0 && (
        <text key={"x" + i} x={padL + slot * i + slot / 2} y={h - 6} fontSize="9" fill={text} textAnchor="middle" style={{ fontFamily: "inherit" }}>{d[0]}</text>
      ))}
    </svg>
  );
}

/* ---- Barras horizontales divergentes (movers) ---- */
function DivBars({ data, w = 640, rowH = 30, up = "#3fb950", down = "#f85149", text = "#c9d1d9", muted = "#7d8590",
                   labelKey = "nombre", valKey = "pct", maxAbs = null, showVal = true, labelW = 130 }) {
  const M = maxAbs || Math.max(...data.map(d => Math.abs(d[valKey]))) * 1.05;
  const h = data.length * rowH + 6;
  const cx = labelW + (w - labelW - 56) / 2 + 8;
  const half = (w - labelW - 56) / 2;
  return (
    <svg viewBox={`0 0 ${w} ${h}`} width="100%" style={{ display: "block" }}>
      <line x1={cx} x2={cx} y1={4} y2={h - 4} stroke={muted} strokeWidth="1" opacity="0.4" />
      {data.map((d, i) => {
        const v = d[valKey]; const yy = i * rowH + 6;
        const bw = (Math.abs(v) / M) * half;
        const col = v >= 0 ? up : down;
        return (<g key={i}>
          <text x={labelW - 8} y={yy + rowH / 2 + 3} fontSize="12" fill={text} textAnchor="end" style={{ fontFamily: "inherit", fontWeight: 500 }}>{d[labelKey]}</text>
          <rect x={v >= 0 ? cx : cx - bw} y={yy + 5} width={Math.max(1, bw)} height={rowH - 12} fill={col} rx="2" opacity="0.92" />
          {showVal && <text x={v >= 0 ? cx + bw + 6 : cx - bw - 6} y={yy + rowH / 2 + 3} fontSize="11.5" fill={col} textAnchor={v >= 0 ? "start" : "end"} style={{ fontFamily: "inherit", fontWeight: 700 }}>{pctStr(v)}</text>}
        </g>);
      })}
    </svg>
  );
}

/* ---- Barras verticales simples ---- */
function VBars({ data, w = 420, h = 200, up = "#3fb950", down = "#f85149", text = "#888", labelKey = "n", valKey = "pct", pad = 30 }) {
  const M = Math.max(...data.map(d => Math.abs(d[valKey]))) * 1.15 || 1;
  const iw = w - pad * 2, ih = h - 40;
  const slot = iw / data.length; const bw = slot * 0.5;
  const zeroY = 16 + ih / 2;
  const scale = (ih / 2) / M;
  return (
    <svg viewBox={`0 0 ${w} ${h}`} width="100%" style={{ display: "block" }}>
      <line x1={pad} x2={w - pad} y1={zeroY} y2={zeroY} stroke={text} strokeWidth="1" opacity="0.4" />
      {data.map((d, i) => {
        const v = d[valKey]; const cx = pad + slot * i + slot / 2;
        const bh = Math.abs(v) * scale; const col = v >= 0 ? up : down;
        return (<g key={i}>
          <rect x={cx - bw / 2} y={v >= 0 ? zeroY - bh : zeroY} width={bw} height={Math.max(1, bh)} fill={col} rx="2" />
          <text x={cx} y={v >= 0 ? zeroY - bh - 5 : zeroY + bh + 13} fontSize="10.5" fill={col} textAnchor="middle" style={{ fontFamily: "inherit", fontWeight: 700 }}>{pctStr(v)}</text>
          <text x={cx} y={h - 6} fontSize="10" fill={text} textAnchor="middle" style={{ fontFamily: "inherit" }}>{d[labelKey]}</text>
        </g>);
      })}
    </svg>
  );
}

/* ---- Curva de tipos ---- */
function YieldCurve({ data, w = 480, h = 220, color = "#5aa9ff", grid = "#222", text = "#888", area = true }) {
  const vals = data.map(d => d.v);
  const lo = Math.min(...vals) - 0.15, hi = Math.max(...vals) + 0.15;
  const range = hi - lo;
  const padT = 16, padB = 26, padL = 36, padR = 14;
  const iw = w - padL - padR, ih = h - padT - padB;
  const x = i => padL + (i / (data.length - 1)) * iw;
  const y = v => padT + ih - ((v - lo) / range) * ih;
  const pts = data.map((d, i) => `${x(i)},${y(d.v)}`).join(" ");
  const gid = "yc" + Math.random().toString(36).slice(2, 7);
  return (
    <svg viewBox={`0 0 ${w} ${h}`} width="100%" style={{ display: "block" }}>
      <defs><linearGradient id={gid} x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stopColor={color} stopOpacity="0.25" /><stop offset="100%" stopColor={color} stopOpacity="0" />
      </linearGradient></defs>
      {[0, 0.5, 1].map((g, i) => (
        <g key={i}><line x1={padL} x2={padL + iw} y1={padT + ih * g} y2={padT + ih * g} stroke={grid} strokeWidth="1" />
        <text x={padL - 6} y={padT + ih * g + 3} fontSize="9.5" fill={text} textAnchor="end" style={{ fontFamily: "inherit" }}>{fmt(hi - g * range, 1)}</text></g>
      ))}
      {area && <polygon points={`${padL},${padT + ih} ${pts} ${padL + iw},${padT + ih}`} fill={`url(#${gid})`} />}
      <polyline points={pts} fill="none" stroke={color} strokeWidth="2.5" strokeLinejoin="round" />
      {data.map((d, i) => (<g key={i}>
        <circle cx={x(i)} cy={y(d.v)} r="3.5" fill={color} />
        <text x={x(i)} y={h - 7} fontSize="9.5" fill={text} textAnchor="middle" style={{ fontFamily: "inherit" }}>{d.plazo}</text>
      </g>))}
    </svg>
  );
}

/* ---- Heatmap sectorial ---- */
function SectorHeat({ data, up = "#2ea043", down = "#da3633", text = "#c9d1d9", neutral = "#6e7681", cols = 3, showRazon = false }) {
  const cellColor = (pct) => {
    const a = Math.min(Math.abs(pct) / 3, 1);
    if (Math.abs(pct) < 0.2) return `rgba(110,118,129,0.25)`;
    const c = pct >= 0 ? up : down;
    return c + Math.round(40 + a * 130).toString(16).padStart(2, "0");
  };
  return (
    <div style={{ display: "grid", gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: 6 }}>
      {data.map((s, i) => (
        <div key={i} style={{ background: cellColor(s.pct), borderRadius: 8, padding: "12px 13px", border: "1px solid rgba(255,255,255,0.05)" }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
            <span style={{ fontSize: 13, fontWeight: 600, color: text }}>{s.n}</span>
            <span style={{ fontSize: 13, fontWeight: 800, color: text }}>{pctStr(s.pct)}</span>
          </div>
          {showRazon && <div style={{ fontSize: 11, color: text, opacity: 0.78, marginTop: 5, lineHeight: 1.35 }}>{s.razon}</div>}
        </div>
      ))}
    </div>
  );
}

/* ---- Donut / gauge ---- */
function Donut({ value, max = 100, w = 160, color = "#5aa9ff", track = "#222", text = "#c9d1d9", label = "", sub = "", thickness = 14 }) {
  const r = (w - thickness) / 2 - 4; const cx = w / 2, cy = w / 2;
  const circ = 2 * Math.PI * r; const frac = Math.min(value / max, 1);
  return (
    <svg viewBox={`0 0 ${w} ${w}`} width={w} style={{ display: "block" }}>
      <circle cx={cx} cy={cy} r={r} fill="none" stroke={track} strokeWidth={thickness} />
      <circle cx={cx} cy={cy} r={r} fill="none" stroke={color} strokeWidth={thickness} strokeLinecap="round"
              strokeDasharray={`${circ * frac} ${circ}`} transform={`rotate(-90 ${cx} ${cy})`} />
      <text x={cx} y={cy - 2} fontSize={w * 0.2} fontWeight="800" fill={text} textAnchor="middle" style={{ fontFamily: "inherit" }}>{label}</text>
      {sub && <text x={cx} y={cy + w * 0.13} fontSize={w * 0.078} fill={text} opacity="0.7" textAnchor="middle" style={{ fontFamily: "inherit" }}>{sub}</text>}
    </svg>
  );
}

/* ---- Sparkline ---- */
function Spark({ data, w = 90, h = 28, color = "#3fb950", strokeW = 1.6 }) {
  const [lo, hi] = minMax(data); const range = (hi - lo) || 1;
  const x = i => (i / (data.length - 1)) * (w - 2) + 1;
  const y = v => h - 2 - ((v - lo) / range) * (h - 4);
  const pts = data.map((v, i) => `${x(i)},${y(v)}`).join(" ");
  return (<svg viewBox={`0 0 ${w} ${h}`} width={w} height={h} style={{ display: "block" }}>
    <polyline points={pts} fill="none" stroke={color} strokeWidth={strokeW} strokeLinejoin="round" strokeLinecap="round" />
  </svg>);
}

/* ---- Flecha grande arriba/abajo (novato) ---- */
function BigArrow({ down = true, color = "#e0533d", size = 64 }) {
  return (
    <svg viewBox="0 0 64 64" width={size} height={size} style={{ display: "block" }}>
      <g transform={down ? "" : "rotate(180 32 32)"}>
        <path d="M32 8 L32 44 M32 48 L18 32 M32 48 L46 32" fill="none" stroke={color} strokeWidth="6" strokeLinecap="round" strokeLinejoin="round" />
      </g>
    </svg>
  );
}

Object.assign(window, { LineChart, Candles, DivBars, VBars, YieldCurve, SectorHeat, Donut, Spark, BigArrow, fmtNum: fmt, pctStr });
