// Shared UI primitives

function Sparkline({ data, color="var(--accent)", height=28, fill=true }) {
  if (!data || !data.length) return null;
  const w = 100;
  const max = Math.max(...data.map(d=>d.v));
  const min = Math.min(...data.map(d=>d.v));
  const pts = data.map((d,i) => {
    const x = (i/(data.length-1)) * w;
    const y = height - 2 - ((d.v - min) / Math.max(1, max-min)) * (height - 4);
    return [x,y];
  });
  const line = pts.map((p,i)=> (i===0?"M":"L") + p[0].toFixed(2) + "," + p[1].toFixed(2)).join(" ");
  const area = line + ` L ${w},${height} L 0,${height} Z`;
  return (
    <svg className="chart" viewBox={`0 0 ${w} ${height}`} preserveAspectRatio="none" style={{height}}>
      {fill && <path d={area} fill={color} opacity="0.1"/>}
      <path d={line} fill="none" stroke={color} strokeWidth="1.4" vectorEffect="non-scaling-stroke"/>
    </svg>
  );
}

function EmptyState({ icon="sparkle", message="No data yet", sub }) {
  const Ic = Icon[icon] || Icon.sparkle;
  return (
    <div style={{display:"flex", flexDirection:"column", alignItems:"center", justifyContent:"center",
                 padding:"40px 24px", gap:10, color:"var(--ink-4)"}}>
      <Ic size={28} style={{opacity:.4}}/>
      <div style={{fontSize:13, fontWeight:500, color:"var(--ink-3)"}}>{message}</div>
      {sub && <div style={{fontSize:12, color:"var(--ink-4)", textAlign:"center", maxWidth:280}}>{sub}</div>}
    </div>
  );
}

function LineChart({ data, color="var(--accent)", height=220, valueLabel=v=>v, secondary }) {
  if (!data || data.length < 2) return <EmptyState message="No data yet" sub="Charts will appear once your app has users"/>;
  const w = 800;
  const pad = { l: 40, r: 16, t: 14, b: 26 };
  const ih = height - pad.t - pad.b;
  const iw = w - pad.l - pad.r;
  const all = secondary ? [...data.map(d=>d.v), ...secondary.map(d=>d.v)] : data.map(d=>d.v);
  const max = Math.max(...all)*1.1 || 1;
  const min = 0;
  const x = i => pad.l + (i/(data.length-1)) * iw;
  const y = v => pad.t + ih - ((v - min) / (max - min)) * ih;
  const mkPath = arr => arr.map((d,i)=> (i===0?"M":"L") + x(i) + "," + y(d.v)).join(" ");
  const linePath = mkPath(data);
  const areaPath = linePath + ` L ${x(data.length-1)},${pad.t+ih} L ${x(0)},${pad.t+ih} Z`;
  const ticks = 4;
  const yTicks = Array.from({length:ticks+1}, (_,i)=> min + (max-min)*i/ticks);
  const xTicks = [0, Math.floor(data.length/4), Math.floor(data.length/2), Math.floor(3*data.length/4), data.length-1];
  return (
    <svg className="chart" viewBox={`0 0 ${w} ${height}`} preserveAspectRatio="none" style={{height, width:"100%"}}>
      {yTicks.map((t,i)=>(
        <g key={i}>
          <line x1={pad.l} x2={pad.l+iw} y1={y(t)} y2={y(t)} className="grid-line" strokeDasharray="2 3"/>
          <text x={pad.l-6} y={y(t)+3} textAnchor="end" className="axis-text">{valueLabel(t)}</text>
        </g>
      ))}
      {xTicks.map((i)=>(
        <text key={i} x={x(i)} y={height-8} textAnchor="middle" className="axis-text">
          {data[i].date.toLocaleDateString('en-US',{month:'short',day:'numeric'})}
        </text>
      ))}
      {secondary && <path d={mkPath(secondary)} fill="none" stroke="var(--ink-4)" strokeWidth="1.2" strokeDasharray="3 3"/>}
      <path d={areaPath} fill={color} opacity="0.09"/>
      <path d={linePath} fill="none" stroke={color} strokeWidth="1.8"/>
    </svg>
  );
}

function BarChart({ data, color="var(--accent)", height=220, valueLabel=v=>v }) {
  if (!data || data.length === 0) return <EmptyState message="No data yet" sub="Charts will appear once your app has users"/>;
  const w = 800;
  const pad = { l: 40, r: 16, t: 14, b: 26 };
  const ih = height - pad.t - pad.b;
  const iw = w - pad.l - pad.r;
  const max = Math.max(...data.map(d=>d.v)) * 1.1 || 1;
  const bw = iw / data.length * 0.7;
  const step = iw / data.length;
  const y = v => pad.t + ih - ((v) / max) * ih;
  const yTicks = Array.from({length:4+1}, (_,i)=> max*i/4);
  const xTicks = [0, Math.floor(data.length/4), Math.floor(data.length/2), Math.floor(3*data.length/4), data.length-1];
  return (
    <svg className="chart" viewBox={`0 0 ${w} ${height}`} preserveAspectRatio="none" style={{height, width:"100%"}}>
      {yTicks.map((t,i)=>(
        <g key={i}>
          <line x1={pad.l} x2={pad.l+iw} y1={y(t)} y2={y(t)} className="grid-line" strokeDasharray="2 3"/>
          <text x={pad.l-6} y={y(t)+3} textAnchor="end" className="axis-text">{valueLabel(t)}</text>
        </g>
      ))}
      {xTicks.map((i)=>(
        <text key={i} x={pad.l + step*i + step/2} y={height-8} textAnchor="middle" className="axis-text">
          {data[i].date.toLocaleDateString('en-US',{month:'short',day:'numeric'})}
        </text>
      ))}
      {data.map((d,i) => (
        <rect key={i} x={pad.l + step*i + (step-bw)/2} y={y(d.v)}
          width={bw} height={pad.t+ih-y(d.v)} fill={color} opacity={0.85} rx="1.5"/>
      ))}
    </svg>
  );
}

