/* ============================================================
   MUIY — Monitoring · test detail (the history repository)
   Description · latest · due · trend chart · full history with
   add / edit / delete. Ferritin keeps its rich iron analytics.
   ============================================================ */

/* ---- compact numeric trend chart with optional normal-range band ---- */
function MonTrendChart({ logs, test, height = 132, profile }) {
  const pts = logs.map((l) => ({ date: l.date, v: MON.numVal(l) })).filter((p) => p.v != null).reverse(); // oldest → newest
  if (pts.length < 2) return null;
  const W = 300,H = height,padL = 36,padR = 10,padT = 14,padB = 20;
  const xs = (i, n) => padL + (n <= 1 ? (W - padL - padR) / 2 : i / (n - 1) * (W - padL - padR));
  const vals = pts.map((p) => p.v);
  // Therapy-relative markers (e.g. pre-transfusion Hb) shade their TARGET band,
  // per profile type — not the healthy-adult reference range.
  const tBand = test.therapy_relative && window.CLINICAL && CLINICAL.therapyBand
    ? CLINICAL.therapyBand(test.id, MON.profileType(profile)) : null;
  const nr = tBand ? { low: tBand.low, high: tBand.high } : (test.normal_range || {});
  const bandLabel = tBand ? tBand.label : 'Usual range';
  let dmin = Math.min(...vals),dmax = Math.max(...vals);
  if (nr.low != null) dmin = Math.min(dmin, nr.low);
  if (nr.high != null) dmax = Math.max(dmax, nr.high);
  const span = dmax - dmin || Math.abs(dmax) || 1;
  let min = dmin - span * 0.18,max = dmax + span * 0.18;
  if (min === max) {min -= 1;max += 1;}
  const y = (v) => padT + (1 - (v - min) / (max - min)) * (H - padT - padB);
  const path = pts.map((p, i) => `${i ? 'L' : 'M'} ${xs(i, pts.length).toFixed(1)} ${y(p.v).toFixed(1)}`).join(' ');
  const cat = MON.catMeta(test.category);
  const color = cat.color;
  const bandTop = nr.high != null ? y(Math.min(nr.high, max)) : padT;
  const bandBot = nr.low != null ? y(Math.max(nr.low, min)) : H - padB;
  const ticks = [max, (min + max) / 2, min];
  const fmtT = (v) => Math.abs(v) >= 1000 ? (v / 1000).toFixed(1) + 'k' : Math.round(v * 10) / 10;
  const hasBand = nr.low != null || nr.high != null;
  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" style={{ display: 'block' }}>
      {hasBand && <rect x={padL} y={bandTop} width={W - padL - padR} height={Math.max(0, bandBot - bandTop)} fill="var(--green-wash)" opacity="0.75" />}
      {hasBand && nr.high != null && <text x={W - padR - 2} y={bandTop + 11} fontSize="8.5" fontWeight="800" textAnchor="end" fill="var(--success)">{bandLabel}</text>}
      {ticks.map((tv, i) =>
      <g key={i}>
          <line x1={padL} y1={y(tv)} x2={W - padR} y2={y(tv)} stroke="var(--hairline)" strokeWidth="1" />
          <text x={padL - 5} y={y(tv) + 3} fontSize="8.5" fontWeight="700" textAnchor="end" fill="var(--ink-3)">{fmtT(tv)}</text>
        </g>
      )}
      <path d={path} fill="none" stroke={color} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
      {pts.map((p, i) => <circle key={i} cx={xs(i, pts.length)} cy={y(p.v)} r="3.6" fill="var(--surface)" stroke={color} strokeWidth="2.1" />)}
    </svg>);

}

