/* global React */
// Reusable SVG viz primitives, props-driven. All inherit Onest via parent.
const { useMemo: vMemo } = React;

function smoothPath(pts) {
  if (pts.length < 2) return "";
  let d = `M ${pts[0][0]} ${pts[0][1]}`;
  for (let i = 0; i < pts.length - 1; i++) {
    const p0 = pts[i - 1] || pts[i], p1 = pts[i], p2 = pts[i + 1], p3 = pts[i + 2] || p2;
    d += ` C ${p1[0] + (p2[0]-p0[0])/6} ${p1[1] + (p2[1]-p0[1])/6} ${p2[0] - (p3[0]-p1[0])/6} ${p2[1] - (p3[1]-p1[1])/6} ${p2[0]} ${p2[1]}`;
  }
  return d;
}

// Multi-series smooth line chart
function LineChart({ series, height = 170, min, max, colors = ["#3a6b22", "#c6cf4a", "#a7ab98"], fill = true, dashed = [], labels }) {
  const W = 520, H = height, padX = 6, padT = 14, padB = labels ? 24 : 10;
  const all = series.flatMap((s) => s.data);
  const lo = min != null ? min : Math.min(...all) * 0.9;
  const hi = max != null ? max : Math.max(...all) * 1.05;
  const X = (i, n) => padX + (i / (n - 1)) * (W - padX * 2);
  const Y = (v) => padT + (1 - (v - lo) / (hi - lo)) * (H - padT - padB);
  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" style={{ display: "block" }}>
      {[0, 1, 2, 3].map((i) => (
        <line key={i} x1="0" x2={W} y1={padT + i * ((H - padT - padB) / 3)} y2={padT + i * ((H - padT - padB) / 3)}
              stroke="#1b1e14" strokeOpacity="0.06" />
      ))}
      {series.map((s, si) => {
        const pts = s.data.map((v, i) => [X(i, s.data.length), Y(v)]);
        const line = smoothPath(pts);
        return (
          <g key={si}>
            {fill && si === 0 && (
              <path d={`${line} L ${pts[pts.length-1][0]} ${H-padB} L ${pts[0][0]} ${H-padB} Z`}
                    fill={colors[si]} opacity="0.12" />
            )}
            <path d={line} fill="none" stroke={colors[si % colors.length]} strokeWidth={si === 0 ? 2.4 : 1.8}
                  strokeLinecap="round" strokeDasharray={dashed.includes(si) ? "5 5" : "none"} opacity={si === 0 ? 1 : 0.8} />
          </g>
        );
      })}
      {labels && labels.map((l, i) => (
        <text key={i} x={X(i, labels.length)} y={H - 6} fontSize="11" fontFamily="Onest"
              fill="#8b9079" textAnchor={i === 0 ? "start" : i === labels.length-1 ? "end" : "middle"}>{l}</text>
      ))}
    </svg>
  );
}

// Tiny area sparkline
function Spark({ data, color = "#3a6b22", width = 96, height = 34 }) {
  const lo = Math.min(...data), hi = Math.max(...data);
  const pts = data.map((v, i) => [i / (data.length - 1) * width, height - 3 - ((v - lo) / (hi - lo || 1)) * (height - 6)]);
  const line = smoothPath(pts);
  return (
    <svg viewBox={`0 0 ${width} ${height}`} width={width} height={height} style={{ display: "block" }}>
      <path d={`${line} L ${width} ${height} L 0 ${height} Z`} fill={color} opacity="0.14" />
      <path d={line} fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round" />
    </svg>
  );
}

// Horizontal bars with labels + values
function BarsH({ rows, max, accent = "#3a6b22", track = "#e2e4d6", suffix = "" }) {
  const hi = max != null ? max : Math.max(...rows.map((r) => r.value));
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
      {rows.map((r) => (
        <div key={r.label}>
          <div style={{ display: "flex", justifyContent: "space-between", fontSize: 13.5, marginBottom: 6 }}>
            <span style={{ color: "var(--ink-2)", fontWeight: 500 }}>{r.label}</span>
            <span style={{ color: "var(--ink)", fontWeight: 700 }}>{r.value}{suffix}</span>
          </div>
          <div style={{ height: 8, borderRadius: 6, background: track, overflow: "hidden" }}>
            <div style={{ height: "100%", width: `${(r.value / hi) * 100}%`, borderRadius: 6,
              background: r.color || accent, transition: "width 0.6s ease" }} />
          </div>
        </div>
      ))}
    </div>
  );
}

