// olivia-overview-data.jsx
// Sample analytics data + chart primitives for the Olivia studio Overview page.

const OV = {
  pageBg: '#F5EFE6', panel: '#FFFCF7', panelMute: '#FAF4EA',
  hair: 'rgba(58,46,38,0.08)', hairStrong: 'rgba(58,46,38,0.16)',
  ink: '#3A2E26', inkSoft: '#7A6E66', inkMute: '#A89E94',
  accent: '#D97757', accentDeep: '#B85A3D', accentWash: '#FAE7D8',
  sage: '#6FA06A', sageDeep: '#4E6147', sageWash: '#E1ECDB',
  amber: '#D9A03A', amberWash: '#F8EBCB',
  rose: '#C56B6E', roseWash: '#F5DBDC',
  sky: '#5E83A0',
};

const OV_DATA = {
  asOf: 'Jun 6, 2026 · 9:00 AM',
  signups: { total: 12847, week: 384, prevWeek: 351 },
  active: { count: 7210, pct: 56, prev: 6940 },
  childrenCount: { total: 21340, prev: 19860 },
  cardsCompleted: { total: 198432, week: 14820 },
  avgStreak: 9.4, longestStreak: 63, prevAvgStreak: 8.8,

  signupTrend: [612, 588, 640, 705, 690, 742, 798, 760, 690, 720, 351, 384],
  activeTrend: [3200, 3600, 4050, 4520, 4980, 5400, 5880, 6240, 6580, 6880, 6940, 7210],

  byKind: [
    { kind: 'Prayer of thanks', count: 72400, color: '#D97757' },
    { kind: 'Bedtime ritual',   count: 41200, color: '#7A8B6F' },
    { kind: 'Bible story',      count: 33800, color: '#5E83A0' },
    { kind: 'Prayer of asking', count: 29600, color: '#D9A03A' },
    { kind: 'Wonder walk',      count: 21432, color: '#C56B8A' },
  ],

  streakBuckets: [
    { label: '1–3 days', count: 3180 },
    { label: '4–7 days', count: 2140 },
    { label: '8–14 days', count: 1160 },
    { label: '15–30 days', count: 540 },
    { label: '30+ days', count: 190 },
  ],

  milestones: [
    { id: 'first-prayer', label: 'First prayer together', count: 9120 },
    { id: 'seven-day',    label: '7-day streak',          count: 5340 },
    { id: 'first-story',  label: 'First Bible story',      count: 4980 },
    { id: 'blessing',     label: 'First bedtime blessing', count: 3180 },
    { id: 'thirty',       label: '30-day streak',          count: 1290 },
  ],

  dropOff: [
    980, 1520, 1840, 1610, 1330, 980, 1120, 740, 620, 540,
    470, 410, 360, 380, 290, 250, 220, 200, 180, 170,
    190, 140, 120, 110, 100, 95, 90, 110, 80, 70,
  ],
};

const ovFmt = (n) => n.toLocaleString('en-US');
const ovPctOf = (n, d) => Math.round((n / d) * 100);

function ovSmoothPath(points) {
  if (points.length < 2) return '';
  let d = `M${points[0][0]},${points[0][1]}`;
  for (let i = 0; i < points.length - 1; i++) {
    const p0 = points[i - 1] || points[i];
    const p1 = points[i];
    const p2 = points[i + 1];
    const p3 = points[i + 2] || p2;
    const c1x = p1[0] + (p2[0] - p0[0]) / 6;
    const c1y = p1[1] + (p2[1] - p0[1]) / 6;
    const c2x = p2[0] - (p3[0] - p1[0]) / 6;
    const c2y = p2[1] - (p3[1] - p1[1]) / 6;
    d += ` C${c1x.toFixed(1)},${c1y.toFixed(1)} ${c2x.toFixed(1)},${c2y.toFixed(1)} ${p2[0].toFixed(1)},${p2[1].toFixed(1)}`;
  }
  return d;
}

function OvAreaChart({ values, color = OV.accent, fill = 'rgba(217,119,87,0.12)', h = 120 }) {
  const W = 600, H = h, pad = 8;
  const max = Math.max(...values) * 1.08;
  const min = Math.min(...values) * 0.92;
  const pts = values.map((v, i) => [
    pad + (i * (W - 2 * pad)) / (values.length - 1),
    H - pad - ((v - min) / (max - min)) * (H - 2 * pad),
  ]);
  const line = ovSmoothPath(pts);
  const area = `${line} L${pts[pts.length - 1][0]},${H} L${pts[0][0]},${H} Z`;
  const last = pts[pts.length - 1];
  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={h} preserveAspectRatio="none" style={{ display: 'block' }}>
      <path d={area} fill={fill}/>
      <path d={line} fill="none" stroke={color} strokeWidth="2.5" strokeLinecap="round"/>
      <circle cx={last[0]} cy={last[1]} r="4" fill={color}/>
      <circle cx={last[0]} cy={last[1]} r="8" fill={color} opacity="0.18"/>
    </svg>
  );
}

function OvSpark({ values, color = OV.sage, w = null, h = 38 }) {
  const W = 400, H = h, pad = 4;
  const max = Math.max(...values), min = Math.min(...values);
  const pts = values.map((v, i) => [
    pad + (i * (W - 2 * pad)) / (values.length - 1),
    H - pad - ((v - min) / (max - min || 1)) * (H - 2 * pad),
  ]);
  const line = ovSmoothPath(pts);
  const area = `${line} L${pts[pts.length-1][0]},${H} L${pts[0][0]},${H} Z`;
  const fillColor = color + '22';
  return (
    <svg viewBox={`0 0 ${W} ${H}`} width={w || '100%'} height={h} preserveAspectRatio="none" style={{ display: 'block' }}>
      <path d={area} fill={fillColor}/>
      <path d={line} fill="none" stroke={color} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  );
}

function OvDonut({ pct, size = 92, stroke = 11, color = OV.sage, track = '#E7DECF', children }) {
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const off = c * (1 - pct / 100);
  return (
    <div style={{ position: 'relative', width: size, height: size }}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={track} strokeWidth={stroke}/>
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={color} strokeWidth={stroke}
          strokeDasharray={c} strokeDashoffset={off} strokeLinecap="round"/>
      </svg>
      <div style={{
        position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column',
        alignItems: 'center', justifyContent: 'center',
      }}>{children}</div>
    </div>
  );
}

Object.assign(window, { OV, OV_DATA, ovFmt, ovPctOf, OvAreaChart, OvSpark, OvDonut });
