/* Ward Desk — one fixture for the whole product.
   Every screen reads these arrays; no screen writes a second literal to match.
   The clock is frozen so the derived flags are reproducible: Tuesday 17 March
   2026, 09:20 on the Beaumont ward.

   The notes, the feed and the notifications are authored AGAINST these records:
   a note that names a bed wait, a consent or a stock line agrees with that
   record's status and timeline at the moment it was written. */

const HD_NOW = Date.parse("2026-03-17T09:20:00Z");
const hoursAgo = (h) => HD_NOW - h * HOUR_MS;
const hoursOn = (h) => HD_NOW + h * HOUR_MS;
const daysAgo = (d) => HD_NOW - d * DAY_MS;
const dayAt = (offset, hour, minute) => {
  const d = new Date(HD_NOW + offset * DAY_MS);
  d.setHours(hour, minute || 0, 0, 0);
  return d.getTime();
};

const HD_HOSPITAL = {
  name: "Halden General Hospital",
  short: "Halden General",
  trust: "Halden and Westmere NHS Trust",
  timezone: "Europe/London",
  recordsEmail: "records@haldengeneral.nhs.uk",
  retentionYears: 8,
};

const HD_SIGNED_IN = "stf_03";

/* ── Staff: doctors and every other employee in one list ─────────────────── */
const STAFF = [
  { id: "stf_01", name: "Adaeze Okonkwo", email: "a.okonkwo@haldengeneral.nhs.uk", family: "medical", jobTitle: "Consultant general surgeon", specialty: "general_surgery", staffRole: "clinician", status: "active", ward: "beaumont", avatar: "../../assets/img/avatar-f-3.jpg", startedAt: daysAgo(2190), phone: "ext 4402", gmc: "GMC 7104882", timezone: "Europe/London" },
  { id: "stf_02", name: "Rasmus Feld", email: "r.feld@haldengeneral.nhs.uk", family: "medical", jobTitle: "Consultant cardiologist", specialty: "cardiology", staffRole: "clinician", status: "active", ward: "corvid", avatar: "../../assets/img/avatar-m-2.jpg", startedAt: daysAgo(1560), phone: "ext 4419", gmc: "GMC 6620145", timezone: "Europe/London" },
  { id: "stf_03", name: "Imogen Vance", email: "i.vance@haldengeneral.nhs.uk", family: "nursing", jobTitle: "Ward manager", specialty: null, staffRole: "ward_manager", status: "active", ward: "beaumont", avatar: "../../assets/img/avatar-f-5.jpg", startedAt: daysAgo(1204), phone: "ext 4380", gmc: null, timezone: "Europe/London" },
  { id: "stf_04", name: "Tobias Lenz", email: "t.lenz@haldengeneral.nhs.uk", family: "medical", jobTitle: "Registrar, acute medicine", specialty: "acute_medicine", staffRole: "clinician", status: "active", ward: "linden", avatar: "../../assets/img/avatar-m-4.jpg", startedAt: daysAgo(640), phone: "ext 4455", gmc: "GMC 7391066", timezone: "Europe/London" },
  { id: "stf_05", name: "Priya Raghunathan", email: "p.raghunathan@haldengeneral.nhs.uk", family: "pharmacy", jobTitle: "Lead pharmacist", specialty: null, staffRole: "pharmacist", status: "active", ward: null, avatar: "../../assets/img/avatar-f-7.jpg", startedAt: daysAgo(1830), phone: "ext 4210", gmc: null, timezone: "Europe/London" },
  { id: "stf_06", name: "Marek Solis", email: "m.solis@haldengeneral.nhs.uk", family: "nursing", jobTitle: "Staff nurse", specialty: null, staffRole: "clinician", status: "active", ward: "linden", avatar: "../../assets/img/avatar-m-6.jpg", startedAt: daysAgo(410), phone: "ext 4391", gmc: null, timezone: "Europe/London" },
  { id: "stf_07", name: "Hanne Dahl", email: "h.dahl@haldengeneral.nhs.uk", family: "admin", jobTitle: "Theatre coordinator", specialty: null, staffRole: "coordinator", status: "active", ward: null, avatar: "../../assets/img/avatar-f-9.jpg", startedAt: daysAgo(980), phone: "ext 4501", gmc: null, timezone: "Europe/London" },
  { id: "stf_08", name: "Yusuf Baraka", email: "y.baraka@haldengeneral.nhs.uk", family: "imaging", jobTitle: "Radiographer", specialty: "radiology", staffRole: "coordinator", status: "active", ward: null, avatar: "../../assets/img/avatar-m-9.jpg", startedAt: daysAgo(720), phone: "ext 4622", gmc: null, timezone: "Europe/London" },
  { id: "stf_09", name: "Cordelia Mbeki", email: "c.mbeki@haldengeneral.nhs.uk", family: "medical", jobTitle: "Consultant anaesthetist", specialty: "anaesthetics", staffRole: "clinician", status: "on_leave", ward: null, avatar: "../../assets/img/avatar-f-11.jpg", startedAt: daysAgo(2010), phone: "ext 4470", gmc: "GMC 6902377", timezone: "Europe/London", leaveUntil: daysAgo(-11) },
  { id: "stf_10", name: "Ivo Petrescu", email: "i.petrescu@haldengeneral.nhs.uk", family: "facilities", jobTitle: "Portering lead", specialty: null, staffRole: "read_only", status: "active", ward: null, avatar: "../../assets/img/avatar-m-10.jpg", startedAt: daysAgo(2560), phone: "ext 4118", gmc: null, timezone: "Europe/London" },
  { id: "stf_11", name: "Saoirse Whelan", email: "s.whelan@haldengeneral.nhs.uk", family: "nursing", jobTitle: "Staff nurse", specialty: null, staffRole: "clinician", status: "onboarding", ward: "beaumont", avatar: "../../assets/img/avatar-f-13.jpg", startedAt: daysAgo(-4), phone: "ext 4398", gmc: null, timezone: "Europe/London" },
  { id: "stf_12", name: "Emeka Nwosu", email: "e.nwosu@haldengeneral.nhs.uk", family: "pharmacy", jobTitle: "Pharmacy technician", specialty: null, staffRole: "read_only", status: "active", ward: null, avatar: "../../assets/img/avatar-m-12.jpg", startedAt: daysAgo(300), phone: "ext 4216", gmc: null, timezone: "Europe/London" },
  { id: "stf_13", name: "Beatrix Halloran", email: "b.halloran@haldengeneral.nhs.uk", family: "medical", jobTitle: "Consultant geriatrician", specialty: "geriatrics", staffRole: "clinician", status: "active", ward: "hollis", avatar: "../../assets/img/avatar-f-15.jpg", startedAt: daysAgo(3120), phone: "ext 4433", gmc: "GMC 5540912", timezone: "Europe/London" },
  { id: "stf_14", name: "Dmitri Volkov", email: "d.volkov@haldengeneral.nhs.uk", family: "admin", jobTitle: "Records officer", specialty: null, staffRole: "coordinator", status: "suspended", ward: null, avatar: "../../assets/img/avatar-m-14.jpg", startedAt: daysAgo(1440), phone: "ext 4507", gmc: null, timezone: "Europe/London", suspendedNote: "Access suspended pending an information-governance review opened 4 March." },
];