/* ---- rich ferritin block (ported from the old Trends view) ---- */
function MonFerritinRich({ store }) {
  const series = TC.ferritinSeries(store.data);
  const latest = series[0];
  if (!latest) return null;
  const st = TC.ferritinStatus(latest.value);
  const risk = TC.ferritinRisk(latest.value);
  const ins = TC.ferritinInsight(series, 180);
  return (
    <div style={{ marginTop: 6 }}>
      <div className="card-flat" style={{ padding: 14, marginBottom: 12 }}>
        <div className="eyebrow" style={{ marginBottom: 8 }}>Current iron load</div>
        <div className="row" style={{ alignItems: 'baseline', gap: 8 }}>
          <span className="num" style={{ fontSize: 34, fontWeight: 800, letterSpacing: '-.02em', lineHeight: 1, color: st ? st.color : 'var(--ink)' }}>{Math.round(latest.value).toLocaleString()}</span>
          <span style={{ fontWeight: 800, fontSize: 13, color: 'var(--ink-3)' }}>{MON.unitOf('ferritin')}</span>
          {st && <span className="chip-status" style={{ marginLeft: 'auto', background: st.wash, color: st.color, fontSize: 12 }}><span style={{ width: 7, height: 7, borderRadius: 999, background: st.color }} />{st.note}</span>}
        </div>
        {ins &&
        <div className="body" style={{ marginTop: 11, fontSize: 13, color: 'var(--ink)', lineHeight: 1.55 }}>{ins.narrative}</div>
        }
      </div>
      {risk &&
      <div className="card-flat" style={{ marginBottom: 12, padding: 0, overflow: 'hidden', border: `1.5px solid ${risk.color}`, borderLeft: `5px solid ${risk.color}` }}>
          <div style={{ padding: '13px 15px' }}>
            <div className="row" style={{ gap: 10, alignItems: 'center', marginBottom: 7 }}>
              <div className="leaf" style={{ width: 32, height: 32, flex: 'none', background: risk.wash, color: risk.color, borderRadius: 10 }}><Icon name="warn" size={17} color={risk.color} /></div>
              <div style={{ fontWeight: 800, fontSize: 14, color: risk.color, letterSpacing: '-.01em' }}>{risk.heading}</div>
            </div>
            <div className="body" style={{ fontSize: 12.8, color: 'var(--ink)', lineHeight: 1.5 }}>{risk.body}</div>
          </div>
        </div>
      }
      <div className="card-flat" style={{ padding: '13px 15px', marginBottom: 4 }}>
        <div className="sec-title" style={{ marginBottom: 10, fontSize: 12 }}>Iron burden bands</div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr', gap: '9px 14px' }}>
          {[['var(--success)', 'Low', '< 1,000'], ['var(--warning)', 'Moderate', '1,000–2,500'], ['var(--orange)', 'Elevated', '2,500–5,000'], ['var(--danger)', 'Very high', '5,000–10,000'], ['#B11A22', 'Severe', '> 10,000']].map(([c, label, rng]) =>
          <div key={label} className="row" style={{ gap: 9 }}>
              <span style={{ width: 10, height: 10, borderRadius: 999, background: c, flex: 'none' }} />
              <span style={{ fontSize: 13, fontWeight: 800, color: 'var(--ink)', whiteSpace: 'nowrap' }}>{label}</span>
              <span className="num" style={{ fontSize: 12.5, fontWeight: 700, color: 'var(--ink-3)', marginLeft: 'auto', whiteSpace: 'nowrap' }}>{rng}</span>
            </div>
          )}
        </div>
      </div>
    </div>);

}

/* ---- plain-language "is this high or low — should I worry?" block ----
   Deterministic interpretation from window.RESULTMEANING (no AI). Shown
   whenever there's a latest numeric reading, so a curious patient gets a
   straight answer in context.                                            */
