/* Charts: small SVG components — sparkline, ring, bar, multi-line stream */

const SparkLine = ({ data, width = 120, height = 32, color = "var(--accent)", fill = true, dots = false, fluid = false }) => {
  if (!data || data.length < 2) return null;
  const min = Math.min(...data);
  const max = Math.max(...data);
  const range = max - min || 1;
  // Coordinate space stays at `width`; cuando fluid=true el SVG se estira al
  // 100% del contenedor vía CSS (preserveAspectRatio="none"). Eso evita el
  // medio-sparkline en cards que crecen con el viewport.
  const step = width / (data.length - 1);
  const points = data.map((d, i) => [i * step, height - ((d - min) / range) * (height - 4) - 2]);
  const path = points.map((p, i) => `${i === 0 ? "M" : "L"}${p[0].toFixed(1)} ${p[1].toFixed(1)}`).join(" ");
  const area = `${path} L${width} ${height} L0 ${height} Z`;
  const svgProps = fluid
    ? { width: "100%", height, viewBox: `0 0 ${width} ${height}`, preserveAspectRatio: "none", style: { display: "block" } }
    : { width, height, viewBox: `0 0 ${width} ${height}`, style: { overflow: "visible" } };
  return (
    <svg {...svgProps}>
      {fill && <path d={area} fill={color} opacity="0.12" />}
      <path d={path} fill="none" stroke={color} strokeWidth={fluid ? "0.8" : "1.5"} strokeLinejoin="round" strokeLinecap="round" vectorEffect="non-scaling-stroke" />
      {dots && points.map(([x, y], i) => (
        <circle key={i} cx={x} cy={y} r="1.5" fill={color} />
      ))}
    </svg>
  );
};

const Ring = ({ value = 0, max = 100, size = 64, stroke = 6, color = "var(--accent)", track = "var(--line)", label, sublabel }) => {
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const pct = Math.min(1, Math.max(0, value / max));
  return (
    <div style={{ position: "relative", width: size, height: size, display: "inline-block" }}>
      <svg width={size} height={size} style={{ transform: "rotate(-90deg)" }}>
        <circle cx={size/2} cy={size/2} r={r} stroke={track} strokeWidth={stroke} fill="none" />
        <circle cx={size/2} cy={size/2} r={r} stroke={color} strokeWidth={stroke} fill="none"
          strokeDasharray={c} strokeDashoffset={c * (1 - pct)} strokeLinecap="round" />
      </svg>
      {(label || sublabel) && (
        <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", textAlign: "center" }}>
          <div>
            {label && <div className="num" style={{ fontSize: size * 0.28, fontWeight: 500, lineHeight: 1, letterSpacing: "-0.02em" }}>{label}</div>}
            {sublabel && <div style={{ fontSize: 9, color: "var(--text-3)", marginTop: 2, fontFamily: "var(--font-mono)", letterSpacing: 0.05, textTransform: "uppercase" }}>{sublabel}</div>}
          </div>
        </div>
      )}
    </div>
  );
};

const Bars = ({ data, width = 280, height = 60, color = "var(--accent)", labels }) => {
  if (!data) return null;
  const max = Math.max(...data, 1);
  const gap = 3;
  const bw = (width - gap * (data.length - 1)) / data.length;
  return (
    <svg width={width} height={height + 16} viewBox={`0 0 ${width} ${height + 16}`}>
      {data.map((d, i) => {
        const h = (d / max) * height;
        return (
          <g key={i}>
            <rect x={i * (bw + gap)} y={height - h} width={bw} height={h} rx={2} fill={color} opacity={d === 0 ? 0.15 : 1} />
            {labels && (
              <text x={i * (bw + gap) + bw / 2} y={height + 12} textAnchor="middle" style={{ fill: "var(--text-3)", fontFamily: "var(--font-mono)", fontSize: 9 }}>
                {labels[i]}
              </text>
            )}
          </g>
        );
      })}
    </svg>
  );
};