/* ── Patients ────────────────────────────────────────────────────────────── */
const PATIENTS = [
  { id: "pat_01", name: "Ruth Adeyemi", number: "H-40-2291", born: "14 Feb 1958", sex: "Female", status: "inpatient", avatar: "../../assets/img/avatar-f-2.png", allergies: ["Penicillin"], lastReviewAt: hoursAgo(30), gp: "Fern Lane Surgery", phone: "07700 900 118", registeredAt: daysAgo(1820), nextOfKin: "Deborah Adeyemi (daughter)" },
  { id: "pat_02", name: "Callum Frayne", number: "H-40-4013", born: "3 Sep 1991", sex: "Male", status: "inpatient", avatar: "../../assets/img/avatar-m-3.jpg", allergies: [], lastReviewAt: hoursAgo(2), gp: "Halden Road Practice", phone: "07700 900 204", registeredAt: daysAgo(430), nextOfKin: "Erin Frayne (wife)" },
  { id: "pat_03", name: "Margit Sølve", number: "H-40-1188", born: "22 Jun 1947", sex: "Female", status: "inpatient", avatar: "../../assets/img/avatar-f-4.jpg", allergies: ["Latex", "Codeine"], lastReviewAt: hoursAgo(14), gp: "Westmere Health Centre", phone: "07700 900 331", registeredAt: daysAgo(2600), nextOfKin: "Anton Sølve (son)" },
  { id: "pat_04", name: "Desmond Ayo", number: "H-40-3376", born: "9 Nov 1962", sex: "Male", status: "inpatient", avatar: "../../assets/img/avatar-m-5.jpg", allergies: [], lastReviewAt: hoursAgo(40), gp: "Fern Lane Surgery", phone: "07700 900 447", registeredAt: daysAgo(900), nextOfKin: "Ada Ayo (wife)" },
  { id: "pat_05", name: "Ivy Trethewey", number: "H-40-2740", born: "30 Jan 1939", sex: "Female", status: "inpatient", avatar: "../../assets/img/avatar-f-6.jpg", allergies: ["Aspirin"], lastReviewAt: hoursAgo(6), gp: "Halden Road Practice", phone: "07700 900 512", registeredAt: daysAgo(3400), nextOfKin: "Peter Trethewey (son)" },
  { id: "pat_06", name: "Hakim Barzani", number: "H-40-3902", born: "17 Mar 1955", sex: "Male", status: "inpatient", avatar: "../../assets/img/avatar-m-7.jpg", allergies: [], lastReviewAt: hoursAgo(4), gp: "Westmere Health Centre", phone: "07700 900 660", registeredAt: daysAgo(1120), nextOfKin: "Layla Barzani (daughter)" },
  { id: "pat_07", name: "Nour Haddad", number: "H-40-4402", born: "5 Jul 1984", sex: "Female", status: "inpatient", avatar: "../../assets/img/avatar-f-8.jpg", allergies: ["Iodine contrast"], lastReviewAt: hoursAgo(3), gp: "Fern Lane Surgery", phone: "07700 900 771", registeredAt: daysAgo(260), nextOfKin: "Samir Haddad (husband)" },
  { id: "pat_08", name: "Gordon Mealy", number: "H-40-2015", born: "28 Apr 1970", sex: "Male", status: "discharged", avatar: "../../assets/img/avatar-m-13.jpg", allergies: [], lastReviewAt: daysAgo(6), gp: "Halden Road Practice", phone: "07700 900 802", registeredAt: daysAgo(2200), nextOfKin: "Rita Mealy (sister)" },
  { id: "pat_09", name: "Eluned Pryce", number: "H-40-1663", born: "12 Dec 1936", sex: "Female", status: "inpatient", avatar: "../../assets/img/avatar-f-10.jpg", allergies: ["Penicillin", "Sulfonamides"], lastReviewAt: hoursAgo(20), gp: "Westmere Health Centre", phone: "07700 900 915", registeredAt: daysAgo(4100), nextOfKin: "Gareth Pryce (son)" },
  { id: "pat_10", name: "Anselm Dubois", number: "H-40-3120", born: "1 Aug 1978", sex: "Male", status: "discharged", avatar: "../../assets/img/avatar-m-15.jpg", allergies: [], lastReviewAt: daysAgo(9), gp: "Out of area", phone: "07700 900 118", registeredAt: daysAgo(680), nextOfKin: "Colette Dubois (wife)" },
  { id: "pat_11", name: "Farida Kettle", number: "H-40-4521", born: "19 May 1996", sex: "Female", status: "day_case", avatar: "../../assets/img/avatar-f-12.jpg", allergies: [], lastReviewAt: hoursAgo(22), gp: "Halden Road Practice", phone: "07700 900 227", registeredAt: daysAgo(90), nextOfKin: "Jonah Kettle (brother)" },
  { id: "pat_12", name: "Stefan Kovač", number: "H-40-4560", born: "2 Oct 1988", sex: "Male", status: "outpatient", avatar: "../../assets/img/avatar-m-16.jpg", allergies: [], lastReviewAt: daysAgo(12), gp: "Fern Lane Surgery", phone: "07700 900 340", registeredAt: daysAgo(45), nextOfKin: "Not recorded" },
];

/* ── Admissions: one episode of ward care each ───────────────────────────── */
const ADMISSIONS = [
  { id: "adm_01", patientId: "pat_01", ward: "linden", bed: null, status: "awaiting_bed", source: "ed", reason: "Chest pain, troponin rise — needs a monitored bed", requestedAt: hoursAgo(5), admittedAt: null, fitAt: null, dischargedAt: null, expectedStayDays: 3, consultantId: "stf_04" },
  { id: "adm_02", patientId: "pat_02", ward: "beaumont", bed: null, status: "awaiting_bed", source: "ed", reason: "Right iliac fossa pain, surgical review", requestedAt: hoursAgo(2), admittedAt: null, fitAt: null, dischargedAt: null, expectedStayDays: 2, consultantId: "stf_01" },
  { id: "adm_03", patientId: "pat_03", ward: "beaumont", bed: "B-04", status: "on_ward", source: "elective", reason: "Gallstone disease, for cholecystectomy", requestedAt: daysAgo(4), admittedAt: daysAgo(3), fitAt: null, dischargedAt: null, expectedStayDays: 4, consultantId: "stf_01" },
  { id: "adm_04", patientId: "pat_04", ward: "corvid", bed: "C-02", status: "on_ward", source: "gp", reason: "Unstable angina, awaiting angiography", requestedAt: daysAgo(10), admittedAt: daysAgo(9), fitAt: null, dischargedAt: null, expectedStayDays: 5, consultantId: "stf_02" },
  { id: "adm_05", patientId: "pat_05", ward: "beaumont", bed: "B-07", status: "fit_for_discharge", source: "ed", reason: "Infected surgical wound, debrided 15 March", requestedAt: daysAgo(7), admittedAt: daysAgo(6), fitAt: hoursAgo(30), dischargedAt: null, expectedStayDays: 5, consultantId: "stf_01" },
  { id: "adm_06", patientId: "pat_06", ward: "hollis", bed: "H-01", status: "fit_for_discharge", source: "gp", reason: "Iron-deficiency anaemia, scoped this morning", requestedAt: daysAgo(12), admittedAt: daysAgo(11), fitAt: hoursAgo(5), dischargedAt: null, expectedStayDays: 9, consultantId: "stf_13" },
  { id: "adm_07", patientId: "pat_07", ward: "linden", bed: "L-05", status: "on_ward", source: "ed", reason: "Sepsis of unknown source, on IV antibiotics", requestedAt: daysAgo(1), admittedAt: daysAgo(1), fitAt: null, dischargedAt: null, expectedStayDays: 3, consultantId: "stf_04" },
  { id: "adm_08", patientId: "pat_08", ward: "aster", bed: "D-02", status: "discharged", source: "elective", reason: "Appendicectomy, uncomplicated", requestedAt: daysAgo(9), admittedAt: daysAgo(8), fitAt: daysAgo(7), dischargedAt: daysAgo(6), expectedStayDays: 2, consultantId: "stf_01" },
  { id: "adm_09", patientId: "pat_09", ward: "hollis", bed: "H-06", status: "on_ward", source: "ed", reason: "Fractured neck of femur, for hemiarthroplasty", requestedAt: daysAgo(4), admittedAt: daysAgo(4), fitAt: null, dischargedAt: null, expectedStayDays: 7, consultantId: "stf_13" },
  { id: "adm_10", patientId: "pat_10", ward: "corvid", bed: "C-05", status: "transferred", source: "transfer", reason: "Transferred to Westmere for electrophysiology", requestedAt: daysAgo(15), admittedAt: daysAgo(14), fitAt: null, dischargedAt: daysAgo(9), expectedStayDays: 4, consultantId: "stf_02" },
];

