/* Charts — pure SVG, no libraries. Brand-tuned. */
const { useMemo: useMemo_c } = React;

/* Sparkline */
function Spark({ values, w = 80, h = 20, color = 'var(--text-dim)', fill }) {
  if (!values || values.length === 0) return null;
  const min = Math.min(...values);
  const max = Math.max(...values);
  const range = max - min || 1;
  const step = w / (values.length - 1);
  const pts = values.map((v, i) => [i * step, h - ((v - min) / range) * h]);
  const d = pts.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(' ');
  const dArea = `${d} L${w},${h} L0,${h} Z`;
  return (
    <svg width={w} height={h} style={{ display: 'block' }}>
      {fill && <path d={dArea} fill={fill} />}
      <path d={d} fill="none" stroke={color} strokeWidth="1.5" />
    </svg>
  );
}

/* Position history mini — line that goes down=better */
function PosSpark({ values, w = 100, h = 24 }) {
  if (!values || values.length === 0) return null;
  // null / 0 / >100 = not found in tracked SERP depth. Plot at chart floor (100)
  // so unranked weeks drop to the bottom; coercing them to 0 puts them at the top
  // and makes unranked keywords look like rank #1.
  const UNRANKED = 100;
  const isUnranked = (v) => v == null || v <= 0 || v > 100;
  const safe = values.map(v => isUnranked(v) ? UNRANKED : v);
  const max = Math.max(20, Math.max(...safe));
  const min = 1;
  const range = max - min;
  const step = w / (safe.length - 1);
  // Lower position = higher on chart
  const pts = safe.map((v, i) => [i * step, ((v - min) / range) * h]);
  const d = pts.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(' ');
  const last = values[values.length - 1];
  const lastTop = isUnranked(last) ? 'var(--text-muted)'
                : last <= 3 ? 'var(--gold)' : last <= 10 ? 'var(--accent)' : 'var(--text-muted)';
  return (
    <svg width={w} height={h} style={{ display: 'block' }}>
      <path d={d} fill="none" stroke={lastTop} strokeWidth="1.5" />
      <circle cx={pts[pts.length - 1][0]} cy={pts[pts.length - 1][1]} r="2" fill={lastTop} />
    </svg>
  );
}

/* Format a series date ('YYYY-MM-DD' or GA4 'YYYYMMDD') as a short axis label. */
function fmtChartDate(s) {
  if (s == null) return '';
  const str = String(s);
  let y, m, d;
  if (str.includes('-')) { const p = str.split('-'); y = p[0]; m = p[1]; d = p[2]; }
  else if (/^\d{8}$/.test(str)) { y = str.slice(0, 4); m = str.slice(4, 6); d = str.slice(6, 8); }
  else return '';
  const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
  const mi = parseInt(m, 10) - 1;
  return (mi >= 0 && mi <= 11) ? `${months[mi]} ${parseInt(d, 10)}` : '';
}

/* Big trend chart for traffic. `dates` (same length as `current`) drives the
   x-axis labels so the axis always matches the selected reporting period. */
