/* MedBridge shared components */

const { useState: useStateMB, useEffect: useEffectMB, useRef: useRefMB } = React;

/* animated number */
function useCountUp(target, dur = 900, dec = 0) {
  const [v, setV] = useStateMB(0);
  useEffectMB(() => {
    let raf, start, done = false;
    const tick = (t) => {
      if (!start) start = t;
      const p = Math.min(1, (t - start) / dur);
      const e = 1 - Math.pow(1 - p, 3);
      setV(target * e);
      if (p < 1) raf = requestAnimationFrame(tick);
      else { done = true; setV(target); }
    };
    raf = requestAnimationFrame(tick);
    // guarantee the final value even if rAF is throttled/paused (e.g. backgrounded)
    const safety = setTimeout(() => { if (!done) setV(target); }, dur + 120);
    return () => { cancelAnimationFrame(raf); clearTimeout(safety); };
  }, [target]);
  return dec ? v.toFixed(dec) : Math.round(v);
}

const scoreColor = (s) => (s >= 88 ? "var(--mb-good)" : s >= 62 ? "var(--mb-warn)" : "var(--mb-crit)");

/* radial gauge */
function Gauge({ value, size = 168, stroke = 14, label = "Completeness", sub }) {
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const v = useCountUp(value, 1000);
  const off = c - (v / 100) * c;
  const col = scoreColor(value);
  return (
    <div className="gauge-wrap" style={{ 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="var(--surface-3)" strokeWidth={stroke} />
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={col} strokeWidth={stroke}
          strokeDasharray={c} strokeDashoffset={off} strokeLinecap="round"
          style={{ transition: "stroke-dashoffset .25s linear" }} />
      </svg>
      <div className="gauge-center">
        <div className="gv" style={{ color: col }}>{v}<span style={{ fontSize: size * 0.16 }}>%</span></div>
        <div className="gl">{label}</div>
        {sub && <div style={{ fontSize: 11, color: "var(--text-3)", marginTop: 3 }}>{sub}</div>}
      </div>
    </div>
  );
}

/* score pill */
function ScorePill({ score, showWord }) {
  const cls = window.MB.scoreClass(score);
  return <span className={`score-pill sp-${cls}`}>{score}%{showWord && <span style={{ fontWeight: 600, opacity: .85 }}>· {window.MB.scoreWord(score)}</span>}</span>;
}

/* mini 8-field strip */
function FieldStrip({ fields }) {
  return (
    <span className="field-strip" title="8-field completeness">
      {window.MB.FIELDS.map((f) => {
        const on = !!fields[f.key];
        return <i key={f.key} className={on ? "fs-on" : "fs-off" + (f.critical ? " crit" : "")} title={f.label + (on ? ": present" : ": ABSENT")} />;
      })}
    </span>
  );
}

/* full 8-field grid */
function FieldGrid({ fields }) {
  return (
    <div className="field-grid">
      {window.MB.FIELDS.map((f) => {
        const val = fields[f.key];
        const present = !!val;
        const critMiss = f.critical && !present;
        return (
          <div key={f.key} className={`fieldcell ${present ? "fc-present" : "fc-absent"} ${critMiss ? "fc-critical-missing" : ""}`}>
            <div className="fc-top">
              <span className="fc-ic"><Icon name={present ? f.icon : "x"} size={15} /></span>
              {present ? <Icon name="check" size={15} style={{ color: "var(--mb-good)" }} />
                : <span className="badge badge-critical" style={{ height: 17, fontSize: 10 }}>{f.critical ? "CRITICAL" : "Missing"}</span>}
            </div>
            <div className="fc-name">{f.label}</div>
            <div className="fc-val">{present ? val : `No ${f.code} data received`}</div>
          </div>
        );
      })}
    </div>
  );
}

/* KPI tile */
function Kpi({ label, icon, value, unit, sub, delta, deltaDir, spark, sparkColor, accent }) {
  return (
    <div className="kpi">
      <div className="kpi-lab"><Icon name={icon} size={14} style={{ color: accent || "var(--primary)" }} />{label}</div>
      <div className="kpi-val" style={accent ? { color: accent } : null}>{value}{unit && <small>{unit}</small>}</div>
      {(sub || delta) && (
        <div className="kpi-sub">
          {delta && <span className={deltaDir === "up" ? "delta-up" : "delta-down"}>{deltaDir === "up" ? "▲" : "▼"} {delta}</span>}
          {sub}
        </div>
      )}
      {spark && <div className="kpi-spark"><Sparkline data={spark} color={sparkColor || "var(--primary)"} w={68} h={26} /></div>}
    </div>
  );
}

/* horizontal bar row */
function BarRow({ label, value, max, suffix = "", color, sub, onClick }) {
  const [w, setW] = useStateMB(0);
  useEffectMB(() => { const t = setTimeout(() => setW((value / max) * 100), 60); return () => clearTimeout(t); }, [value, max]);
  return (
    <div className="row gap12" style={{ padding: "9px 0", cursor: onClick ? "pointer" : "default" }} onClick={onClick}>
      <div style={{ width: 188, flexShrink: 0, paddingRight: 8 }}>
        <div className="fw6" style={{ fontSize: 12.5, lineHeight: 1.25 }}>{label}</div>
        {sub && <div className="muted" style={{ fontSize: 11 }}>{sub}</div>}
      </div>
      <div className="hbar-track"><div className="hbar-fill" style={{ width: w + "%", background: color }} /></div>
      <div className="mono fw7" style={{ width: 64, textAlign: "right", fontSize: 13, color }}>{value}{suffix}</div>
    </div>
  );
}

/* acuity dot reuse */
function AcuityDotMB({ level }) {
  const c = { critical: "var(--mb-crit)", watch: "var(--mb-warn)", stable: "var(--mb-good)" }[level] || "var(--text-3)";
  return <span className="sdot" style={{ background: c, boxShadow: `0 0 0 3px color-mix(in srgb, ${c} 16%, transparent)` }} />;
}

/* route badge */
function RouteBadge({ route }) {
  const map = {
    "Inter-provincial medevac": ["purple", "send"],
    "Inter-facility": ["info", "arrowUp"],
    "Intra-hospital": ["neutral", "refresh"],
    "Hospital → LTC": ["neutral", "bed"],
  };
  const [k, ic] = map[route] || ["neutral", "arrowUp"];
  return <span className={`badge badge-${k}`}><Icon name={ic} size={11} />{route}</span>;
}

Object.assign(window, { useCountUp, scoreColor, Gauge, ScorePill, FieldStrip, FieldGrid, Kpi, BarRow, AcuityDotMB, RouteBadge });