/* ── Interventions ───────────────────────────────────────────────────────── */
const INTERVENTIONS = [
  { id: "int_01", patientId: "pat_03", name: "Laparoscopic cholecystectomy", specialty: "general_surgery", priority: "routine", status: "scheduled", theatre: "t1", requestedAt: daysAgo(3), scheduledAt: dayAt(0, 11, 0), consentAt: hoursAgo(19), surgeonId: "stf_01", anaesthetistId: "stf_09", plannedMin: 90, completedAt: null, notes: "Day-three inpatient, fasted from midnight." },
  { id: "int_02", patientId: "pat_11", name: "Inguinal hernia repair", specialty: "general_surgery", priority: "routine", status: "scheduled", theatre: "day", requestedAt: daysAgo(18), scheduledAt: dayAt(0, 14, 0), consentAt: null, surgeonId: "stf_01", anaesthetistId: null, plannedMin: 60, completedAt: null, notes: "Day case. Consent not on the record — she arrived at 08:40." },
  { id: "int_03", patientId: "pat_04", name: "Coronary angiography", specialty: "cardiology", priority: "urgent", status: "scheduled", theatre: "t2", requestedAt: daysAgo(8), scheduledAt: dayAt(1, 9, 0), consentAt: null, surgeonId: "stf_02", anaesthetistId: null, plannedMin: 45, completedAt: null, notes: "Ninth day on Corvid; the list has slipped twice." },
  { id: "int_04", patientId: "pat_07", name: "Central line insertion", specialty: "acute_medicine", priority: "urgent", status: "in_theatre", theatre: "t3", requestedAt: hoursAgo(20), scheduledAt: hoursAgo(1), consentAt: hoursAgo(3), surgeonId: "stf_04", anaesthetistId: null, plannedMin: 40, completedAt: null, notes: "Started 08:20 for antibiotic access." },
  { id: "int_05", patientId: "pat_05", name: "Wound debridement", specialty: "general_surgery", priority: "urgent", status: "completed", theatre: "t1", requestedAt: daysAgo(3), scheduledAt: daysAgo(2), consentAt: daysAgo(2), surgeonId: "stf_01", anaesthetistId: "stf_09", plannedMin: 45, completedAt: daysAgo(2), notes: "Healthy margins; dressing changed daily." },
  { id: "int_06", patientId: "pat_09", name: "Hip hemiarthroplasty", specialty: "general_surgery", priority: "urgent", status: "requested", theatre: null, requestedAt: hoursAgo(26), scheduledAt: null, consentAt: null, surgeonId: "stf_13", anaesthetistId: null, plannedMin: 120, completedAt: null, notes: "Fourth day since the fall — she needs a slot." },
  { id: "int_07", patientId: "pat_06", name: "Upper GI endoscopy", specialty: "geriatrics", priority: "routine", status: "recovery", theatre: "t2", requestedAt: daysAgo(6), scheduledAt: hoursAgo(3), consentAt: daysAgo(1), surgeonId: "stf_13", anaesthetistId: null, plannedMin: 30, completedAt: null, notes: "In recovery since 08:40; awaiting sedation score." },
  { id: "int_08", patientId: "pat_01", name: "CT-guided drainage", specialty: "radiology", priority: "emergency", status: "requested", theatre: null, requestedAt: hoursAgo(4), scheduledAt: null, consentAt: null, surgeonId: "stf_04", anaesthetistId: null, plannedMin: 60, completedAt: null, notes: "Requested from ED at the same time as the bed." },
  { id: "int_09", patientId: "pat_08", name: "Appendicectomy", specialty: "general_surgery", priority: "emergency", status: "completed", theatre: "t1", requestedAt: daysAgo(8), scheduledAt: daysAgo(8), consentAt: daysAgo(8), surgeonId: "stf_01", anaesthetistId: "stf_09", plannedMin: 75, completedAt: daysAgo(8), notes: "Uncomplicated; discharged two days later." },
  { id: "int_10", patientId: "pat_12", name: "Skin lesion excision", specialty: "general_surgery", priority: "routine", status: "scheduled", theatre: "day", requestedAt: daysAgo(20), scheduledAt: dayAt(6, 10, 30), consentAt: null, surgeonId: "stf_01", anaesthetistId: null, plannedMin: 30, completedAt: null, notes: "Outpatient; consent at pre-assessment on the day." },
];

/* ── Medication orders ───────────────────────────────────────────────────── */
const MEDICATION_ORDERS = [
  { id: "med_01", patientId: "pat_07", drug: "Piperacillin-tazobactam", dose: "4.5 g", route: "iv", frequency: "Three times daily", status: "active", indication: "Sepsis of unknown source", prescriberId: "stf_04", verifiedById: "stf_05", startedAt: daysAgo(1), nextDoseAt: hoursOn(0.5), lastGivenAt: hoursAgo(7.5), endsAt: daysAgo(-4), drugId: "drg_02" },
  { id: "med_02", patientId: "pat_01", drug: "Enoxaparin", dose: "40 mg", route: "sc", frequency: "Once daily", status: "awaiting_verification", indication: "Thromboprophylaxis", prescriberId: "stf_04", verifiedById: null, startedAt: hoursAgo(4), nextDoseAt: hoursOn(9), lastGivenAt: null, endsAt: null, drugId: "drg_05" },
  { id: "med_03", patientId: "pat_02", drug: "Morphine sulfate", dose: "5 mg", route: "iv", frequency: "As required, up to four hourly", status: "awaiting_verification", indication: "Abdominal pain", prescriberId: "stf_01", verifiedById: null, startedAt: hoursAgo(1.5), nextDoseAt: null, lastGivenAt: null, endsAt: null, drugId: "drg_07" },
  { id: "med_04", patientId: "pat_09", drug: "Paracetamol", dose: "1 g", route: "oral", frequency: "Four times daily", status: "active", indication: "Hip pain", prescriberId: "stf_13", verifiedById: "stf_05", startedAt: daysAgo(4), nextDoseAt: hoursAgo(2), lastGivenAt: hoursAgo(8), endsAt: null, drugId: "drg_01" },
  { id: "med_05", patientId: "pat_03", drug: "Ondansetron", dose: "4 mg", route: "iv", frequency: "As required, eight hourly", status: "active", indication: "Post-operative nausea cover", prescriberId: "stf_01", verifiedById: "stf_05", startedAt: hoursAgo(19), nextDoseAt: hoursOn(6), lastGivenAt: hoursAgo(2), endsAt: null, drugId: "drg_04" },
  { id: "med_06", patientId: "pat_04", drug: "Bisoprolol", dose: "2.5 mg", route: "oral", frequency: "Once daily", status: "on_hold", indication: "Rate control — held before angiography", prescriberId: "stf_02", verifiedById: "stf_05", startedAt: daysAgo(9), nextDoseAt: null, lastGivenAt: daysAgo(1), endsAt: null, drugId: "drg_06" },
  { id: "med_07", patientId: "pat_05", drug: "Flucloxacillin", dose: "1 g", route: "iv", frequency: "Four times daily", status: "active", indication: "Wound infection", prescriberId: "stf_01", verifiedById: "stf_05", startedAt: daysAgo(5), nextDoseAt: hoursOn(2.5), lastGivenAt: hoursAgo(3.5), endsAt: daysAgo(-2), drugId: "drg_03" },
  { id: "med_08", patientId: "pat_06", drug: "Ferrous fumarate", dose: "210 mg", route: "oral", frequency: "Twice daily", status: "active", indication: "Iron-deficiency anaemia", prescriberId: "stf_13", verifiedById: "stf_05", startedAt: daysAgo(10), nextDoseAt: hoursOn(3), lastGivenAt: hoursAgo(9), endsAt: null, drugId: "drg_08" },
  { id: "med_09", patientId: "pat_03", drug: "Co-amoxiclav", dose: "1.2 g", route: "iv", frequency: "Three times daily", status: "awaiting_verification", indication: "Surgical prophylaxis for today's list", prescriberId: "stf_01", verifiedById: null, startedAt: hoursAgo(0.75), nextDoseAt: null, lastGivenAt: null, endsAt: null, drugId: "drg_09" },
  { id: "med_10", patientId: "pat_08", drug: "Paracetamol", dose: "1 g", route: "oral", frequency: "Four times daily", status: "completed", indication: "Post-operative pain", prescriberId: "stf_01", verifiedById: "stf_05", startedAt: daysAgo(8), nextDoseAt: null, lastGivenAt: daysAgo(6), endsAt: daysAgo(6), drugId: "drg_01" },
  { id: "med_11", patientId: "pat_10", drug: "Amiodarone", dose: "200 mg", route: "oral", frequency: "Once daily", status: "stopped", indication: "Stopped on transfer to Westmere", prescriberId: "stf_02", verifiedById: "stf_05", startedAt: daysAgo(13), nextDoseAt: null, lastGivenAt: daysAgo(9), endsAt: daysAgo(9), drugId: "drg_10" },
  { id: "med_12", patientId: "pat_09", drug: "Enoxaparin", dose: "40 mg", route: "sc", frequency: "Once daily", status: "active", indication: "Thromboprophylaxis", prescriberId: "stf_13", verifiedById: "stf_05", startedAt: daysAgo(4), nextDoseAt: hoursOn(11), lastGivenAt: hoursAgo(13), endsAt: null, drugId: "drg_05" },
];