function MonResultMeaning({ test, profile, last }) {
  if (!last || !window.RESULTMEANING) return null;
  const v = MON.numVal(last);
  if (v == null) return null;
  const m = RESULTMEANING.of(test, last.value, profile);
  if (!m) return null;
  const w = m.worry;
  const showGauge = m.pos != null;
  return (
    <div className="card-flat" style={{ padding: 0, overflow: 'hidden', margin: '12px 0 14px', border: `1.5px solid ${m.color}`, borderLeft: `5px solid ${m.color}` }}>
      <div style={{ padding: '14px 15px 6px' }}>
        <div className="eyebrow" style={{ marginBottom: 9 }}>Your latest reading</div>
        <div className="row" style={{ gap: 11, alignItems: 'center' }}>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 5, flex: 'none' }}>
            <span className="num" style={{ fontSize: 30, fontWeight: 800, letterSpacing: '-.02em', lineHeight: 1, color: m.color }}>{last.value}</span>
            {test.unit && <span style={{ fontWeight: 800, fontSize: 12.5, color: 'var(--ink-3)' }}>{test.unit}</span>}
          </div>
          <span className="chip-status" style={{ background: m.wash, color: m.color, fontSize: 12, fontWeight: 800, marginLeft: 'auto', flex: 'none' }}>
            <Icon name={m.arrow} size={13} color={m.color} sw={2.6} />{m.label}
          </span>
        </div>
        <div className="dmeta muted" style={{ marginTop: 6 }}>Measured {TC.fmtDate(last.date)}</div>
      </div>

      {/* where it sits: low — usual — high */}
      {showGauge &&
      <div style={{ padding: '4px 15px 13px' }}>
          <div style={{ position: 'relative', height: 8, borderRadius: 999, background: 'var(--surface-2)', overflow: 'hidden' }}>
            <div style={{ position: 'absolute', left: '33%', width: '34%', top: 0, bottom: 0, background: 'var(--green-wash)' }} />
            <div style={{ position: 'absolute', left: '33%', top: 0, bottom: 0, width: 1.5, background: 'var(--success)', opacity: 0.5 }} />
            <div style={{ position: 'absolute', left: '67%', top: 0, bottom: 0, width: 1.5, background: 'var(--success)', opacity: 0.5 }} />
          </div>
          <div style={{ position: 'relative', height: 0 }}>
            <div style={{ position: 'absolute', top: -13, left: `${Math.round(m.pos * 100)}%`, transform: 'translateX(-50%)', width: 13, height: 13, borderRadius: 999, background: m.color, border: '2.5px solid var(--surface)', boxShadow: 'var(--sh-sm)' }} />
          </div>
          <div className="between" style={{ marginTop: 8 }}>
            <span className="dmeta muted">Lower</span>
            <span className="dmeta" style={{ fontWeight: 800, color: 'var(--success)' }}>{m.range ? m.range.label : 'Usual range'}</span>
            <span className="dmeta muted">Higher</span>
          </div>
        </div>
      }

      {/* what it means */}
      <div style={{ padding: '0 15px 13px' }}>
        <div className="sec-title" style={{ fontSize: 12, marginBottom: 5 }}>What this means</div>
        <div className="body" style={{ fontSize: 13, lineHeight: 1.55, color: 'var(--ink)' }}>{m.meaning}</div>
      </div>

      {/* should you worry */}
      <div style={{ background: w.wash, padding: '12px 15px', display: 'flex', gap: 10, alignItems: 'flex-start' }}>
        <span style={{ width: 9, height: 9, borderRadius: 999, background: w.dot, flex: 'none', marginTop: 5 }} />
        <div style={{ minWidth: 0 }}>
          <div style={{ fontWeight: 800, fontSize: 13, color: w.color }}>{w.label}</div>
          <div className="body" style={{ fontSize: 12.5, lineHeight: 1.5, marginTop: 2, color: 'var(--ink)' }}>{w.text}</div>
        </div>
      </div>
    </div>
  );
}

