/* Shared UI primitives */

const Avatar = ({ p, size = 40, ring }) => {
  const initials = (p.first[0] + p.last[0]).toUpperCase();
  const bg = `hsl(${p.avatarHue} 42% 46%)`;
  return (
    <div className="avatar" style={{
      width: size, height: size, background: bg, fontSize: size * 0.38,
      boxShadow: ring ? `0 0 0 3px ${ring}` : "none",
    }}>{initials}</div>
  );
};

const AcuityDot = ({ level }) => <span className={`dot-acuity acuity-${level}`} />;

const Badge = ({ kind = "neutral", children, icon }) => (
  <span className={`badge badge-${kind}`}>
    {icon && <Icon name={icon} size={12} />}
    {children}
  </span>
);

const codeBadge = (code) => {
  if (!code) return null;
  if (code.startsWith("Full")) return <Badge kind="good">{code}</Badge>;
  return <Badge kind="critical" icon="alert">{code}</Badge>;
};

/* ---- Sparkline (inline trend) ---- */
const Sparkline = ({ data, w = 86, h = 26, color = "var(--primary)", fill = true }) => {
  if (!data || !data.length) return null;
  const min = Math.min(...data), max = Math.max(...data);
  const rng = max - min || 1;
  const pts = data.map((v, i) => [
    (i / (data.length - 1)) * w,
    h - 3 - ((v - min) / rng) * (h - 6),
  ]);
  const d = pts.map((p, i) => (i ? "L" : "M") + p[0].toFixed(1) + " " + p[1].toFixed(1)).join(" ");
  const area = d + ` L${w} ${h} L0 ${h} Z`;
  return (
    <svg width={w} height={h} style={{ display: "block", overflow: "visible" }}>
      {fill && <path d={area} fill={color} opacity="0.10" />}
      <path d={d} fill="none" stroke={color} strokeWidth="1.8" strokeLinejoin="round" strokeLinecap="round" />
      <circle cx={pts[pts.length - 1][0]} cy={pts[pts.length - 1][1]} r="2.6" fill={color} />
    </svg>
  );
};

/* ---- Larger line chart with axis (for vitals / labs) ---- */
const LineChart = ({ series, labels, w = 640, h = 200, unit = "", refRange }) => {
  const pad = { l: 38, r: 14, t: 14, b: 26 };
  const iw = w - pad.l - pad.r, ih = h - pad.t - pad.b;
  const all = series.flatMap((s) => s.data);
  let min = Math.min(...all), max = Math.max(...all);
  if (refRange) { min = Math.min(min, refRange[0]); max = Math.max(max, refRange[1]); }
  const pd = (max - min) * 0.12 || 1; min -= pd; max += pd;
  const rng = max - min || 1;
  const x = (i, n) => pad.l + (n <= 1 ? iw / 2 : (i / (n - 1)) * iw);
  const y = (v) => pad.t + ih - ((v - min) / rng) * ih;
  const ticks = 4;
  return (
    <svg width="100%" viewBox={`0 0 ${w} ${h}`} style={{ display: "block" }}>
      {[...Array(ticks + 1)].map((_, i) => {
        const val = min + (rng * i) / ticks;
        const yy = y(val);
        return (
          <g key={i}>
            <line x1={pad.l} y1={yy} x2={w - pad.r} y2={yy} stroke="var(--hairline)" />
            <text x={pad.l - 7} y={yy + 3.5} textAnchor="end" fontSize="10" fill="var(--text-3)" className="mono">{val.toFixed(rng < 6 ? 1 : 0)}</text>
          </g>
        );
      })}
      {refRange && (
        <rect x={pad.l} y={y(refRange[1])} width={iw} height={Math.max(0, y(refRange[0]) - y(refRange[1]))}
          fill="var(--good)" opacity="0.07" />
      )}
      {labels.map((lb, i) => (
        <text key={i} x={x(i, labels.length)} y={h - 8} textAnchor="middle" fontSize="10" fill="var(--text-3)" className="mono">{lb}</text>
      ))}
      {series.map((s, si) => {
        const dd = s.data.map((v, i) => (i ? "L" : "M") + x(i, s.data.length) + " " + y(v)).join(" ");
        return (
          <g key={si}>
            <path d={dd} fill="none" stroke={s.color} strokeWidth="2.2" strokeLinejoin="round" strokeLinecap="round" />
            {s.data.map((v, i) => <circle key={i} cx={x(i, s.data.length)} cy={y(v)} r="3" fill="#fff" stroke={s.color} strokeWidth="2" />)}
          </g>
        );
      })}
    </svg>
  );
};

/* ---- Card wrapper ---- */
const Card = ({ title, icon, action, children, className = "", bodyClass = "", noBody }) => (
  <div className={`card ${className}`}>
    {title && (
      <div className="card-h">
        <h3>{icon && <span className="ch-ic"><Icon name={icon} size={16} /></span>}{title}</h3>
        <div className="spacer" />
        {action}
      </div>
    )}
    {noBody ? children : <div className={`card-b ${bodyClass}`}>{children}</div>}
  </div>
);

/* ---- value with trend arrow ---- */
const TrendVal = ({ vals }) => {
  if (!vals || vals.length < 2) return null;
  const a = vals[vals.length - 2], b = vals[vals.length - 1];
  if (a === b) return <span className="muted" style={{ fontSize: 11 }}>→</span>;
  const up = b > a;
  return <span style={{ color: up ? "var(--critical)" : "var(--info)", fontSize: 11, fontWeight: 700 }}>{up ? "▲" : "▼"}</span>;
};

Object.assign(window, { Avatar, AcuityDot, Badge, codeBadge, Sparkline, LineChart, Card, TrendVal });