/* ── Formulary and stock ─────────────────────────────────────────────────── */
const FORMULARY = [
  { id: "drg_01", name: "Paracetamol", form: "500 mg tablet", route: "oral", stock: "in_stock", onHand: 2400, reorderAt: 600, unit: "tablets", supplier: "Trust wholesaler", earliestExpiry: daysAgo(-420), unitCostMinor: 4, controlled: false },
  { id: "drg_02", name: "Piperacillin-tazobactam", form: "4.5 g vial", route: "iv", stock: "low", onHand: 34, reorderAt: 40, unit: "vials", supplier: "Halden pharmacy production", earliestExpiry: daysAgo(-95), unitCostMinor: 2100, controlled: false },
  { id: "drg_03", name: "Flucloxacillin", form: "1 g vial", route: "iv", stock: "in_stock", onHand: 180, reorderAt: 60, unit: "vials", supplier: "Trust wholesaler", earliestExpiry: daysAgo(-260), unitCostMinor: 320, controlled: false },
  { id: "drg_04", name: "Ondansetron", form: "4 mg/2 ml ampoule", route: "iv", stock: "in_stock", onHand: 210, reorderAt: 80, unit: "ampoules", supplier: "Trust wholesaler", earliestExpiry: daysAgo(-310), unitCostMinor: 180, controlled: false },
  { id: "drg_05", name: "Enoxaparin", form: "40 mg syringe", route: "sc", stock: "low", onHand: 52, reorderAt: 75, unit: "syringes", supplier: "Trust wholesaler", earliestExpiry: daysAgo(-140), unitCostMinor: 490, controlled: false },
  { id: "drg_06", name: "Bisoprolol", form: "2.5 mg tablet", route: "oral", stock: "in_stock", onHand: 900, reorderAt: 300, unit: "tablets", supplier: "Trust wholesaler", earliestExpiry: daysAgo(-500), unitCostMinor: 6, controlled: false },
  { id: "drg_07", name: "Morphine sulfate", form: "10 mg/1 ml ampoule", route: "iv", stock: "out", onHand: 0, reorderAt: 30, unit: "ampoules", supplier: "Controlled drugs cupboard", earliestExpiry: null, unitCostMinor: 220, controlled: true },
  { id: "drg_08", name: "Ferrous fumarate", form: "210 mg tablet", route: "oral", stock: "in_stock", onHand: 640, reorderAt: 200, unit: "tablets", supplier: "Trust wholesaler", earliestExpiry: daysAgo(-380), unitCostMinor: 5, controlled: false },
  { id: "drg_09", name: "Co-amoxiclav", form: "1.2 g vial", route: "iv", stock: "in_stock", onHand: 145, reorderAt: 60, unit: "vials", supplier: "Trust wholesaler", earliestExpiry: daysAgo(-210), unitCostMinor: 280, controlled: false },
  { id: "drg_10", name: "Amiodarone", form: "200 mg tablet", route: "oral", stock: "discontinued", onHand: 0, reorderAt: 0, unit: "tablets", supplier: "Withdrawn — cardiology switched to sotalol", earliestExpiry: null, unitCostMinor: 30, controlled: false },
];

/* ── The social layer: notes written on records, and the feed that reads them ── */
const COMMENTS = [
  { id: "cmt_01", record: { type: "admission", id: "adm_01" }, authorId: "stf_04", at: hoursAgo(4.5), body: "ED has held her five hours now. @stf_03 is there anything on Linden after the 11:00 discharge round?", mentions: ["stf_03"], reactions: {} },
  { id: "cmt_02", record: { type: "admission", id: "adm_01" }, authorId: "stf_07", at: hoursAgo(3), body: "Portering can move her the moment a bed is named — Ivo has a team free until noon.", mentions: [], reactions: { ack: ["stf_04"] } },
  { id: "cmt_03", record: { type: "intervention", id: "int_02" }, authorId: "stf_07", at: hoursAgo(0.6), body: "Consent still not on Farida's record and she is second on the day-case list. @stf_01 can you see her before 14:00?", mentions: ["stf_01"], reactions: {} },
  { id: "cmt_04", record: { type: "intervention", id: "int_06" }, authorId: "stf_13", at: hoursAgo(22), body: "Fourth day since the fall. She needs a slot tomorrow at the latest — every day here costs her mobility.", mentions: [], reactions: { agree: ["stf_01", "stf_03"] } },
  { id: "cmt_05", record: { type: "intervention", id: "int_06" }, authorId: "stf_07", at: hoursAgo(19), body: "Theatre 3 has a 13:30 gap tomorrow if anaesthetics can cover it. @stf_09 is on leave until the 28th.", mentions: ["stf_09"], reactions: {} },
  { id: "cmt_06", record: { type: "medication", id: "med_03" }, authorId: "stf_05", at: hoursAgo(1), body: "Morphine is out of stock in the cupboard — I will not verify this until we have ampoules back. @stf_01 oral oxycodone in the meantime?", mentions: ["stf_01"], reactions: {} },
  { id: "cmt_07", record: { type: "medication", id: "med_04" }, authorId: "stf_06", at: hoursAgo(1.8), body: "Dose was due 07:20 and has not gone in. She was off the ward for imaging — flagged to the nurse in charge.", mentions: [], reactions: { seen: ["stf_03"] } },
  { id: "cmt_08", record: { type: "patient", id: "pat_05" }, authorId: "stf_03", at: hoursAgo(28), body: "Fit for discharge since yesterday morning; we are waiting on a district-nurse dressing visit. Family can collect any time after 10:00.", mentions: [], reactions: { agree: ["stf_01"] } },
  { id: "cmt_09", record: { type: "patient", id: "pat_04" }, authorId: "stf_02", at: hoursAgo(26), body: "Ninth day, angiography now booked for 09:00 tomorrow. Bisoprolol held from this morning. @stf_03 please keep him nil by mouth from midnight.", mentions: ["stf_03"], reactions: {} },
  { id: "cmt_10", record: { type: "patient", id: "pat_09" }, authorId: "stf_06", at: hoursAgo(9), body: "Slept better; pain score 3 with regular paracetamol. Daughter asked about the operating list.", mentions: [], reactions: { seen: ["stf_13"] } },
  { id: "cmt_11", record: { type: "patient", id: "pat_01" }, authorId: "stf_03", at: hoursAgo(2.2), body: "Penicillin allergy is on the front of her chart. Drainage request went in at 05:20 alongside the bed request.", mentions: [], reactions: {} },
  { id: "cmt_12", record: { type: "transfer", id: "trf_02" }, authorId: "stf_14", at: hoursAgo(21), body: "Twelve rows from the PAS export have no hospital number. They need a human before I let them near the patient index.", mentions: ["stf_03"], reactions: {} },
  { id: "cmt_13", record: { type: "formulary", id: "drg_07" }, authorId: "stf_12", at: hoursAgo(7), body: "Controlled-drugs order placed with the wholesaler this morning; delivery expected Thursday.", mentions: [], reactions: { ack: ["stf_05"] } },
  { id: "cmt_15", record: { type: "invoice", id: "inv_10" }, authorId: "stf_07", at: hoursAgo(30), body: "The commissioner is right that the stay ran to eleven days — two of those were waiting on a district-nurse visit, not on care. @stf_03 can you confirm the dates so I can answer them?", mentions: ["stf_03"], reactions: {} },
  { id: "cmt_16", record: { type: "invoice", id: "inv_08" }, authorId: "stf_14", at: hoursAgo(18), body: "Bank transfer came back this morning. Letter sent to the address on the record; nothing else to do until she replies.", mentions: [], reactions: { seen: ["stf_07"] } },
  { id: "cmt_14", record: { type: "intervention", id: "int_07" }, authorId: "stf_06", at: hoursAgo(0.4), body: "Sedation score 1, observations stable. Ready to go back to Hollis as soon as a porter is free.", mentions: [], reactions: {} },
];

