// ═══════════════════════════════════════════════════════════════
// inventory-controlled.jsx — the controlled-substance drawer (Step 8)
// ═══════════════════════════════════════════════════════════════
//
// WHAT THIS IS (in plain English):
// Two screens for the same drawer, deliberately kept apart:
//
//   The card on today's schedule, where the OR staff are. At the end of the
//   day it asks for two things — a count of what is physically in the
//   drawer, and, for any dose that was half a tablet, someone to witness
//   that the other half was destroyed. The count is BLIND on purpose: no
//   expected number is shown, because a number on the screen turns a count
//   into a confirmation. Two names go on it, the person counting and a
//   witness, both picked from the real staff list.
//
//   The Stock Room report, where the comparison happens afterwards. What
//   the charts say was given, what the system thinks is left, what was
//   counted, and the difference. Plus the day's waste log, and a CSV of the
//   lot to keep.
//
// Nothing is corrected automatically. If the count doesn't match, that is a
// finding for a person to explain, not something for software to paper over
// by quietly rewriting the stock figure.
// ═══════════════════════════════════════════════════════════════

const csToday = () => new Date().toLocaleDateString('en-CA', { timeZone: 'America/Detroit' });
const csTime = (iso) => (iso ? new Date(iso).toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' }) : '');

async function csFetchDay(date) {
  const r = await fetch('/api/inventory/controlled?date=' + encodeURIComponent(date), { headers: InvApi.headers() });
  const b = await r.json().catch(() => ({}));
  if (!r.ok) throw new Error(b.error || 'Could not read the controlled-substance day');
  return b;
}
async function csFetchStaff() {
  const r = await fetch('/api/auth/staff', { headers: InvApi.headers() });
  const b = await r.json().catch(() => ({}));
  return (b && b.staff) || [];
}
// The counts and waste records live in the `cs_counts` drawer. Both are
// append-only: a recount leaves the earlier count on the record.
async function csAppend(patch) {
  for (let attempt = 0; attempt < 4; attempt++) {
    const cur = await InvApi.get('cs_counts');
    const data = cur.data || {};
    const next = {
      counts: [...(data.counts || []), ...(patch.counts || [])],
      waste: [...(data.waste || []), ...(patch.waste || [])],
    };
    const r = await InvApi.save('cs_counts', next, cur.version);
    if (r.ok) return true;
    if (!r.conflict) throw new Error('Could not save — check the connection and try again.');
  }
  throw new Error('Someone else was saving at the same time. Try once more.');
}

function CsStaffPicker({ staff, value, onChange, exclude, placeholder }) {
  return (
    <select value={value || ''} onChange={(e) => onChange(e.target.value)} style={{ minWidth: 170, maxWidth: 240 }}>
      <option value="">{placeholder || 'Pick a witness…'}</option>
      {staff.filter((s) => s.name && s.name !== exclude).map((s) => <option key={s.id} value={s.name}>{s.name}</option>)}
    </select>
  );
}

// ─── The card on today's schedule ────────────────────────────────
function CsDayCard({ me, onToast }) {
  const date = csToday();
  const [day, setDay] = invUseState(null);
  const [staff, setStaff] = invUseState([]);
  const [entries, setEntries] = invUseState({});      // productId → typed count
  const [witness, setWitness] = invUseState('');
  const [wasteWitness, setWasteWitness] = invUseState({});
  const [busy, setBusy] = invUseState(false);
  const [err, setErr] = invUseState('');
  const [recounting, setRecounting] = invUseState(false);
  const myName = (me && (me.name || me.email)) || '';

  const load = invUseCallback(() => {
    csFetchDay(date).then(setDay).catch((e) => setErr(e.message));
  }, [date]);
  invUseEffect(() => { load(); csFetchStaff().then(setStaff).catch(() => {}); }, [load]);

  if (err) return <div className="card"><div className="card-body" style={{ color: 'var(--red)' }}>⚠️ {err}</div></div>;
  if (!day) return null;
  if (!day.drugs.length) return null; // nothing in the catalog is marked controlled

  const saveCount = async () => {
    const rows = day.drugs
      .filter((d) => entries[d.productId] !== undefined && entries[d.productId] !== '')
      .map((d) => ({ date, productId: d.productId, drug: d.description, qty: Number(entries[d.productId]), countedBy: myName, witness, at: new Date().toISOString() }));
    if (!rows.length) { onToast && onToast('⚠️ Enter a count first.', 'error'); return; }
    if (!witness) { onToast && onToast('⚠️ A witness has to sign the count.', 'error'); return; }
    setBusy(true);
    try {
      await csAppend({ counts: rows });
      InvApi.audit('INV_CS_COUNT', `Controlled substances counted for ${date} by ${myName}, witnessed by ${witness}: ${rows.map((r) => `${r.drug} ${r.qty}`).join('; ')}`);
      onToast && onToast('Count recorded.');
      setEntries({}); setWitness(''); setRecounting(false);
      load();
    } catch (e) { onToast && onToast('⚠️ ' + e.message, 'error'); }
    setBusy(false);
  };

  const recordWaste = async (d) => {
    const w = wasteWitness[d.key];
    if (!w) { onToast && onToast('⚠️ A witness has to sign the destruction.', 'error'); return; }
    setBusy(true);
    try {
      await csAppend({ waste: [{ key: d.key, date, productId: d.productId, description: d.description, patientId: d.patientId, patientName: d.patientName, medName: d.medName, doseMg: d.doseMg, tablets: d.tablets, wasteMg: d.wasteMg, recordedBy: myName, witness: w, at: new Date().toISOString() }] });
      InvApi.audit('INV_CS_WASTE', `${d.wasteMg} mg ${d.medName} destroyed (${d.patientName}), recorded by ${myName}, witnessed by ${w}`);
      onToast && onToast('Destruction recorded.');
      load();
    } catch (e) { onToast && onToast('⚠️ ' + e.message, 'error'); }
    setBusy(false);
  };

  const pending = recounting ? day.drugs : day.drugs.filter((d) => d.counted == null);
  return (
    <div className="card" style={{ marginTop: 16 }}>
      <div className="card-header">Controlled substances — end of day</div>
      <div className="card-body">
        {day.wasteDue.length > 0 && (
          <div style={{ marginBottom: 16 }}>
            <div style={{ fontWeight: 700, fontSize: '0.82rem', color: 'var(--red)', textTransform: 'uppercase' }}>Part tablets to account for ({day.wasteDue.length})</div>
            <div style={{ fontSize: '0.8rem', color: 'var(--gray-600)', margin: '4px 0 8px' }}>A whole tablet left the drawer; only part of it was given. The rest has to be witnessed as destroyed.</div>
            <table style={{ width: '100%', borderCollapse: 'collapse' }}>
              <tbody>
                {day.wasteDue.map((d) => (
                  <tr key={d.key}>
                    <td style={invCell}>{d.patientName || d.patientId}</td>
                    <td style={invCell}>{d.medName} {d.doseMg} mg given{d.at ? ` at ${d.at}` : ''}</td>
                    <td style={{ ...invCell, fontWeight: 600, color: 'var(--red)' }}>{d.wasteMg} mg destroyed</td>
                    <td style={invCell}><CsStaffPicker staff={staff} value={wasteWitness[d.key]} exclude={myName} onChange={(v) => setWasteWitness({ ...wasteWitness, [d.key]: v })} /></td>
                    <td style={invCell}><button className="btn btn-sm btn-primary" disabled={busy} onClick={() => recordWaste(d)}>Record</button></td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}

        <div style={{ fontWeight: 700, fontSize: '0.82rem', color: 'var(--gray-600)', textTransform: 'uppercase' }}>Drawer count</div>
        <div style={{ fontSize: '0.8rem', color: 'var(--gray-600)', margin: '4px 0 8px' }}>Count what is actually in the drawer and enter it. The system's figure is deliberately not shown here — the Stock Room compares them afterwards.</div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <tbody>
            {day.drugs.map((d) => (
              <tr key={d.productId}>
                <td style={invCell}>{d.description}</td>
                <td style={{ ...invCell, width: 150 }}>
                  {d.counted != null && !recounting
                    ? <span style={{ color: 'var(--green)', fontWeight: 600 }}>✓ {d.counted} counted</span>
                    : <input type="number" min="0" step="1" value={entries[d.productId] === undefined ? '' : entries[d.productId]}
                        onChange={(e) => setEntries({ ...entries, [d.productId]: e.target.value })} placeholder="Count" style={{ width: 110 }} />}
                </td>
                <td style={{ ...invCell, fontSize: '0.76rem', color: 'var(--gray-500)' }}>
                  {d.counted != null ? `${d.countedBy}${d.witness ? ' · witnessed by ' + d.witness : ''} · ${csTime(d.countedAt)}${d.recounts ? ` · recounted ${d.recounts}×` : ''}` : ''}
                </td>
              </tr>
            ))}
          </tbody>
        </table>

        {pending.length > 0 && (
          <div style={{ display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap', marginTop: 12 }}>
            <span style={{ fontSize: '0.82rem', color: 'var(--gray-600)' }}>Counted by <strong>{myName}</strong>, witnessed by</span>
            <CsStaffPicker staff={staff} value={witness} exclude={myName} onChange={setWitness} />
            <button className="btn btn-primary btn-sm" disabled={busy} onClick={saveCount}>Save count</button>
          </div>
        )}
        {pending.length === 0 && day.drugs.length > 0 && (
          <div style={{ marginTop: 12, color: 'var(--green)', fontWeight: 600, fontSize: '0.86rem' }}>
            ✓ Everything in the drawer has been counted for today.
            {/* a recount is a new count on the record, not an edit of the old one */}
            <button className="btn btn-outline btn-sm" style={{ marginLeft: 10 }} onClick={() => { setEntries({}); setRecounting(true); }}>Recount</button>
          </div>
        )}
      </div>
    </div>
  );
}

// ─── The Stock Room report ───────────────────────────────────────
function InvControlled() {
  const [date, setDate] = invUseState(csToday);
  const [day, setDay] = invUseState(null);
  const [err, setErr] = invUseState('');
  invUseEffect(() => { setDay(null); setErr(''); csFetchDay(date).then(setDay).catch((e) => setErr(e.message)); }, [date]);

  const exportCsv = () => {
    if (!day) return;
    const rows = [['Date', 'Drug', 'System on hand', 'Counted', 'Difference', 'Tablets pulled', 'Given (mg)', 'Destroyed (mg)', 'Counted by', 'Witness', 'Counted at']];
    day.drugs.forEach((d) => rows.push([date, d.description, d.onHand, d.counted == null ? '' : d.counted, d.variance == null ? '' : d.variance, d.tabletsPulled, d.administeredMg, d.wastedMg, d.countedBy, d.witness, d.countedAt]));
    rows.push([]);
    rows.push(['Destruction log']);
    rows.push(['Date', 'Patient', 'Drug', 'Given (mg)', 'Destroyed (mg)', 'Recorded by', 'Witness', 'At']);
    (day.wasteToday || []).forEach((w) => rows.push([w.date, w.patientName, w.medName, w.doseMg, w.wasteMg, w.recordedBy, w.witness, w.at]));
    const csv = rows.map((r) => r.map((c) => `"${String(c == null ? '' : c).replace(/"/g, '""')}"`).join(',')).join('\n');
    const a = document.createElement('a');
    a.href = 'data:text/csv;charset=utf-8,' + encodeURIComponent(csv);
    a.download = `controlled_substances_${date}.csv`;
    a.click();
  };

  if (err) return <div className="card"><div className="card-body" style={{ color: 'var(--red)' }}>⚠️ {err}</div></div>;
  return (
    <div>
      <p style={{ fontSize: '0.85rem', color: 'var(--gray-600)', maxWidth: 760 }}>
        What the charts say was given, what the system thinks is left, and what was actually counted at the drawer. A count that doesn't match is left standing as a finding — nothing here rewrites stock to make it agree.
      </p>
      <div style={{ display: 'flex', gap: 12, alignItems: 'flex-end', flexWrap: 'wrap', marginBottom: 12 }}>
        <InvField label="Day"><input type="date" value={date} onChange={(e) => setDate(e.target.value)} /></InvField>
        <span style={{ flex: 1 }} />
        {day && <button className="btn btn-outline btn-sm" onClick={exportCsv}>↓ Export the day (CSV)</button>}
      </div>
      {!day ? <div style={{ color: 'var(--gray-500)', padding: 12 }}>Reading the day…</div> : (
        <div>
          {!day.counted && <div style={{ color: 'var(--amber)', fontWeight: 600, marginBottom: 10, fontSize: '0.86rem' }}>⚠ No count has been entered for {date} yet.</div>}
          {day.mismatches > 0 && <div style={{ color: 'var(--red)', fontWeight: 700, marginBottom: 10, fontSize: '0.86rem' }}>⚠ {day.mismatches} drug(s) counted differently from what the system expects.</div>}
          {day.counted > 0 && day.mismatches === 0 && day.allCounted && <div style={{ color: 'var(--green)', fontWeight: 600, marginBottom: 10, fontSize: '0.86rem' }}>✓ Everything counted matches.</div>}
          <div className="card" style={{ margin: 0 }}>
            <div className="tbl-wrap" style={{ overflowX: 'auto' }}>
              <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                <thead><tr>
                  <th style={invTh}>Drug</th>
                  <th style={{ ...invTh, textAlign: 'right' }}>System</th>
                  <th style={{ ...invTh, textAlign: 'right' }}>Counted</th>
                  <th style={{ ...invTh, textAlign: 'right' }}>Difference</th>
                  <th style={{ ...invTh, textAlign: 'right' }}>Pulled today</th>
                  <th style={{ ...invTh, textAlign: 'right' }}>Given</th>
                  <th style={{ ...invTh, textAlign: 'right' }}>Destroyed</th>
                  <th style={invTh}>Signed</th>
                </tr></thead>
                <tbody>
                  {day.drugs.map((d) => (
                    <tr key={d.productId}>
                      <td style={invCell}>{d.description}</td>
                      <td style={{ ...invCell, textAlign: 'right' }}>{invFmtQty(d.onHand)}</td>
                      <td style={{ ...invCell, textAlign: 'right', fontWeight: 600 }}>{d.counted == null ? <span style={{ color: 'var(--gray-400)' }}>—</span> : d.counted}</td>
                      <td style={{ ...invCell, textAlign: 'right', fontWeight: 700, color: d.variance == null ? 'var(--gray-400)' : d.variance === 0 ? 'var(--green)' : 'var(--red)' }}>
                        {d.variance == null ? '—' : d.variance === 0 ? '✓' : (d.variance > 0 ? '+' : '') + d.variance}
                      </td>
                      <td style={{ ...invCell, textAlign: 'right' }}>{d.tabletsPulled || '—'}</td>
                      <td style={{ ...invCell, textAlign: 'right' }}>{d.administeredMg ? d.administeredMg + ' mg' : '—'}</td>
                      <td style={{ ...invCell, textAlign: 'right', color: d.wastedMg ? 'var(--red)' : undefined }}>{d.wastedMg ? d.wastedMg + ' mg' : '—'}</td>
                      <td style={{ ...invCell, fontSize: '0.76rem', color: 'var(--gray-600)' }}>{d.countedBy}{d.witness ? ` · ${d.witness}` : ''}{d.recounts ? ` · recounted ${d.recounts}×` : ''}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>

          {day.wasteDue.length > 0 && (
            <div style={{ marginTop: 14, color: 'var(--red)', fontSize: '0.85rem', fontWeight: 600 }}>
              ⚠ {day.wasteDue.length} part-tablet dose(s) still waiting for a witness on the destroyed remainder — that's done on the day's schedule screen.
            </div>
          )}
          {(day.wasteToday || []).length > 0 && (
            <div style={{ marginTop: 14 }}>
              <div style={{ fontWeight: 700, fontSize: '0.8rem', color: 'var(--gray-600)', textTransform: 'uppercase' }}>Destruction log</div>
              <div className="card" style={{ margin: '6px 0 0' }}>
                <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                  <tbody>
                    {day.wasteToday.map((w) => (
                      <tr key={w.key}>
                        <td style={invCell}>{w.patientName}</td>
                        <td style={invCell}>{w.medName} — {w.doseMg} mg given, <strong>{w.wasteMg} mg destroyed</strong></td>
                        <td style={{ ...invCell, fontSize: '0.78rem', color: 'var(--gray-600)' }}>{w.recordedBy} · witnessed by {w.witness} · {csTime(w.at)}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

window.SurgSuiteControlled = { DayCard: CsDayCard };