/* Larger time-series area chart with grid */
const AreaChart = ({ data, width = 600, height = 200, color = "var(--accent)", yLabel, xLabels = [], yMin, yMax, secondary }) => {
  if (!data || data.length < 2) return null;
  const padL = 32, padR = 8, padT = 12, padB = 24;
  const w = width - padL - padR;
  const h = height - padT - padB;
  const min = yMin !== undefined ? yMin : Math.min(...data);
  const max = yMax !== undefined ? yMax : Math.max(...data);
  const range = max - min || 1;
  const step = w / (data.length - 1);
  const pts = data.map((d, i) => [padL + i * step, padT + h - ((d - min) / range) * h]);
  const path = pts.map((p, i) => `${i === 0 ? "M" : "L"}${p[0].toFixed(1)} ${p[1].toFixed(1)}`).join(" ");
  const area = `${path} L${padL + w} ${padT + h} L${padL} ${padT + h} Z`;

  const yTicks = 4;
  const ticks = Array.from({ length: yTicks + 1 }, (_, i) => min + (range * i) / yTicks);

  return (
    <svg width="100%" height={height} viewBox={`0 0 ${width} ${height}`} preserveAspectRatio="none" style={{ display: "block" }}>
      {ticks.map((t, i) => {
        const y = padT + h - (i / yTicks) * h;
        return (
          <g key={i}>
            <line x1={padL} x2={padL + w} y1={y} y2={y} stroke="var(--line-soft)" strokeWidth="1" strokeDasharray={i === 0 ? "0" : "2 3"} />
            <text x={padL - 6} y={y + 3} textAnchor="end" style={{ fill: "var(--text-3)", fontFamily: "var(--font-mono)", fontSize: 9 }}>
              {Math.round(t)}
            </text>
          </g>
        );
      })}
      {secondary && (() => {
        const sMin = Math.min(...secondary);
        const sMax = Math.max(...secondary);
        const sR = sMax - sMin || 1;
        const sPts = secondary.map((d, i) => [padL + i * step, padT + h - ((d - sMin) / sR) * h]);
        const sPath = sPts.map((p, i) => `${i === 0 ? "M" : "L"}${p[0].toFixed(1)} ${p[1].toFixed(1)}`).join(" ");
        return <path d={sPath} fill="none" stroke="var(--text-3)" strokeWidth="1" strokeDasharray="3 3" opacity="0.6" />;
      })()}
      <path d={area} fill={color} opacity="0.1" />
      <path d={path} fill="none" stroke={color} strokeWidth="1.6" strokeLinejoin="round" />
      {pts.map(([x, y], i) => (
        <circle key={i} cx={x} cy={y} r="2" fill="var(--bg-1)" stroke={color} strokeWidth="1.4" />
      ))}
      {xLabels.map((l, i) => {
        const idx = Math.floor((i * (data.length - 1)) / (xLabels.length - 1));
        const x = padL + idx * step;
        return (
          <text key={i} x={x} y={height - 6} textAnchor="middle" style={{ fill: "var(--text-3)", fontFamily: "var(--font-mono)", fontSize: 9 }}>
            {l}
          </text>
        );
      })}
    </svg>
  );
};

/* Multi-line stream (HR, pace, elevation).
 *
 * Cada serie acepta `{ data, color, fill?, label?, axis?, format? }`:
 *   - `axis`: "left" | "right" — decide a qué costado va la escala (min/max).
 *   - `format(v)`: opcional — cómo formatear el min/max para esa serie.
 *     (ej. pace negativo se invierte para mostrar pace real).
 *   - `label`: corto, mostrado debajo del valor (ej. "FC", "Pace").
 *
 * Si una serie no declara `axis`, no aparece etiquetada (compat hacia atrás).
 */