const ACTIVITY = [
  { id: "act_01", actorId: "stf_04", at: hoursAgo(0.3), verb: "requested a bed", record: { type: "admission", id: "adm_02" }, note: "Right iliac fossa pain from ED" },
  { id: "act_02", actorId: "stf_13", at: hoursAgo(3), verb: "moved to recovery", record: { type: "intervention", id: "int_07" }, note: null },
  { id: "act_03", actorId: "stf_04", at: hoursAgo(1), verb: "started in theatre", record: { type: "intervention", id: "int_04" }, note: "Theatre 3" },
  { id: "act_04", actorId: "stf_05", at: hoursAgo(1.1), verb: "commented", record: { type: "medication", id: "med_03" }, note: null },
  { id: "act_05", actorId: "stf_01", at: hoursAgo(19), verb: "recorded consent", record: { type: "intervention", id: "int_01" }, note: null },
  { id: "act_06", actorId: "stf_03", at: hoursAgo(28), verb: "commented", record: { type: "patient", id: "pat_05" }, note: null },
  { id: "act_07", actorId: "stf_13", at: hoursAgo(5), verb: "marked fit for discharge", record: { type: "admission", id: "adm_06" }, note: null },
  { id: "act_08", actorId: "stf_05", at: hoursAgo(6), verb: "verified an order", record: { type: "medication", id: "med_07" }, note: null },
  { id: "act_09", actorId: "stf_14", at: hoursAgo(21), verb: "imported records", record: { type: "transfer", id: "trf_02" }, note: "318 rows from the patient administration system" },
  { id: "act_10", actorId: "stf_03", at: hoursAgo(23), verb: "exported a report", record: { type: "transfer", id: "trf_01" }, note: "Beaumont ward board, CSV" },
  { id: "act_11", actorId: "stf_07", at: hoursAgo(19), verb: "commented", record: { type: "intervention", id: "int_06" }, note: null },
  { id: "act_12", actorId: "stf_02", at: hoursAgo(26), verb: "commented", record: { type: "patient", id: "pat_04" }, note: null },
  { id: "act_13", actorId: "stf_01", at: daysAgo(2), verb: "completed a procedure", record: { type: "intervention", id: "int_05" }, note: "Wound debridement, 45 minutes" },
  { id: "act_14", actorId: "stf_12", at: hoursAgo(7), verb: "commented", record: { type: "formulary", id: "drg_07" }, note: null },
  { id: "act_15", actorId: "stf_07", at: daysAgo(3), verb: "recorded a payment", record: { type: "invoice", id: "inv_01" }, note: "Commissioner remittance REM-88214" },
  { id: "act_16", actorId: "stf_14", at: hoursAgo(18), verb: "commented", record: { type: "invoice", id: "inv_08" }, note: null },
  { id: "act_17", actorId: "stf_07", at: daysAgo(1), verb: "issued an invoice", record: { type: "invoice", id: "inv_03" }, note: null },
];

/* ── Import and export jobs ─────────────────────────────────────────────── */
const TRANSFERS = [
  { id: "trf_01", kind: "export", label: "Beaumont ward board", scope: "Admissions on Beaumont, 17 March", format: "CSV", source: null, status: "completed", rows: 4, accepted: 4, rejected: 0, pending: 0, startedAt: hoursAgo(23), finishedAt: hoursAgo(23), byId: "stf_03", fileName: "beaumont-board-17-03-2026.csv", sizeKb: 6 },
  { id: "trf_02", kind: "import", label: "Patient administration system", scope: "Nightly patient index", format: "CSV", source: "pas_csv", status: "needs_review", rows: 318, accepted: 306, rejected: 0, pending: 12, startedAt: hoursAgo(21.5), finishedAt: hoursAgo(21), byId: "stf_14", fileName: "pas-index-16-03-2026.csv", sizeKb: 412 },
  { id: "trf_03", kind: "import", label: "Pathology feed", scope: "Results for Linden and Corvid", format: "HL7", source: "lab_hl7", status: "running", rows: 96, accepted: 71, rejected: 0, pending: 0, startedAt: hoursAgo(0.4), finishedAt: null, byId: "stf_08", fileName: "path-feed-live", sizeKb: 88 },
  { id: "trf_04", kind: "import", label: "Rota system", scope: "March nursing rota", format: "XLSX", source: "rota_xlsx", status: "failed", rows: 0, accepted: 0, rejected: 0, pending: 0, startedAt: daysAgo(1), finishedAt: daysAgo(1), byId: "stf_07", fileName: "nursing-rota-march.xlsx", sizeKb: 240, failure: "The sheet named “Week 12” is missing the ward column, so no row could be matched to a ward." },
  { id: "trf_05", kind: "export", label: "Theatre utilisation", scope: "All interventions, 1–16 March", format: "XLSX", source: null, status: "completed", rows: 61, accepted: 61, rejected: 0, pending: 0, startedAt: daysAgo(1.2), finishedAt: daysAgo(1.2), byId: "stf_07", fileName: "theatre-utilisation-01-16-03.xlsx", sizeKb: 74 },
  { id: "trf_06", kind: "import", label: "Formulary supplier catalogue", scope: "Price and pack-size update", format: "CSV", source: "formulary_csv", status: "completed", rows: 1204, accepted: 1204, rejected: 0, pending: 0, startedAt: daysAgo(3), finishedAt: daysAgo(3), byId: "stf_05", fileName: "supplier-catalogue-14-03.csv", sizeKb: 980 },
  { id: "trf_07", kind: "export", label: "Medication administration record", scope: "Active orders, all wards", format: "CSV", source: null, status: "completed", rows: 7, accepted: 7, rejected: 0, pending: 0, startedAt: daysAgo(2), finishedAt: daysAgo(2), byId: "stf_05", fileName: "mar-active-15-03-2026.csv", sizeKb: 11 },
];

