// Custom SVG charts. No libs. Crisp, minimal, themable via CSS vars.

const { useEffect, useRef, useState, useMemo, useId } = React;

function pathFromSeries(series, w, h, padX = 0, padY = 4) {
  const min = Math.min(...series), max = Math.max(...series);
  const range = max - min || 1;
  const step = (w - padX * 2) / (series.length - 1);
  return series.map((v, i) => {
    const x = padX + i * step;
    const y = h - padY - ((v - min) / range) * (h - padY * 2);
    return `${i === 0 ? "M" : "L"} ${x.toFixed(2)} ${y.toFixed(2)}`;
  }).join(" ");
}

function areaPathFromSeries(series, w, h, padX = 0, padY = 4) {
  const linePath = pathFromSeries(series, w, h, padX, padY);
  return `${linePath} L ${w-padX} ${h} L ${padX} ${h} Z`;
}

const Sparkline = ({ data, color = "var(--accent)", height = 36, fill = true, strokeWidth = 1.25 }) => {
  const ref = useRef(null);
  const [w, setW] = useState(120);
  useEffect(() => {
    if (!ref.current) return;
    const ro = new ResizeObserver(([e]) => setW(e.contentRect.width));
    ro.observe(ref.current);
    return () => ro.disconnect();
  }, []);
  const id = useId().replace(/:/g, "");
  return (
    <div ref={ref} style={{ width: "100%", height }}>
      <svg width={w} height={height} className="spark">
        <defs>
          <linearGradient id={"g"+id} x1="0" y1="0" x2="0" y2="1">
            <stop offset="0" stopColor={color} stopOpacity="0.18"/>
            <stop offset="1" stopColor={color} stopOpacity="0"/>
          </linearGradient>
        </defs>
        {fill && <path d={areaPathFromSeries(data, w, height)} fill={"url(#g"+id+")"}/>}
        <path d={pathFromSeries(data, w, height)} fill="none" stroke={color} strokeWidth={strokeWidth} strokeLinejoin="round" strokeLinecap="round"/>
      </svg>
    </div>
  );
};

// Larger area chart for hero
const AreaChart = ({ data, height = 220, color = "var(--accent)", labels = [], yFmt = v => v }) => {
  const ref = useRef(null);
  const [w, setW] = useState(600);
  useEffect(() => {
    if (!ref.current) return;
    const ro = new ResizeObserver(([e]) => setW(e.contentRect.width));
    ro.observe(ref.current);
    return () => ro.disconnect();
  }, []);
  const padL = 44, padR = 8, padT = 14, padB = 22;
  const innerW = w - padL - padR;
  const innerH = height - padT - padB;
  const min = Math.min(...data), max = Math.max(...data);
  const range = max - min || 1;
  const yTicks = 4;
  const ticks = Array.from({length: yTicks+1}, (_, i) => min + (range * i)/yTicks);
  const id = useId().replace(/:/g, "");

  const pts = data.map((v,i) => {
    const x = padL + (i/(data.length-1)) * innerW;
    const y = padT + innerH - ((v-min)/range) * innerH;
    return [x, y, v];
  });
  const linePath = pts.map((p,i)=>`${i===0?"M":"L"} ${p[0].toFixed(2)} ${p[1].toFixed(2)}`).join(" ");
  const areaPath = `${linePath} L ${pts[pts.length-1][0]} ${padT+innerH} L ${pts[0][0]} ${padT+innerH} Z`;

  const [hover, setHover] = useState(null);

  return (
    <div ref={ref} style={{ width: "100%", height, position: "relative" }}>
      <svg width={w} height={height} style={{ display: "block" }}
        onMouseMove={(e) => {
          const rect = e.currentTarget.getBoundingClientRect();
          const x = e.clientX - rect.left;
          if (x < padL || x > w - padR) { setHover(null); return; }
          const idx = Math.round(((x - padL) / innerW) * (data.length - 1));
          setHover(Math.max(0, Math.min(data.length-1, idx)));
        }}
        onMouseLeave={() => setHover(null)}
      >
        <defs>
          <linearGradient id={"a"+id} x1="0" y1="0" x2="0" y2="1">
            <stop offset="0"  stopColor={color} stopOpacity="0.20"/>
            <stop offset="1"  stopColor={color} stopOpacity="0"/>
          </linearGradient>
        </defs>
        {/* y grid */}
        {ticks.map((t, i) => {
          const y = padT + innerH - ((t-min)/range) * innerH;
          return (
            <g key={i}>
              <line x1={padL} x2={w-padR} y1={y} y2={y} stroke="var(--hairline)" strokeWidth="1"/>
              <text x={padL-8} y={y+3} textAnchor="end" fill="var(--ink-3)" fontFamily="var(--font-mono)" fontSize="9.5">{yFmt(t)}</text>
            </g>
          );
        })}
        {/* x labels */}
        {labels.map((l, i) => {
          const x = padL + (i/(labels.length-1)) * innerW;
          return <text key={i} x={x} y={height-6} textAnchor="middle" fill="var(--ink-3)" fontFamily="var(--font-mono)" fontSize="9.5">{l}</text>;
        })}
        <path d={areaPath} fill={"url(#a"+id+")"}/>
        <path d={linePath} fill="none" stroke={color} strokeWidth="1.5"/>

        {hover != null && (
          <g>
            <line x1={pts[hover][0]} x2={pts[hover][0]} y1={padT} y2={padT+innerH} stroke="var(--ink-4)" strokeDasharray="2 3" strokeWidth="1"/>
            <circle cx={pts[hover][0]} cy={pts[hover][1]} r="3.5" fill="var(--surface)" stroke={color} strokeWidth="1.5"/>
          </g>
        )}
      </svg>
      {hover != null && (
        <div style={{
          position: "absolute",
          left: Math.min(pts[hover][0] + 10, w - 130),
          top: Math.max(pts[hover][1] - 30, 4),
          background: "var(--ink)", color: "var(--paper)",
          borderRadius: 4, padding: "4px 8px",
          fontFamily: "var(--font-mono)", fontSize: 10.5,
          pointerEvents: "none", whiteSpace: "nowrap",
        }}>
          {labels[hover] && <span style={{opacity:.6, marginRight:8}}>{labels[hover]}</span>}
          {yFmt(pts[hover][2])}
        </div>
      )}
    </div>
  );
};

