// charts.jsx — small SVG chart primitives
const { useMemo, useState, useRef, useEffect } = React;

// 12-month area chart (unique visitors)
function MonthlyVisitorsChart({ data, height = 280 }) {
  const w = 800, h = height, ml = 40, mr = 16, mt = 16, mb = 28;
  const cw = w - ml - mr, ch = h - mt - mb;
  const max = Math.max(...data.map(d => d.v));
  const min = 0;
  const x = i => ml + (i / (data.length - 1)) * cw;
  const y = v => mt + ch - ((v - min) / (max - min)) * ch;

  const linePath = data.map((d, i) => `${i === 0 ? "M" : "L"} ${x(i)} ${y(d.v)}`).join(" ");
  const areaPath = linePath + ` L ${x(data.length - 1)} ${mt + ch} L ${x(0)} ${mt + ch} Z`;

  const ticks = [0, 200, 400, 600, 800];
  const [hover, setHover] = useState(null);

  return (
    <svg viewBox={`0 0 ${w} ${h}`} className="spark area" onMouseLeave={() => setHover(null)}>
      <defs>
        <linearGradient id="visGrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="oklch(0.30 0.06 150)" stopOpacity="0.18" />
          <stop offset="100%" stopColor="oklch(0.30 0.06 150)" stopOpacity="0" />
        </linearGradient>
      </defs>
      {ticks.map(t => (
        <g key={t}>
          <line className="gridline" x1={ml} x2={w - mr} y1={y(t)} y2={y(t)} />
          <text x={ml - 8} y={y(t) + 3} textAnchor="end" className="axis-text" style={{ fontFamily: "JetBrains Mono", fontSize: 10, fill: "var(--mid)" }}>{t}</text>
        </g>
      ))}
      <path d={areaPath} fill="url(#visGrad)" />
      <path d={linePath} stroke="oklch(0.30 0.06 150)" strokeWidth="2.5" fill="none" strokeLinejoin="round" strokeLinecap="round" />
      {data.map((d, i) => (
        <g key={i}>
          <circle cx={x(i)} cy={y(d.v)} r={hover === i ? 5 : 3} fill="oklch(0.30 0.06 150)" stroke="var(--bg-2)" strokeWidth="2" />
          <rect x={x(i) - 18} y={mt} width={36} height={ch} fill="transparent" onMouseEnter={() => setHover(i)} />
          <text x={x(i)} y={h - 10} textAnchor="middle" style={{ fontFamily: "JetBrains Mono", fontSize: 10, fill: "var(--mid)" }}>{d.m}</text>
        </g>
      ))}
      {hover !== null && (
        <g style={{ pointerEvents: "none" }}>
          <line x1={x(hover)} x2={x(hover)} y1={mt} y2={mt + ch} stroke="var(--ink)" strokeDasharray="2 3" strokeWidth="1" opacity="0.4" />
          <g transform={`translate(${x(hover)}, ${y(data[hover].v) - 18})`}>
            <rect x={-32} y={-22} width={64} height={20} fill="var(--ink)" rx={3} />
            <text x={0} y={-8} textAnchor="middle" style={{ fontFamily: "JetBrains Mono", fontSize: 11, fill: "var(--bg)" }}>{data[hover].v}</text>
          </g>
        </g>
      )}
    </svg>
  );
}