/* The twelve rows the PAS import could not place. The review screen executes on
   these, so the accept and reject counts on trf_02 move with what is decided. */
const TRANSFER_ROWS = {
  trf_02: [
    { line: 14, name: "Kettle, Farida", problem: "No hospital number", detail: "Matches H-40-4521 on name and date of birth" },
    { line: 27, name: "Ayo, Desmond", problem: "No hospital number", detail: "Matches H-40-3376 on name and date of birth" },
    { line: 38, name: "Unknown", problem: "Date of birth unreadable", detail: "Field reads “00/00/0000”" },
    { line: 51, name: "Pryce, Eluned", problem: "Duplicate of line 50", detail: "Both lines carry H-40-1663" },
    { line: 66, name: "Sølve, Margit", problem: "No hospital number", detail: "Matches H-40-1188 on name and date of birth" },
    { line: 90, name: "Frayne, Callum", problem: "Ward not recognised", detail: "Ward code “BEA2” is not a Halden ward" },
    { line: 104, name: "Unknown", problem: "Name field empty", detail: "Only a GP code was supplied" },
    { line: 133, name: "Barzani, Hakim", problem: "No hospital number", detail: "Matches H-40-3902 on name and date of birth" },
    { line: 178, name: "Dubois, Anselm", problem: "Ward not recognised", detail: "Ward code “WST” belongs to Westmere" },
    { line: 205, name: "Unknown", problem: "Date of birth unreadable", detail: "Field reads “31/02/1954”" },
    { line: 261, name: "Trethewey, Ivy", problem: "Duplicate of line 259", detail: "Both lines carry H-40-2740" },
    { line: 300, name: "Adeyemi, Ruth", problem: "No hospital number", detail: "Matches H-40-2291 on name and date of birth" },
  ],
};

/* Invoices. Every line names the record it bills — an intervention, an
   admission's bed days, a medication course — so a line is checkable against the
   care record rather than being a plausible amount. Totals are NOT stored: they
   are the sum of the lines, and what has been paid is the sum of the cleared
   payments below. Amounts are pence. */
const INVOICES = [
  { id: "inv_01", patientId: "pat_08", payer: "nhs_commissioner", status: "paid", reference: "HG-2026-0331", issuedAt: daysAgo(5), dueAt: daysAgo(-25), codedById: "stf_07", note: null,
    lines: [
      { label: "Emergency appendicectomy", kind: "procedure", ref: { type: "intervention", id: "int_09" }, qty: 1, unitMinor: 241000 },
      { label: "Day-surgery bed day, Aster", kind: "bed", ref: { type: "admission", id: "adm_08" }, qty: 2, unitMinor: 48000 },
    ] },
  { id: "inv_02", patientId: "pat_10", payer: "private_insurer", status: "part_paid", reference: "HG-2026-0318", issuedAt: daysAgo(8), dueAt: daysAgo(-22), codedById: "stf_07", note: "Insurer settles in two instalments by agreement.",
    lines: [
      { label: "Cardiology inpatient care", kind: "bed", ref: { type: "admission", id: "adm_10" }, qty: 5, unitMinor: 52000 },
      { label: "Telemetry monitoring", kind: "other", ref: null, qty: 5, unitMinor: 9000 },
    ] },
  { id: "inv_03", patientId: "pat_05", payer: "nhs_commissioner", status: "issued", reference: "HG-2026-0342", issuedAt: daysAgo(1), dueAt: daysAgo(-29), codedById: "stf_07", note: null,
    lines: [
      { label: "Wound debridement", kind: "procedure", ref: { type: "intervention", id: "int_05" }, qty: 1, unitMinor: 118000 },
      { label: "Surgical bed day, Beaumont", kind: "bed", ref: { type: "admission", id: "adm_05" }, qty: 6, unitMinor: 48000 },
    ] },
  { id: "inv_04", patientId: "pat_03", payer: "nhs_commissioner", status: "draft", reference: "HG-2026-0349", issuedAt: null, dueAt: null, codedById: null, note: "Opens for coding when today's cholecystectomy is recorded as completed.",
    lines: [
      { label: "Laparoscopic cholecystectomy", kind: "procedure", ref: { type: "intervention", id: "int_01" }, qty: 1, unitMinor: 294000 },
      { label: "Surgical bed day, Beaumont", kind: "bed", ref: { type: "admission", id: "adm_03" }, qty: 3, unitMinor: 48000 },
    ] },
  { id: "inv_05", patientId: "pat_11", payer: "self_pay", status: "draft", reference: "HG-2026-0350", issuedAt: null, dueAt: null, codedById: null, note: "Quoted at pre-assessment; payable before the day-case list.",
    lines: [{ label: "Inguinal hernia repair, day case", kind: "procedure", ref: { type: "intervention", id: "int_02" }, qty: 1, unitMinor: 219000 }] },
  { id: "inv_06", patientId: "pat_04", payer: "nhs_commissioner", status: "awaiting_coding", reference: "HG-2026-0344", issuedAt: null, dueAt: null, codedById: null, note: "The angiography is not billed until it happens; bed days are coded to date.",
    lines: [
      { label: "Cardiology inpatient care", kind: "bed", ref: { type: "admission", id: "adm_04" }, qty: 9, unitMinor: 52000 },
      { label: "Telemetry monitoring", kind: "other", ref: null, qty: 9, unitMinor: 9000 },
    ] },
  { id: "inv_07", patientId: "pat_09", payer: "nhs_commissioner", status: "issued", reference: "HG-2026-0296", issuedAt: daysAgo(33), dueAt: daysAgo(3), codedById: "stf_14", note: null,
    lines: [
      { label: "Older people's inpatient care", kind: "bed", ref: { type: "admission", id: "adm_09" }, qty: 4, unitMinor: 44000 },
      { label: "Fractured neck of femur pathway", kind: "other", ref: null, qty: 1, unitMinor: 68000 },
    ] },
  { id: "inv_08", patientId: "pat_07", payer: "overseas", status: "issued", reference: "HG-2026-0347", issuedAt: daysAgo(2), dueAt: daysAgo(-12), codedById: "stf_07", note: "Overseas visitor; the trust invoices the patient directly.",
    lines: [
      { label: "Acute medicine inpatient care", kind: "bed", ref: { type: "admission", id: "adm_07" }, qty: 1, unitMinor: 51000 },
      { label: "Central line insertion", kind: "procedure", ref: { type: "intervention", id: "int_04" }, qty: 1, unitMinor: 62000 },
      { label: "Intravenous antibiotic course", kind: "medication", ref: { type: "medication", id: "med_01" }, qty: 1, unitMinor: 31000 },
    ] },
  { id: "inv_09", patientId: "pat_12", payer: "self_pay", status: "draft", reference: "HG-2026-0351", issuedAt: null, dueAt: null, codedById: null, note: "Quoted for the excision booked in six days.",
    lines: [{ label: "Skin lesion excision, day case", kind: "procedure", ref: { type: "intervention", id: "int_10" }, qty: 1, unitMinor: 68000 }] },
  { id: "inv_10", patientId: "pat_06", payer: "nhs_commissioner", status: "disputed", reference: "HG-2026-0309", issuedAt: daysAgo(9), dueAt: daysAgo(-21), codedById: "stf_14", note: "The commissioner queries 11 bed days against a 9-day expected stay.",
    lines: [
      { label: "Upper GI endoscopy", kind: "procedure", ref: { type: "intervention", id: "int_07" }, qty: 1, unitMinor: 96000 },
      { label: "Older people's inpatient care", kind: "bed", ref: { type: "admission", id: "adm_06" }, qty: 11, unitMinor: 44000 },
    ] },
];