function TrendChart({ current, previous, dates, height = 260, format = (v) => v }) {
  const w = 1000;
  const h = height;
  const padL = 48;
  const padR = 16;
  const padT = 16;
  const padB = 32;
  const innerW = w - padL - padR;
  const innerH = h - padT - padB;

  const all = [...current, ...(previous || [])];
  const max = Math.ceil(Math.max(...all) / 100) * 100;
  const min = 0;
  const stepX = innerW / (current.length - 1);

  const pathFor = (vals) => vals.map((v, i) => {
    const x = padL + i * stepX;
    const y = padT + innerH - ((v - min) / (max - min)) * innerH;
    return (i === 0 ? `M${x},${y}` : `L${x},${y}`);
  }).join(' ');

  const areaFor = (vals) => `${pathFor(vals)} L${padL + (vals.length - 1) * stepX},${padT + innerH} L${padL},${padT + innerH} Z`;

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

  // X-axis labels derived from the real series dates (when provided) so the axis
  // always matches the selected period. Falls back to blank rather than the old
  // hardcoded Feb-Apr labels if dates aren't passed.
  const hasDates = Array.isArray(dates) && dates.length === current.length && current.length > 0;
  const tickCount = Math.min(7, current.length);
  const labelIdx = tickCount > 1
    ? Array.from({ length: tickCount }, (_, i) => Math.round((current.length - 1) * (i / (tickCount - 1))))
    : current.length === 1 ? [0] : [];
  const labels = hasDates ? labelIdx.map(idx => fmtChartDate(dates[idx])) : labelIdx.map(() => '');

  return (
    <svg viewBox={`0 0 ${w} ${h}`} className="chart-frame" preserveAspectRatio="none" style={{height}}>
      <defs>
        <linearGradient id="goldArea" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%"   stopColor="var(--gold)" stopOpacity="0.18"/>
          <stop offset="100%" stopColor="var(--gold)" stopOpacity="0"/>
        </linearGradient>
      </defs>
      {/* Grid + y labels */}
      {ticks.map((t, i) => {
        const y = padT + innerH - ((t - min) / (max - min)) * innerH;
        return (
          <g key={i}>
            <line x1={padL} x2={w - padR} y1={y} y2={y} className="chart-grid" />
            <text x={padL - 10} y={y + 3} textAnchor="end" className="chart-y-label">{format(t)}</text>
          </g>
        );
      })}
      {/* Previous (dashed) */}
      {previous && (
        <path d={pathFor(previous)} fill="none" stroke="var(--text-dim)" strokeWidth="1" strokeDasharray="3 4" opacity="0.7"/>
      )}
      {/* Current */}
      <path d={areaFor(current)} fill="url(#goldArea)" />
      <path d={pathFor(current)} fill="none" stroke="var(--gold)" strokeWidth="1.75" />
      {/* X labels */}
      {labels.map((l, i) => {
        const x = padL + labelIdx[i] * stepX;
        return <text key={i} x={x} y={h - 10} textAnchor="middle" className="chart-x-label">{l}</text>;
      })}
    </svg>
  );
}

/* Donut for channel mix */
function Donut({ data, size = 200, total }) {
  const r = size / 2 - 14;
  const cx = size / 2;
  const cy = size / 2;
  const C = 2 * Math.PI * r;
  const colors = ['var(--gold)', 'var(--text)', 'var(--accent)', 'var(--gold-light)', 'var(--text-muted)', 'var(--text-dim)'];
  let off = 0;
  return (
    <svg width={size} height={size}>
      <circle cx={cx} cy={cy} r={r} fill="none" stroke="var(--surface)" strokeWidth="14"/>
      {data.map((d, i) => {
        const len = (d.share / 100) * C;
        const dash = `${len} ${C - len}`;
        const el = (
          <circle key={i} cx={cx} cy={cy} r={r} fill="none"
                  stroke={colors[i % colors.length]} strokeWidth="14"
                  strokeDasharray={dash} strokeDashoffset={-off}
                  transform={`rotate(-90 ${cx} ${cy})`}/>
        );
        off += len;
        return el;
      })}
      <text x={cx} y={cy - 4} textAnchor="middle" className="donut-center">
        {(total / 1000).toFixed(1)}k
      </text>
      <text x={cx} y={cy + 14} textAnchor="middle" className="donut-center-label">Sessions · 30d</text>
    </svg>
  );
}

/* Horizontal bars stack — for distributions like DR */
function HBar({ items, max, format = (v) => v }) {
  return (
    <div style={{display:'flex', flexDirection:'column', gap: 8}}>
      {items.map((it, i) => (
        <div key={i} style={{display:'flex', alignItems:'center', gap: 12, fontSize: 12, fontFamily: 'var(--font-mono)'}}>
          <span style={{ width: 64, color: 'var(--text-dim)', letterSpacing: '0.1em', textTransform: 'uppercase', fontSize: 10 }}>{it.label}</span>
          <span className="bar" style={{flex: 1, height: 8, background: 'var(--surface)', borderRadius: 2, overflow: 'hidden'}}>
            <span style={{display:'block', height:'100%', width: `${(it.value / max) * 100}%`, background: it.color || 'var(--gold)'}}/>
          </span>
          <span className="num" style={{width: 50, textAlign:'right', color:'var(--text)'}}>{format(it.value)}</span>
        </div>
      ))}
    </div>
  );
}

window.Spark = Spark;
window.PosSpark = PosSpark;
window.TrendChart = TrendChart;
window.Donut = Donut;
window.HBar = HBar;