/* ---- the test detail + result add/edit/delete sheet ---- */
function MonTestDetailBody({ store, test, profile, startAdd, hideHeader }) {
  const logs = store.data.testLogs || [];
  const st = MON.statusOf(test, profile, logs);
  const list = MON.logsFor(test.id, logs);
  const cat = MON.catMeta(test.category);
  const grp = MON.groupOfCat(test.category);
  const isNum = !!test.unit;
  const isFer = test.id === 'ferritin';

  const [val, setVal] = React.useState('');
  const [date, setDate] = React.useState(TC.daysAgoDate(0));
  const [adding, setAdding] = React.useState(startAdd || !list.length);
  const valRef = React.useRef(null);
  // focus the value input WITHOUT scrolling the sheet — keeps the test header
  // ("the card") in view when the detail opens straight into add mode.
  React.useEffect(() => {
    if (adding && valRef.current) valRef.current.focus({ preventScroll: true });
  }, [adding]);
  const [editId, setEditId] = React.useState(null);
  const [eVal, setEVal] = React.useState('');
  const [eDate, setEDate] = React.useState('');

  const G = window.CLINICALGUARD;
  const valNote = G && isNum ? G.analyte(test, val) : null;
  const dupNote = G ? G.duplicateTestLog(logs, test.id, date, null) : null;
  const valBlocked = G ? G.blocks([valNote]) : false;

  const save = () => {
    if (!val.trim() || valBlocked) return;
    store.mutate((d) => {
      d.testLogs = d.testLogs || [];
      const vid = MON.ensureVisit(d, date, test.id);
      d.testLogs.push({ id: TC.uid(), testId: test.id, date, value: val.trim(), unit: test.unit || null, method: 'manual', visitId: vid, notes: null, createdAt: new Date().toISOString() });
    });
    store.showToast(`${test.name} saved`, '✅');
    setVal('');setAdding(false);
  };
  const saveEdit = (id) => {
    if (!eVal.trim()) return;
    store.mutate((d) => {
      const l = (d.testLogs || []).find((x) => x.id === id);
      if (l) {l.value = eVal.trim();if (eDate !== l.date) {l.date = eDate;l.visitId = MON.ensureVisit(d, eDate, l.testId);}}
    });
    store.showToast('Result updated', '✏️');setEditId(null);
  };
  const del = (id) => store.openModal('confirm', { title: 'Delete this result?', message: 'This result will be permanently removed from your history. This cannot be undone.', confirmLabel: 'Delete', onConfirm: () => {store.mutate((d) => {d.testLogs = (d.testLogs || []).filter((l) => l.id !== id);});store.showToast('Result removed', '🗑️');} });

  const rangeText = test.normal_range ?
  `${test.normal_range.low != null ? test.normal_range.low : '—'} – ${test.normal_range.high != null ? test.normal_range.high : '—'}${test.unit ? ' ' + test.unit : ''}` :
  null;

  // Example placeholder anchored to THIS test's expected range (therapy band
  // for therapy-relative markers, else the reference range midpoint) so the
  // hint reflects the test instead of a constant "1200" everywhere.
  const examplePlaceholder = (() => {
    if (!isNum) return 'e.g. Negative';
    const tBand = test.therapy_relative && window.CLINICAL && CLINICAL.therapyBand
      ? CLINICAL.therapyBand(test.id, MON.profileType(profile)) : null;
    const r = tBand || test.normal_range || null;
    let n = null;
    if (r) {
      if (r.low != null && r.high != null) n = (r.low + r.high) / 2;
      else if (r.high != null) n = r.high;
      else if (r.low != null) n = r.low;
    }
    if (n == null) return 'Enter the value';
    const rounded = n >= 10 ? Math.round(n) : n >= 1 ? Math.round(n * 10) / 10 : Math.round(n * 100) / 100;
    return `e.g. ${rounded}`;
  })();

  return (
    <React.Fragment>
      {!hideHeader &&
      <div className="row" style={{ gap: 12, marginBottom: 4 }}>
        <div className="leaf" style={{ width: 44, height: 44, flex: 'none', background: cat.wash, color: cat.color, borderRadius: 14 }}><Icon name={cat.icon} size={20} color={cat.color} fill={cat.icon === 'sparkle' || cat.icon === 'drop' ? cat.color : 'none'} /></div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="h2" style={{ fontSize: 18 }}>{test.name}</div>
          <div className="dmeta muted">{grp ? grp.label : cat.key} · {MON.freqLabel(st.freq)}</div>
        </div>
        {monStatusChip(st)}
      </div>
      }

      <div className="body" style={{ fontSize: 13, lineHeight: 1.5, marginTop: 8 }}>{MON.plainOf(test)}</div>
      {st.freq.note && <MWarn tone="soon">{st.freq.note}</MWarn>}

      {/* is this high or low — and should I worry? (deterministic, not AI) */}
      {!isFer && <MonResultMeaning test={test} profile={profile} last={st.last} />}

      {/* ferritin keeps its rich analytics */}
      {isFer && <MonFerritinRich store={store} />}

      {/* trend chart */}
      {isNum && MON.logsFor(test.id, logs).filter((l) => MON.numVal(l) != null).length >= 2 &&
      <div className="card-flat" style={{ padding: '12px 12px 6px', margin: '14px 0' }}>
          <div className="sec-title" style={{ marginBottom: 4, fontSize: 12, paddingLeft: 2 }}>Trend</div>
          <MonTrendChart logs={list} test={test} profile={profile} />
        </div>
      }

      <div className="card-flat" style={{ padding: '12px 14px', margin: '14px 0', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px 14px' }}>
        <div><div className="eyebrow" style={{ marginBottom: 3 }}>Recommended</div><div style={{ fontWeight: 800, fontSize: 13.5 }}>{MON.freqLabel(st.freq)}</div></div>
        <div><div className="eyebrow" style={{ marginBottom: 3 }}>Last done</div><div style={{ fontWeight: 800, fontSize: 13.5 }}>{st.last ? TC.fmtDate(st.last.date) : 'Never'}</div></div>
        <div><div className="eyebrow" style={{ marginBottom: 3 }}>Next due</div><div style={{ fontWeight: 800, fontSize: 13.5 }}>{st.nextDue ? TC.fmtDate(st.nextDue) : '—'}</div></div>
        {rangeText && <div><div className="eyebrow" style={{ marginBottom: 3 }}>Usual range</div><div style={{ fontWeight: 800, fontSize: 13.5 }}>{rangeText}</div></div>}
        {test.unit && <div><div className="eyebrow" style={{ marginBottom: 3 }}>Unit</div><div style={{ fontWeight: 800, fontSize: 13.5 }}>{test.unit}</div></div>}
      </div>

      {/* add-result form */}
      {adding ?
      <div className="card-flat" style={{ padding: 14, marginBottom: 12 }}>
          <div className="sec-title" style={{ marginBottom: 10, fontSize: 13 }}>Add a result</div>
          <div className="field"><label className="field-label">{isNum ? `Value${test.unit ? ' (' + test.unit + ')' : ''}` : 'Result'}</label>
            <input ref={valRef} className="input" type={isNum ? 'number' : 'text'} step="any" value={val} onChange={(e) => setVal(e.target.value)} placeholder={examplePlaceholder} />
          </div>
          <FieldNote note={valNote} onApplySuggest={valNote && valNote.suggest ? (x) => setVal(x) : undefined} />
          <FieldNote note={dupNote} />
          <div className="field"><label className="field-label">Date</label><input className="input" type="date" value={date} onChange={(e) => setDate(e.target.value)} /></div>
          <div className="row" style={{ gap: 10 }}>
            {list.length > 0 && <button className="btn btn-ghost" style={{ flex: 1 }} onClick={() => setAdding(false)}>Cancel</button>}
            <button className="btn btn-primary" style={{ flex: 1.4, opacity: valBlocked ? 0.5 : 1, pointerEvents: valBlocked ? 'none' : 'auto' }} onClick={save}>Save result</button>
          </div>
          <MedicalDisclaimer style={{ marginTop: 12 }} />
        </div> :

      <button className="btn btn-primary" style={{ width: '100%', marginBottom: 12 }} onClick={() => setAdding(true)}><Icon name="plus" size={18} color="#fff" sw={2.6} /> Add result</button>
      }

      {/* history */}
      {list.length > 0 &&
      <div className="detail-sec">
          <SLabel>History · {list.length}</SLabel>
          <div style={{ display: 'flex', flexDirection: 'column' }}>
            {list.slice(0, 12).map((l) => {
            const flag = test.normal_range ? MON.valueFlag(test, l.value, profile) : null;
            const visit = (store.data.visits || []).find((v) => v.id === l.visitId);
            const editing = editId === l.id;
            return (
              <div key={l.id} className="drow" style={{ padding: '11px 0', display: 'block' }}>
                  {editing ?
                <div className="row" style={{ gap: 8, alignItems: 'center' }}>
                      <input className="input" value={eVal} onChange={(e) => setEVal(e.target.value)} style={{ flex: 1.1 }} autoFocus />
                      <input className="input" type="date" value={eDate} onChange={(e) => setEDate(e.target.value)} style={{ flex: 1.3 }} />
                      <button className="icon-btn" style={{ width: 36, height: 36, flex: 'none', background: 'var(--orange)' }} onClick={() => saveEdit(l.id)} aria-label="Save"><Icon name="check" size={16} color="#fff" sw={2.6} /></button>
                    </div> :

                <div className="row" style={{ gap: 8 }}>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div className="row" style={{ gap: 7, alignItems: 'baseline' }}>
                          <span className="num" style={{ fontSize: 15, fontWeight: 800, color: flag && flag.dir !== 'normal' ? flag.color : 'var(--ink)' }}>{l.value}</span>
                          {test.unit && <span className="body" style={{ fontSize: 11.5 }}>{test.unit}</span>}
                          {flag && flag.dir !== 'normal' && <span className="chip-status" style={{ background: flag.wash, color: flag.color, padding: '2px 8px', fontSize: 10.5 }}>{flag.frame === 'therapeutic' ? flag.label : flag.dir}</span>}
                        </div>
                        <div className="dmeta muted">{TC.fmtDate(l.date)}{visit ? ` · ${MON.visitTypeMeta(visit.type).label}` : ''}{l.method === 'scan' ? ' · from report' : ''}</div>
                      </div>
                      <button className="icon-btn" style={{ width: 32, height: 32, flex: 'none', background: 'var(--surface-2)' }} onClick={() => {setEditId(l.id);setEVal(l.value);setEDate(l.date);}} aria-label="Edit result"><Icon name="edit" size={14} /></button>
                      <button className="icon-btn" style={{ width: 32, height: 32, flex: 'none', background: 'var(--surface-2)' }} onClick={() => del(l.id)} aria-label="Delete result"><Icon name="trash" size={14} color="var(--waiting)" /></button>
                    </div>
                }
                </div>);

          })}
          </div>
        </div>
      }
    </React.Fragment>);

}

function MonTestSheet({ store, close, test, profile, startAdd }) {
  return (
    <MSheet onClose={close}>
      <MonTestDetailBody store={store} test={test} profile={profile} startAdd={startAdd} />
    </MSheet>);

}

Object.assign(window, { MonTrendChart, MonFerritinRich, MonResultMeaning, MonTestDetailBody, MonTestSheet });