/* ── Contracts, tariffs and what care costs ───────────────────────────────
   A tariff item is a thing that can be billed; a contract price is what one
   payer pays for it. An invoice line's unit price is checked against the
   contract price at render, so a line billed off contract is a finding rather
   than a silent difference. Item labels are the labels the invoice lines use —
   that is the join. */
const TARIFF_ITEMS = [
  { id: "tar_01", code: "HRG-FZ21A", label: "Emergency appendicectomy", kind: "procedure" },
  { id: "tar_02", code: "HRG-GA10C", label: "Laparoscopic cholecystectomy", kind: "procedure" },
  { id: "tar_03", code: "HRG-JC42Z", label: "Wound debridement", kind: "procedure" },
  { id: "tar_04", code: "HRG-FZ18B", label: "Inguinal hernia repair, day case", kind: "procedure" },
  { id: "tar_05", code: "HRG-EY43Z", label: "Coronary angiography", kind: "procedure" },
  { id: "tar_06", code: "HRG-FZ31Z", label: "Upper GI endoscopy", kind: "procedure" },
  { id: "tar_07", code: "HRG-WA22Z", label: "Central line insertion", kind: "procedure" },
  { id: "tar_08", code: "HRG-JC07Z", label: "Skin lesion excision, day case", kind: "procedure" },
  { id: "tar_09", code: "BED-SURG", label: "Surgical bed day, Beaumont", kind: "bed" },
  { id: "tar_10", code: "BED-DAYC", label: "Day-surgery bed day, Aster", kind: "bed" },
  { id: "tar_11", code: "BED-CARD", label: "Cardiology inpatient care", kind: "bed" },
  { id: "tar_12", code: "BED-OLDR", label: "Older people's inpatient care", kind: "bed" },
  { id: "tar_13", code: "BED-ACUT", label: "Acute medicine inpatient care", kind: "bed" },
  { id: "tar_14", code: "MON-TELE", label: "Telemetry monitoring", kind: "other" },
  { id: "tar_15", code: "DRUG-IVAB", label: "Intravenous antibiotic course", kind: "medication" },
];

const CONTRACTS = [
  { id: "con_01", payer: "nhs_commissioner", name: "Halden and Westmere block contract, 2026/27", status: "live", signedAt: daysAgo(200), expiresAt: daysAgo(-380), dueDays: 30, note: "National tariff, no local uplift. Activity returned monthly." },
  { id: "con_02", payer: "private_insurer", name: "Mercia Health schedule B", status: "live", signedAt: daysAgo(420), expiresAt: daysAgo(-26), dueDays: 30, note: "Renewal negotiation opens six weeks before the end date." },
  { id: "con_03", payer: "self_pay", name: "Self-pay price list, 2026", status: "live", signedAt: daysAgo(90), expiresAt: null, dueDays: 0, note: "Payable in full before the procedure; no credit is given." },
  { id: "con_04", payer: "overseas", name: "Overseas visitor charging schedule", status: "live", signedAt: daysAgo(150), expiresAt: daysAgo(-200), dueDays: 14, note: "Charged under the overseas visitor regulations." },
];

/* One row per price a contract actually carries. A combination that is missing
   is missing on purpose: the invoice line is then off contract and says so. */
const CONTRACT_PRICES = [
  { payer: "nhs_commissioner", itemId: "tar_01", minor: 241000 },
  { payer: "nhs_commissioner", itemId: "tar_02", minor: 294000 },
  { payer: "nhs_commissioner", itemId: "tar_03", minor: 118000 },
  { payer: "nhs_commissioner", itemId: "tar_05", minor: 176000 },
  { payer: "nhs_commissioner", itemId: "tar_06", minor: 96000 },
  { payer: "nhs_commissioner", itemId: "tar_09", minor: 48000 },
  { payer: "nhs_commissioner", itemId: "tar_10", minor: 48000 },
  { payer: "nhs_commissioner", itemId: "tar_11", minor: 52000 },
  { payer: "nhs_commissioner", itemId: "tar_12", minor: 44000 },
  { payer: "nhs_commissioner", itemId: "tar_14", minor: 9000 },
  { payer: "private_insurer", itemId: "tar_01", minor: 262000 },
  { payer: "private_insurer", itemId: "tar_02", minor: 318000 },
  { payer: "private_insurer", itemId: "tar_11", minor: 52000 },
  { payer: "private_insurer", itemId: "tar_14", minor: 9000 },
  { payer: "self_pay", itemId: "tar_02", minor: 348000 },
  { payer: "self_pay", itemId: "tar_04", minor: 219000 },
  { payer: "self_pay", itemId: "tar_08", minor: 68000 },
  { payer: "overseas", itemId: "tar_07", minor: 62000 },
  { payer: "overseas", itemId: "tar_12", minor: 49000 },
  { payer: "overseas", itemId: "tar_13", minor: 51000 },
  { payer: "overseas", itemId: "tar_15", minor: 28000 },
];

/* What the hospital's own accounts say care costs. Bed days are per ward per
   day; theatre is per minute; a drug course is costed from the order's own
   frequency against the formulary's unit cost. Pence throughout. */
const COST_RATES = {
  bedDayByWard: { beaumont: 39000, linden: 41000, corvid: 43000, aster: 31000, hollis: 36000 },
  theatreMinute: 1400,
  source: "Halden finance, 2025/26 reference costs",
};

/* Chases against an invoice: one row per contact, escalating. */
const CHASES = [
  { id: "chs_01", invoiceId: "inv_07", step: "reminder", at: daysAgo(10), byId: "stf_14", outcome: "no_reply", note: "Automatic reminder emailed to the commissioner's finance inbox." },
  { id: "chs_02", invoiceId: "inv_07", step: "statement", at: daysAgo(4), byId: "stf_07", outcome: "no_reply", note: "Statement sent with the March activity return." },
  { id: "chs_03", invoiceId: "inv_08", step: "reminder", at: hoursAgo(16), byId: "stf_14", outcome: "awaiting", note: "Letter to the address on the record after the bank transfer was returned." },
  { id: "chs_04", invoiceId: "inv_02", step: "call", at: daysAgo(2), byId: "stf_07", outcome: "promised", note: "Spoke to Mercia Health; the second instalment is advised for this week." },
];

/* Money against an invoice. What an invoice has been paid is the sum of the
   CLEARED rows here — pending and failed money is not paid money. */
const PAYMENTS = [
  { id: "pay_01", invoiceId: "inv_01", payer: "nhs_commissioner", method: "remittance", status: "cleared", amountMinor: 337000, receivedAt: daysAgo(3), reference: "REM-88214", byId: "stf_07", note: null },
  { id: "pay_02", invoiceId: "inv_02", payer: "private_insurer", method: "bank_transfer", status: "cleared", amountMinor: 120000, receivedAt: daysAgo(6), reference: "BT-40921", byId: "stf_07", note: "First of two instalments." },
  { id: "pay_03", invoiceId: "inv_02", payer: "private_insurer", method: "bank_transfer", status: "pending", amountMinor: 60000, receivedAt: hoursAgo(20), reference: "BT-41077", byId: "stf_07", note: "Second instalment, advised but not cleared." },
  { id: "pay_04", invoiceId: "inv_08", payer: "overseas", method: "bank_transfer", status: "failed", amountMinor: 144000, receivedAt: daysAgo(1), reference: "BT-41102", byId: "stf_14", note: "Returned by the sending bank; the patient has been written to." },
];

/* What each ward physically holds, and how many nurses its establishment asks
   for on a shift. Occupancy percentages and the rota's shortfall both read this;
   neither invents a denominator. */
const WARD_BEDS = [
  { ward: "beaumont", beds: 6, establishment: { day: 3, late: 3, night: 2 } },
  { ward: "linden", beds: 4, establishment: { day: 4, late: 3, night: 2 } },
  { ward: "corvid", beds: 4, establishment: { day: 2, late: 2, night: 1 } },
  { ward: "aster", beds: 3, establishment: { day: 2, late: 2, night: 1 } },
  { ward: "hollis", beds: 4, establishment: { day: 2, late: 2, night: 1 } },
];