// Vertical bar chart
function BarsV({ data, labels, height = 150, accent = "#3a6b22", highlight = -1 }) {
  const hi = Math.max(...data);
  return (
    <div style={{ display: "flex", alignItems: "flex-end", gap: 10, height, padding: "0 2px" }}>
      {data.map((v, i) => (
        <div key={i} style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", gap: 8, height: "100%", justifyContent: "flex-end" }}>
          <div style={{ width: "100%", maxWidth: 34, height: `${(v / hi) * 100}%`, borderRadius: "7px 7px 3px 3px",
            background: i === highlight ? "var(--lime)" : accent, transition: "height 0.6s ease" }} />
          {labels && <span style={{ fontSize: 11, color: "var(--muted)" }}>{labels[i]}</span>}
        </div>
      ))}
    </div>
  );
}

// Semicircular gauge 0-1 or 0-100
function Gauge({ value, max = 1, size = 150, label, sub, color = "#3a6b22" }) {
  const r = size / 2 - 12, cx = size / 2, cy = size / 2 + 4;
  const pct = Math.max(0, Math.min(1, value / max));
  const a = Math.PI * (1 - pct);
  const x2 = cx + r * Math.cos(a), y2 = cy - r * Math.sin(a);
  const large = pct > 0.5 ? 1 : 0;
  return (
    <svg viewBox={`0 0 ${size} ${size * 0.66}`} width="100%" style={{ display: "block", maxWidth: size }}>
      <path d={`M ${cx-r} ${cy} A ${r} ${r} 0 0 1 ${cx+r} ${cy}`} fill="none" stroke="#e2e4d6" strokeWidth="11" strokeLinecap="round" />
      <path d={`M ${cx-r} ${cy} A ${r} ${r} 0 ${large} 1 ${x2} ${y2}`} fill="none" stroke={color} strokeWidth="11" strokeLinecap="round" />
      <text x={cx} y={cy - 4} textAnchor="middle" fontSize="26" fontWeight="800" fontFamily="Onest" fill="var(--ink)">{label}</text>
      {sub && <text x={cx} y={cy + 12} textAnchor="middle" fontSize="11" fontFamily="Onest" fill="var(--muted)">{sub}</text>}
    </svg>
  );
}

// Donut ring with center label
function Donut({ segments, size = 140, thickness = 16, center, sub }) {
  const r = (size - thickness) / 2, c = 2 * Math.PI * r, cx = size / 2;
  let off = 0;
  const total = segments.reduce((s, x) => s + x.value, 0);
  return (
    <svg viewBox={`0 0 ${size} ${size}`} width="100%" style={{ display: "block", maxWidth: size }}>
      <circle cx={cx} cy={cx} r={r} fill="none" stroke="#e2e4d6" strokeWidth={thickness} />
      {segments.map((s, i) => {
        const len = (s.value / total) * c;
        const el = (
          <circle key={i} cx={cx} cy={cx} r={r} fill="none" stroke={s.color} strokeWidth={thickness}
                  strokeDasharray={`${len} ${c - len}`} strokeDashoffset={-off}
                  transform={`rotate(-90 ${cx} ${cx})`} strokeLinecap="butt" />
        );
        off += len;
        return el;
      })}
      {center && <text x={cx} y={cx - 2} textAnchor="middle" fontSize="24" fontWeight="800" fontFamily="Onest" fill="var(--ink)">{center}</text>}
      {sub && <text x={cx} y={cx + 16} textAnchor="middle" fontSize="11" fontFamily="Onest" fill="var(--muted)">{sub}</text>}
    </svg>
  );
}

// Grid heatmap — cells colored by intensity 0-1
function Heatmap({ cells, cols = 3, scale, gap = 6, radius = 9, height = 150, labelKey }) {
  const rows = Math.ceil(cells.length / cols);
  return (
    <div style={{ display: "grid", gridTemplateColumns: `repeat(${cols}, 1fr)`, gridTemplateRows: `repeat(${rows}, 1fr)`, gap, height }}>
      {cells.map((c, i) => (
        <div key={i} style={{ borderRadius: radius, background: scale(c), display: "flex", flexDirection: "column",
          alignItems: "center", justifyContent: "center", color: "#fff", position: "relative" }}>
          {labelKey && <span style={{ fontSize: 12, fontWeight: 700, textShadow: "0 1px 3px rgba(0,0,0,0.3)" }}>{c[labelKey]}</span>}
        </div>
      ))}
    </div>
  );
}

Object.assign(window, { LineChart, Spark, BarsH, BarsV, Gauge, Donut, Heatmap, smoothPath });