// Vertical bars
const BarChart = ({ data, height = 120, labels = [], color = "var(--accent)", highlightIdx = -1 }) => {
  const ref = useRef(null);
  const [w, setW] = useState(400);
  useEffect(() => {
    if (!ref.current) return;
    const ro = new ResizeObserver(([e]) => setW(e.contentRect.width));
    ro.observe(ref.current);
    return () => ro.disconnect();
  }, []);
  const padL = 6, padR = 6, padT = 8, padB = 18;
  const innerW = w - padL - padR;
  const innerH = height - padT - padB;
  const max = Math.max(...data) || 1;
  const bw = innerW / data.length;
  return (
    <div ref={ref} style={{ width: "100%", height }}>
      <svg width={w} height={height} style={{ display: "block" }}>
        {data.map((v, i) => {
          const x = padL + i*bw + bw*0.15;
          const bh = (v / max) * innerH;
          const y = padT + innerH - bh;
          const isHl = i === highlightIdx;
          return (
            <g key={i}>
              <rect x={x} y={y} width={bw*0.7} height={bh}
                fill={isHl ? color : "var(--ink-4)"}
                opacity={isHl ? 1 : 0.32} rx="1"/>
            </g>
          );
        })}
        {/* hour labels every 4h */}
        {labels.map((l, i) => i % 4 === 0 ? (
          <text key={i} x={padL + i*bw + bw*0.5} y={height - 4}
            textAnchor="middle" fill="var(--ink-3)"
            fontFamily="var(--font-mono)" fontSize="9.5">{l}</text>
        ) : null)}
      </svg>
    </div>
  );
};

// Donut / radial progress
const Donut = ({ value = 0.7, size = 64, stroke = 8, color = "var(--accent)", trackColor = "var(--surface-3)" }) => {
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  return (
    <svg width={size} height={size} style={{display:"block"}}>
      <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={trackColor} strokeWidth={stroke}/>
      <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={color} strokeWidth={stroke}
        strokeDasharray={`${c*value} ${c}`} strokeLinecap="round"
        transform={`rotate(-90 ${size/2} ${size/2})`}/>
    </svg>
  );
};

// Heatmap (e.g. orders by hour x day)
const Heatmap = ({ rows = 7, cols = 24, data, rowLabels = [], colLabels = [], color = "var(--accent)" }) => {
  const max = Math.max(...data.flat()) || 1;
  const cell = 18, gap = 2;
  const w = cols * (cell + gap) + 32;
  const h = rows * (cell + gap) + 18;
  return (
    <svg width={w} height={h} style={{ display: "block" }}>
      {data.map((row, ri) => row.map((v, ci) => {
        const o = (v / max);
        return (
          <rect key={`${ri}-${ci}`}
            x={32 + ci*(cell+gap)} y={ri*(cell+gap)}
            width={cell} height={cell} rx="1.5"
            fill={color} opacity={Math.max(0.04, o*0.95)}
          />
        );
      }))}
      {rowLabels.map((l, i) => (
        <text key={i} x={26} y={i*(cell+gap) + cell*0.7}
          textAnchor="end" fontFamily="var(--font-mono)" fontSize="9" fill="var(--ink-3)">{l}</text>
      ))}
      {colLabels.map((l, i) => i % 4 === 0 ? (
        <text key={i} x={32 + i*(cell+gap) + cell/2} y={h - 4}
          textAnchor="middle" fontFamily="var(--font-mono)" fontSize="9" fill="var(--ink-3)">{l}</text>
      ) : null)}
    </svg>
  );
};

Object.assign(window, { Sparkline, AreaChart, BarChart, Donut, Heatmap });