// 30-day impressions bar chart
function DailyImpressionsChart({ data, height = 220, tone = "light" }) {
  const w = 800, h = height, ml = 40, mr = 8, mt = 20, mb = 26;
  const cw = w - ml - mr, ch = h - mt - mb;
  const max = Math.max(...data.map(d => d[1]));
  const bw = cw / data.length - 2;
  const x = i => ml + i * (cw / data.length);
  const y = v => mt + ch - (v / max) * ch;

  const ticks = [0, 500, 1000, 1500, 2000];
  const [hover, setHover] = useState(null);

  const barFill = tone === "dark" ? "oklch(0.78 0.16 138)" : "var(--ink)";
  const barHover = tone === "dark" ? "oklch(0.92 0.18 128)" : "var(--lime-deep)";
  const axisCol = tone === "dark" ? "oklch(0.7 0.02 90)" : "var(--mid)";
  const gridCol = tone === "dark" ? "oklch(0.32 0.012 80)" : "var(--rule)";
  const tipBg = tone === "dark" ? "var(--lime)" : "var(--ink)";
  const tipFg = tone === "dark" ? "oklch(0.16 0.012 80)" : "var(--bg)";

  return (
    <svg viewBox={`0 0 ${w} ${h}`} className="spark bars" onMouseLeave={() => setHover(null)}>
      {ticks.map(t => (
        <g key={t}>
          <line className="gridline" x1={ml} x2={w - mr} y1={y(t)} y2={y(t)} stroke={gridCol} />
          <text x={ml - 8} y={y(t) + 3} textAnchor="end" style={{ fontFamily: "JetBrains Mono", fontSize: 10, fill: axisCol }}>{t}</text>
        </g>
      ))}
      {data.map((d, i) => {
        const bh = ch - (y(d[1]) - mt);
        return (
          <g key={i} onMouseEnter={() => setHover(i)}>
            <rect x={x(i)} y={y(d[1])} width={bw} height={bh}
                  fill={hover === i ? barHover : barFill} />
          </g>
        );
      })}
      {data.map((d, i) => (i % 5 === 0) && (
        <text key={i} x={x(i) + bw / 2} y={h - 8} textAnchor="middle"
              style={{ fontFamily: "JetBrains Mono", fontSize: 10, fill: axisCol }}>{d[0]}</text>
      ))}
      {hover !== null && (
        <g style={{ pointerEvents: "none" }} transform={`translate(${x(hover) + bw / 2}, ${y(data[hover][1]) - 8})`}>
          <rect x={-44} y={-22} width={88} height={20} fill={tipBg} rx={3} />
          <text x={0} y={-8} textAnchor="middle" style={{ fontFamily: "JetBrains Mono", fontSize: 10, fill: tipFg }}>
            {data[hover][0]} · {data[hover][1].toLocaleString()}
          </text>
        </g>
      )}
    </svg>
  );
}

// Donut for device split
function DeviceDonut({ devices, size = 220 }) {
  const total = devices.mobile.imp + devices.desktop.imp + devices.tablet.imp;
  const segments = [
    { name: "Mobile", v: devices.mobile.imp, c: "var(--lime-deep)" },
    { name: "Desktop", v: devices.desktop.imp, c: "var(--ink)" },
    { name: "Tablet", v: devices.tablet.imp, c: "var(--clay)" },
  ];
  const r = size / 2 - 18, cx = size / 2, cy = size / 2;
  const C = 2 * Math.PI * r;
  let off = -C * 0.25; // start at top
  return (
    <svg viewBox={`0 0 ${size} ${size}`} width={size} height={size}>
      <circle cx={cx} cy={cy} r={r} fill="none" stroke="var(--rule)" strokeWidth="24" />
      {segments.map((s, i) => {
        const frac = s.v / total;
        const len = C * frac;
        const el = (
          <circle key={i} cx={cx} cy={cy} r={r}
                  fill="none" stroke={s.c} strokeWidth="24"
                  strokeDasharray={`${len} ${C - len}`}
                  strokeDashoffset={-off} />
        );
        off += len;
        return el;
      })}
      <text x={cx} y={cy - 4} textAnchor="middle" style={{ fontFamily: "Instrument Serif", fontSize: 34, fill: "var(--ink)" }}>
        {Math.round(devices.mobile.imp / total * 100)}%
      </text>
      <text x={cx} y={cy + 16} textAnchor="middle" style={{ fontFamily: "JetBrains Mono", fontSize: 10, letterSpacing: "0.10em", textTransform: "uppercase", fill: "var(--mid)" }}>
        Mobile
      </text>
    </svg>
  );
}

// CountUp — initial state = target value so it's always visible; animate via setTimeout
// (rAF is paused in hidden tabs / screenshot iframes — setTimeout always runs)
function CountUp({ to, suffix = "", duration = 1400, format = (n) => Math.round(n).toLocaleString() }) {
  const [v, setV] = useState(to);
  useEffect(() => {
    if (typeof document !== "undefined" && document.visibilityState === "hidden") {
      setV(to);
      return;
    }
    setV(0);
    const start = Date.now();
    const tick = () => {
      const p = Math.min(1, (Date.now() - start) / duration);
      const eased = 1 - Math.pow(1 - p, 3);
      setV(to * eased);
      if (p < 1) timer = setTimeout(tick, 16);
    };
    let timer = setTimeout(tick, 16);
    return () => clearTimeout(timer);
  }, [to]);
  return <span>{format(v)}{suffix}</span>;
}

Object.assign(window, { MonthlyVisitorsChart, DailyImpressionsChart, DeviceDonut, CountUp });