function Donut({ segments, size=140, stroke=18, centerLabel, centerValue }) {
  const r = size/2 - stroke/2;
  const c = 2 * Math.PI * r;
  const total = segments.reduce((a,s)=>a+s.value, 0);
  if (total === 0) {
    return (
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="var(--border)" strokeWidth={stroke}/>
        <text x={size/2} y={size/2+5} textAnchor="middle" style={{font:"500 11px var(--sans)", fill:"var(--ink-4)"}}>No data</text>
      </svg>
    );
  }
  let offset = 0;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
      <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="var(--border)" strokeWidth={stroke}/>
      {segments.map((s, i) => {
        const len = (s.value/total) * c;
        const el = (
          <circle key={i} cx={size/2} cy={size/2} r={r} fill="none"
            stroke={s.color} strokeWidth={stroke}
            strokeDasharray={`${len} ${c-len}`}
            strokeDashoffset={-offset}
            transform={`rotate(-90 ${size/2} ${size/2})`}
            strokeLinecap="butt"/>
        );
        offset += len;
        return el;
      })}
      {centerValue && (
        <>
          <text x={size/2} y={size/2 - 2} textAnchor="middle" style={{font:"600 18px var(--display)", fill:"var(--ink)"}}>{centerValue}</text>
          <text x={size/2} y={size/2 + 14} textAnchor="middle" style={{font:"500 10px var(--sans)", fill:"var(--ink-3)", letterSpacing:".05em", textTransform:"uppercase"}}>{centerLabel}</text>
        </>
      )}
    </svg>
  );
}

function KPI({ label, value, unit, delta, spark, sparkColor, icon }) {
  const up = delta && delta > 0;
  const Ic = icon ? Icon[icon] : null;
  return (
    <div className="kpi">
      <div className="label">
        {Ic && <Ic size={12}/>}
        {label}
      </div>
      <div className="value">
        <span>{value}</span>
        {unit && <span className="unit">{unit}</span>}
      </div>
      {delta != null && (
        <div className={"delta " + (up ? "up" : "down")}>
          {up ? "▲" : "▼"} {Math.abs(delta).toFixed(1)}%
          <span style={{color:"var(--ink-4)"}}> vs last 30d</span>
        </div>
      )}
      {spark && <Sparkline data={spark} color={sparkColor || "var(--accent)"} height={28}/>}
    </div>
  );
}

function UserCell({ user }) {
  if (!user) return <span className="muted">—</span>;
  const display    = user.name || user.email || "Guest";
  const avatarSeed = user.name || user.email || user.uid || "?";
  const initials   = avatarSeed.split(/[\s@]/).filter(Boolean).map(n=>n[0]).slice(0,2).join('').toUpperCase() || "?";
  // sub-line: email for named users, uid fallback for anonymous users (kid name shown in its own column)
  const sub = user.email || (user.uid ? user.uid.slice(0,10)+"…" : null);
  return (
    <div className="cell-user">
      <div className="avatar" style={{width:24, height:24, fontSize:10}}>{initials || "?"}</div>
      <div style={{minWidth:0}}>
        <div style={{fontWeight:500, overflow:'hidden', textOverflow:'ellipsis'}}>{display}</div>
        {sub && <div className="muted" style={{fontSize:11, overflow:'hidden', textOverflow:'ellipsis'}}>{sub}</div>}
      </div>
    </div>
  );
}

function PlatformBadge({ p }) {
  if (!p || !["ios","android","web"].includes(p)) return <span className="muted">—</span>;
  const map = { ios: <Icon.apple size={11}/>, android: <Icon.android size={11}/>, web: <Icon.web size={11}/> };
  const label = p==="ios"?"iOS":p==="android"?"Android":"Web";
  return <span className="badge">{map[p]} {label}</span>;
}

function PlanBadge({ plan }) {
  const p = PLANS.find(p=>p.id===plan) || PLANS[0];
  if (plan==="free") return <span className="badge">Free</span>;
  const cls = plan==="starter"?"blue" : plan==="family"?"plum" : "accent";
  return <span className={"badge "+cls}><span className="dot"/>{p.name}</span>;
}

function ProviderBadge({ provider }) {
  if (provider === "google") return <span className="badge blue"><Icon.web size={10}/> Google</span>;
  if (provider === "apple")  return <span className="badge"><Icon.apple size={10}/> Apple</span>;
  if (provider === "email")  return <span className="badge"><Icon.mail size={10}/> Email</span>;
  return <span className="muted" style={{fontSize:11}}>Guest</span>;
}

function Switch({ on, onChange }) {
  return <div className="switch" data-on={on} onClick={()=>onChange && onChange(!on)}/>;
}

function Modal({ open, onClose, title, children, footer }) {
  if (!open) return null;
  return (
    <>
      <div className="drawer-backdrop" onClick={onClose}/>
      <div className="drawer">
        <header>
          <div style={{fontWeight:600}}>{title}</div>
          <div className="spacer"/>
          <button className="btn ghost icon sm" onClick={onClose}><Icon.close size={14}/></button>
        </header>
        <div className="body">{children}</div>
        {footer && <footer>{footer}</footer>}
      </div>
    </>
  );
}

Object.assign(window, { Sparkline, LineChart, BarChart, Donut, KPI, UserCell, PlatformBadge, PlanBadge, ProviderBadge, Switch, Modal, EmptyState });