const StreamChart = ({ series, width = 800, height = 220, xMax = 100 }) => {
  const padL = 56, padR = 56, padT = 14, padB = 22;
  const w = width - padL - padR;
  const h = height - padT - padB;

  const axisSeries = (side) => series.filter((s) => s.axis === side);
  const fmtNum = (v) => {
    if (v == null || !isFinite(v)) return "—";
    if (Math.abs(v) >= 100) return Math.round(v).toString();
    if (Math.abs(v) >= 10) return v.toFixed(1);
    return v.toFixed(2);
  };

  const renderAxis = (side) => {
    const ss = axisSeries(side);
    if (!ss.length) return null;
    const x = side === "left" ? padL - 8 : padL + w + 8;
    const anchor = side === "left" ? "end" : "start";
    return ss.map((s, idx) => {
      const min = Math.min(...s.data);
      const max = Math.max(...s.data);
      const fmt = s.format || fmtNum;
      // Bloque vertical por serie: max arriba, label, min abajo.
      const blockTop = padT + idx * 30;
      return (
        <g key={`${side}-${idx}`}>
          <text x={x} y={blockTop + 8} textAnchor={anchor}
            style={{ fill: s.color, fontFamily: "var(--font-mono)", fontSize: 10, fontWeight: 600 }}>
            {fmt(max)}
          </text>
          {s.label && (
            <text x={x} y={blockTop + 19} textAnchor={anchor}
              style={{ fill: "var(--text-3)", fontFamily: "var(--font-mono)", fontSize: 8, letterSpacing: "0.06em" }}>
              {s.label}
            </text>
          )}
          <text x={x} y={padT + h - 4} textAnchor={anchor}
            style={{ fill: "var(--text-3)", fontFamily: "var(--font-mono)", fontSize: 9 }}>
            {fmt(min)}
          </text>
        </g>
      );
    });
  };

  return (
    <svg width="100%" height={height} viewBox={`0 0 ${width} ${height}`} style={{ display: "block" }}>
      {[0, 0.25, 0.5, 0.75, 1].map((p, i) => (
        <line key={i} x1={padL} x2={padL+w} y1={padT + p*h} y2={padT + p*h} stroke="var(--line-soft)" strokeWidth="1" strokeDasharray={p === 0 || p === 1 ? "0" : "2 3"} />
      ))}
      {series.map((s, sIdx) => {
        if (!s.data || s.data.length < 2) return null;
        const min = Math.min(...s.data);
        const max = Math.max(...s.data);
        const range = max - min || 1;
        const step = w / (s.data.length - 1);
        const pts = s.data.map((d, i) => [padL + i * step, padT + h - ((d - min) / range) * h]);
        const path = pts.map((p, i) => `${i === 0 ? "M" : "L"}${p[0].toFixed(1)} ${p[1].toFixed(1)}`).join(" ");
        return (
          <g key={sIdx}>
            {s.fill && <path d={`${path} L${padL+w} ${padT+h} L${padL} ${padT+h} Z`} fill={s.color} opacity="0.08" />}
            <path d={path} fill="none" stroke={s.color} strokeWidth="1.4" />
          </g>
        );
      })}
      {renderAxis("left")}
      {renderAxis("right")}
      {/* X axis km labels */}
      {[0, 0.25, 0.5, 0.75, 1].map((p, i) => (
        <text key={i} x={padL + p*w} y={height - 6} textAnchor="middle" style={{ fill: "var(--text-3)", fontFamily: "var(--font-mono)", fontSize: 9 }}>
          {(p * xMax).toFixed(1)}{p===1?" km":""}
        </text>
      ))}
    </svg>
  );
};

/* Heatmap-ish weekly grid */
const WeekGrid = ({ data, max, color = "var(--accent)", labels = ["L","M","X","J","V","S","D"] }) => {
  return (
    <div style={{ display: "grid", gridTemplateColumns: "repeat(7, 1fr)", gap: 4 }}>
      {data.map((d, i) => {
        const o = Math.max(0.08, d / max);
        return (
          <div key={i} style={{ aspectRatio: "1", display: "flex", flexDirection: "column", alignItems: "center", gap: 2 }}>
            <div style={{ fontSize: 9, color: "var(--text-3)", fontFamily: "var(--font-mono)" }}>{labels[i]}</div>
            <div style={{
              flex: 1, width: "100%", borderRadius: 3,
              background: d === 0 ? "var(--line-soft)" : color,
              opacity: d === 0 ? 1 : o,
            }} />
            <div style={{ fontSize: 9, color: "var(--text-3)", fontFamily: "var(--font-mono)" }}>{d}</div>
          </div>
        );
      })}
    </div>
  );
};

Object.assign(window, { SparkLine, Ring, Bars, AreaChart, StreamChart, WeekGrid });