/* The rota as authored on the ward board: three days out, three shifts a day,
   two wards. Tuples read [staff, day offset, shift] so the coverage is countable
   at a glance and every name is a real staff record. */
const ROTA = [
  ["stf_03", 0, "day", "beaumont"], ["stf_11", 0, "day", "beaumont"], ["stf_01", 0, "day", "beaumont"],
  ["stf_06", 0, "late", "beaumont"], ["stf_11", 0, "late", "beaumont"], ["stf_10", 0, "late", "beaumont"],
  ["stf_06", 0, "night", "beaumont"],
  ["stf_04", 0, "day", "linden"], ["stf_06", 0, "day", "linden"], ["stf_08", 0, "day", "linden"], ["stf_12", 0, "day", "linden"],
  ["stf_04", 0, "late", "linden"], ["stf_11", 0, "late", "linden"],
  ["stf_10", 0, "night", "linden"], ["stf_06", 0, "night", "linden"], ["stf_04", 0, "night", "linden"],
  ["stf_03", 1, "day", "beaumont"], ["stf_01", 1, "day", "beaumont"], ["stf_11", 1, "day", "beaumont"], ["stf_05", 1, "day", "beaumont"],
  ["stf_06", 1, "late", "beaumont"], ["stf_10", 1, "late", "beaumont"], ["stf_11", 1, "late", "beaumont"],
  ["stf_06", 1, "night", "beaumont"], ["stf_10", 1, "night", "beaumont"], ["stf_11", 1, "night", "beaumont"],
  ["stf_04", 1, "day", "linden"], ["stf_13", 1, "day", "linden"], ["stf_08", 1, "day", "linden"],
  ["stf_04", 1, "late", "linden"], ["stf_06", 1, "late", "linden"], ["stf_12", 1, "late", "linden"], ["stf_10", 1, "late", "linden"],
  ["stf_06", 1, "night", "linden"], ["stf_11", 1, "night", "linden"], ["stf_10", 1, "night", "linden"],
  ["stf_03", 2, "day", "beaumont"], ["stf_11", 2, "day", "beaumont"], ["stf_01", 2, "day", "beaumont"], ["stf_07", 2, "day", "beaumont"],
  ["stf_06", 2, "late", "beaumont"], ["stf_10", 2, "late", "beaumont"],
  ["stf_06", 2, "night", "beaumont"], ["stf_11", 2, "night", "beaumont"], ["stf_10", 2, "night", "beaumont"],
  ["stf_04", 2, "day", "linden"], ["stf_08", 2, "day", "linden"], ["stf_12", 2, "day", "linden"], ["stf_13", 2, "day", "linden"], ["stf_06", 2, "day", "linden"],
  ["stf_04", 2, "late", "linden"], ["stf_11", 2, "late", "linden"], ["stf_10", 2, "late", "linden"], ["stf_12", 2, "late", "linden"],
  ["stf_06", 2, "night", "linden"], ["stf_10", 2, "night", "linden"], ["stf_11", 2, "night", "linden"],
].map((row, index) => ({ id: "rot_" + (index + 1), staffId: row[0], day: row[1], shift: row[2], ward: row[3] }));

/* A theatre day is every room in THEATRES for eight hours: the denominator
   theatre utilisation is measured against. Derived, so adding a theatre to the
   enum moves the figure rather than leaving it stale. */
const THEATRE_MINUTES_PER_DAY = THEATRES.length * 8 * 60;

const NOTIFICATIONS = [
  { id: "ntf_01", title: "Bed wait past four hours", body: "Ruth Adeyemi has waited 5 hours for a monitored bed on Linden.", at: hoursAgo(1), route: "/admissions" },
  { id: "ntf_02", title: "Consent not recorded", body: "Farida Kettle is second on the day-case list at 14:00.", at: hoursAgo(0.6), route: "/interventions" },
  { id: "ntf_03", title: "Priya Raghunathan mentioned you", body: "On the morphine order for Callum Frayne.", at: hoursAgo(1), route: "/feed" },
  { id: "ntf_04", title: "Import needs review", body: "12 of 318 rows from the patient administration system could not be placed.", at: hoursAgo(21), route: "/data" },
];

const NOTIFICATION_PREFS = {
  quietHours: { from: "22:00", to: "07:00" },
  rows: [
    { id: "bed_wait", label: "A bed wait passes four hours", email: true, pager: true, inApp: true },
    { id: "consent", label: "A scheduled procedure has no consent recorded", email: false, pager: true, inApp: true },
    { id: "mention", label: "Somebody mentions you on a record", email: true, pager: false, inApp: true },
    { id: "import", label: "An import finishes with rows to review", email: true, pager: false, inApp: true },
    { id: "stock", label: "A formulary line drops below its reorder level", email: false, pager: false, inApp: true },
  ],
};

/* The reset link the /reset-password screen is standing behind. */
/* Settings the hospital has chosen. Each one has a real effect somewhere:
   the reference prefix names every invoice raised, the write-off threshold
   decides whether a balance can be written off here or has to be approved, an
   integration that is off is not offered in the import dialog, and the session
   timeout and two-factor rule are stated on the security screen. */
const BILLING_SETTINGS = {
  referencePrefix: "HG-2026",
  defaultPayer: "nhs_commissioner",
  writeOffThresholdMinor: 250000,
  approver: "Finance director",
};

const INTEGRATIONS = IMPORT_SOURCES.map((source, index) => ({
  source: source.value,
  enabled: index !== 2,
  autoAccept: index === 1,
}));

const SECURITY_SETTINGS = {
  sessionMinutes: 30,
  requireTwoFactor: true,
  passwordAgeDays: 180,
};

/* Signed-in sessions for the account the security screen belongs to. */
const SESSIONS = [
  { id: "ses_01", device: "Ward station, Beaumont nurses' base", browser: "Chrome on Windows", ip: "10.14.2.61", lastSeenAt: hoursAgo(0.1), current: true },
  { id: "ses_02", device: "Trust laptop", browser: "Edge on Windows", ip: "10.14.9.4", lastSeenAt: hoursAgo(26), current: false },
  { id: "ses_03", device: "Personal phone", browser: "Safari on iOS", ip: "82.14.66.201", lastSeenAt: daysAgo(4), current: false },
];

const HD_RESET_LINK = { email: "i.vance@haldengeneral.nhs.uk", issuedAt: hoursAgo(0.5), expiresInMinutes: 60 };

const PASSWORD_RULES = [
  { id: "length", label: "At least 12 characters", test: (v) => (v || "").length >= 12 },
  { id: "case", label: "An upper and a lower case letter", test: (v) => /[a-z]/.test(v || "") && /[A-Z]/.test(v || "") },
  { id: "number", label: "A number", test: (v) => /\d/.test(v || "") },
  { id: "name", label: "Not your name or your email address", test: (v) => !!v && !/vance|imogen/i.test(v) },
];

Object.assign(window, {
  HD_NOW, HD_HOSPITAL, HD_SIGNED_IN, STAFF, PATIENTS, ADMISSIONS, INTERVENTIONS, MEDICATION_ORDERS, FORMULARY,
  COMMENTS, ACTIVITY, TRANSFERS, TRANSFER_ROWS, INVOICES, PAYMENTS, TARIFF_ITEMS, CONTRACTS, CONTRACT_PRICES, COST_RATES, CHASES, WARD_BEDS, ROTA, THEATRE_MINUTES_PER_DAY, SESSIONS, BILLING_SETTINGS, INTEGRATIONS, SECURITY_SETTINGS, NOTIFICATIONS, NOTIFICATION_PREFS, HD_RESET_LINK, PASSWORD_RULES,
  hoursAgo, hoursOn, daysAgo, dayAt,
});
