/* Wards and beds · the rota · the drug round.
   Commit model: INSTANT on all three. Assigning a bed and recording a dose apply
   immediately with an undo toast; nothing here is staged.

   Card variants used, and why: the default card for a titled region, --tint for
   a shift nobody has filled yet and for supporting detail, --fill where cards sit
   side by side and their footers should line up, --flush where a table bleeds to
   the card edge. */
(() => {
  const {
    Button, Badge, Select, Avatar, Alert, AlertTitle, AlertDescription,
    Table, TableHeader, TableBody, TableRow, TableHead, TableCell,
  } = window.OriginDesignSystem_7c998b;

  /* One pip per bed: occupancy as a shape, not only a number. Every pip is a bed
     the ward establishment says exists. */
  function BedGrid({ ward }) {
    const pips = [];
    for (let i = 0; i < ward.beds; i++) {
      const state = i < ward.occupied - ward.held ? "occupied" : i < ward.occupied ? "held" : "free";
      pips.push(<span className="hd-bed" key={i} data-state={state} />);
    }
    const label = ward.occupied + " of " + ward.beds + " beds occupied on " + ward.label + ", " + ward.held + " held for somebody fit to go home";
    return (
      <span className="hd-beds" role="img" aria-label={label}>{pips}</span>
    );
  }

  function WardsScreen({ data, now, viewer, onNavigate, onAdmissionTransition, onExport }) {
    const wards = wardRows(data.admissions, data.wardBeds);
    const beds = data.wardBeds.reduce((n, b) => n + b.beds, 0);
    const occupied = wards.reduce((n, w) => n + w.occupied, 0);
    const free = wards.reduce((n, w) => n + w.free, 0);
    const held = wards.reduce((n, w) => n + w.held, 0);
    const waiting = bedsWaiting(data.admissions);
    const [ward, setWard] = React.useState(viewer.ward || WARDS[0].value);
    const chosen = wards.find((w) => w.ward === ward);
    const onShift = rotaFor(data.rota, 0, ward, "day");

    return (
      <>
        <PageHeader
          path="/wards"
          title="Wards and beds"
          sub={"Five wards and the " + beds + " beds Ward Desk covers. Occupancy is counted from the admissions each ward renders, against the bed count in the ward record."}
          actions={<ExportMenu scope={"Bed state across all " + WARDS.length + " wards"} onExport={(format) => onExport("Ward and bed state", "Every ward", wards.length, format)} />}
        />
        <Figures items={[
          { label: "Beds occupied", value: occupied, qualifier: "of " + beds + " · " + Math.round((occupied / beds) * 100) + "% of the hospital" },
          { label: "Beds free", value: free, qualifier: waiting.length + (waiting.length === 1 ? " person is waiting for one" : " people are waiting for one") },
          { label: "Held for a discharge", value: held, qualifier: held ? "occupied by somebody already fit to go home" : "nobody fit to go home is still in a bed" },
          /* The qualifier decomposes this figure's own set and nothing else: each
             request, the ward it was made onto, and how long it has waited. Why a
             wait persists beside a free bed is not in the fixture, so this does not
             claim it. */
          { label: "Waiting for a bed", value: waiting.length, qualifier: waiting.length
            ? waiting.slice().sort((a, b) => a.requestedAt - b.requestedAt)
                .map((a) => wardName(a.ward) + ", " + formatCountdown(a.requestedAt, now).replace(" over", "").replace(" left", ""))
                .join(" · ")
            : "every request has a bed against it" },
        ]} />

        <Band title="The board" note="One card per ward: a pip per bed, dark for occupied, amber where the bed is held for somebody fit to go home.">
          <div className="hd-ward">
            {wards.map((w) => (
              <div className="hd-ward__cell" key={w.ward}>
                <span className="hd-ward__top">
                  <span className="hd-ward__name">{w.label}</span>
                  <span className="hd-ward__count">{w.occupied}<span className="hd-footnote"> / {w.beds}</span></span>
                </span>
                <BedGrid ward={w} />
                <span className="hd-footnote">
                  {w.specialty} · {w.free} free
                  {w.waiting ? " · " + w.waiting + " waiting" : ""}
                  {w.held ? " · " + w.held + " held" : ""}
                </span>
                <Button variant="outline" size="xs" onClick={() => setWard(w.ward)}>Open {w.label}</Button>
              </div>
            ))}
          </div>
        </Band>

        <div className="hd-cols hd-cols--wide">
          <div>
            <Band flush fill title={chosen.label + " — who is in it (" + chosen.rows.length + ")"}
              note={"Occupied beds and outstanding requests on " + chosen.label + ", " + chosen.specialty + "."}
              actions={
                <span className="hd-filters__select">
                  <Select size="sm" aria-label="Ward" items={WARDS.map((w) => ({ value: w.value, label: wardName(w.value) }))} value={ward} onValueChange={setWard} />
                </span>
              }>
              {chosen.rows.length ? (
                <TableWrap>
                  <Table>
                    <TableHeader>
                      <TableRow>
                        <TableHead>Bed</TableHead>
                        <TableHead>Patient</TableHead>
                        <TableHead>Status</TableHead>
                        <TableHead>Day</TableHead>
                        <TableHead>Consultant</TableHead>
                        <TableHead>Action</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody>
                      {chosen.rows.map((admission) => {
                        const patient = patientById(data.patients, admission.patientId);
                        return (
                          <TableRow key={admission.id}>
                            <TableCell>{admission.bed || <span className="hd-warn">No bed</span>}</TableCell>
                            <TableCell>
                              <PersonCell name={patient.name} avatar={patient.avatar} size={24} meta={patient.number}
                                onOpen={() => onNavigate("/patients/" + patient.id)} />
                            </TableCell>
                            <TableCell><StatusBadge values={ADMISSION_STATUS} value={admission.status} /></TableCell>
                            <TableCell className="hd-num">{admission.admittedAt ? ADMISSION_FLAGS.lengthOfStayDays(admission, now) : "—"}</TableCell>
                            <TableCell>{staffName(data.staff, admission.consultantId)}</TableCell>
                            <TableCell><RowActions transitions={admissionTransitions(admission, viewer)} onRun={(t) => onAdmissionTransition(admission, t)} label={"Actions for " + patient.name} /></TableCell>
                          </TableRow>
                        );
                      })}
                    </TableBody>
                  </Table>
                </TableWrap>
              ) : <p className="hd-footnote" style={{ paddingInline: "var(--card-pad)" }}>{chosen.label} is empty — {chosen.beds} beds and nobody in them.</p>}
            </Band>
          </div>
          <div>
            <Band tint fill title={"On " + chosen.label + " today"} note={"The day shift, 07:00–15:00. The establishment asks for " + chosen.establishment.day + "."}>
              <div className="hd-rows">
                {onShift.length ? onShift.map((entry) => {
                  const person = staffById(data.staff, entry.staffId);
                  return (
                    <div className="hd-row" key={entry.id}>
                      <PersonCell name={person.name} avatar={person.avatar} size={28} meta={person.jobTitle}
                        onOpen={() => onNavigate((person.family === "medical" ? "/doctors/" : "/employees/") + person.id)} />
                    </div>
                  );
                }) : <p className="hd-footnote">Nobody is rostered onto {chosen.label} today.</p>}
              </div>
              <p className="hd-footnote" style={{ marginTop: "var(--space-3)" }}>
                {onShift.length >= chosen.establishment.day
                  ? "Fully staffed for the day shift."
                  : (chosen.establishment.day - onShift.length) + " short of the establishment for the day shift."}
                {" "}<button type="button" className="hd-linkbtn" onClick={() => onNavigate("/rota")}>Open the rota</button>
              </p>
            </Band>
          </div>
        </div>
      </>
    );
  }

  /* The rota is a grid rather than a table: the question it answers is "is this
     shift covered", which a row of names cannot show. */
  function RotaScreen({ data, now, viewer, onNavigate, onExport }) {
    const [ward, setWard] = React.useState(viewer.ward || rotaWards(data.rota)[0].value);
    const days = [0, 1, 2];
    const capacity = wardBedsOf(data.wardBeds, ward);
    const thin = understaffedShifts(data.rota, data.wardBeds, days);
    const thinHere = thin.filter((s) => s.ward === ward);
    const rosteredHere = data.rota.filter((r) => r.ward === ward && days.indexOf(r.day) > -1);
    const people = rosteredHere.reduce((list, r) => (list.indexOf(r.staffId) > -1 ? list : list.concat([r.staffId])), []);

    return (
      <>
        <PageHeader
          path="/rota"
          title="Rota"
          sub={"Three days out, three shifts a day. A shift is short when fewer people are rostered onto it than the ward establishment asks for."}
          actions={<ExportMenu scope={rosteredHere.length + " shifts on " + wardName(ward) + " over three days"} onExport={(format) => onExport("Rota", wardName(ward) + " ward, three days", rosteredHere.length, format)} />}
        />
        <Figures three items={[
          { label: "Shifts short of establishment", value: thin.length, qualifier: thinHere.length + " of them on " + wardName(ward) },
          { label: "People rostered here", value: people.length, qualifier: "across " + rosteredHere.length + " shifts on " + wardName(ward) },
          { label: "People short in total", value: thin.reduce((n, s) => n + s.shortfall, 0), qualifier: thin.length ? "summed over every short shift on both wards" : "every shift meets its establishment" },
        ]} />

        {thinHere.length ? (
          <div className="hd-alertwrap">
            <Alert variant="warning">
              <AlertTitle>{thinHere.length === 1 ? "One shift on " + wardName(ward) + " is short" : thinHere.length + " shifts on " + wardName(ward) + " are short"}</AlertTitle>
              <AlertDescription>
                {thinHere.map((s) => (s.day === 0 ? "Today" : new Date(now + s.day * DAY_MS).toLocaleDateString("en-GB", { weekday: "long" })) + " " + labelOf(SHIFT_TYPES, s.shift).split(",")[0].toLowerCase() + ", " + s.shortfall + " short").join(" · ")}.
              </AlertDescription>
            </Alert>
          </div>
        ) : null}

        <Band title={wardName(ward) + " — three days"} note={"The establishment is " + SHIFT_TYPES.map((s) => s.label.split(",")[0].toLowerCase() + " " + capacity.establishment[s.value]).join(", ") + "."}
          actions={
            <span className="hd-filters__select">
              <Select size="sm" aria-label="Ward" items={rotaWards(data.rota).map((w) => ({ value: w.value, label: wardName(w.value) }))} value={ward} onValueChange={setWard} />
            </span>
          }>
          <div className="hd-rota">
            <div className="hd-rota__head">
              <span>Day</span>
              {SHIFT_TYPES.map((shift) => <span key={shift.value}>{shift.label}</span>)}
            </div>
            {days.map((day) => (
              <div className="hd-rota__day" key={day}>
                <span className="hd-rota__label">
                  {day === 0 ? "Today" : new Date(now + day * DAY_MS).toLocaleDateString("en-GB", { weekday: "long" })}
                  <span className="hd-footnote">{new Date(now + day * DAY_MS).toLocaleDateString("en-GB", { day: "numeric", month: "short" })}</span>
                </span>
                {SHIFT_TYPES.map((shift) => {
                  const rostered = rotaFor(data.rota, day, ward, shift.value);
                  const establishment = capacity.establishment[shift.value];
                  const short = SHIFT_FLAGS.understaffed(rostered, establishment);
                  return (
                    <div className="hd-rota__cell" key={shift.value} data-thin={short ? "true" : "false"}>
                      <span className="hd-rota__shift">
                        {rostered.length} of {establishment}
                        {short ? " · " + SHIFT_FLAGS.shortfall(rostered, establishment) + " short" : " · covered"}
                      </span>
                      {rostered.map((entry) => {
                        const person = staffById(data.staff, entry.staffId);
                        return (
                          <PersonCell key={entry.id} size={22} name={person.name} avatar={person.avatar} meta={person.jobTitle}
                            onOpen={() => onNavigate((person.family === "medical" ? "/doctors/" : "/employees/") + person.id)} />
                        );
                      })}
                      {rostered.length ? null : <span className="hd-footnote">Nobody rostered.</span>}
                    </div>
                  );
                })}
              </div>
            ))}
          </div>
        </Band>
      </>
    );
  }

  /* The drug round: active orders grouped by where their clock has got to, so a
     nurse works down one card at a time. */
  function RoundsScreen({ data, now, viewer, onNavigate, onMedicationTransition, onExport }) {
    const groups = roundGroups(data.orders, now);
    const due = dosesDue(data.orders, now);
    const missed = dosesMissed(data.orders, now);
    const given = dosesGivenSince(data.orders, now, 8);
    const active = activeOrders(data.orders);

    return (
      <>
        <PageHeader
          path="/rounds"
          title="Drug round"
          sub={"Every verified course with a dose on the clock. Recording a dose moves its next dose by the interval its frequency states."}
          actions={<ExportMenu scope={active.length + " active courses with a dose clock"} onExport={(format) => onExport("Drug round", "Active courses, all wards", active.length, format)} />}
        />
        <Figures items={[
          { label: "Overdue", value: missed.length, qualifier: missed.length ? "due more than an hour ago" : "nothing has been missed" },
          { label: "Due within the hour", value: due.filter((o) => !MEDICATION_FLAGS.doseMissed(o, now)).length, qualifier: "the round you are on" },
          { label: "Given in the last 8 hours", value: given.length, qualifier: "of " + active.length + " active courses" },
          { label: "Awaiting a pharmacist", value: ordersAwaitingPharmacy(data.orders).length, qualifier: "not on the round until they are verified" },
        ]} />

        {groups.map((group) => (
          <Band key={group.id} tint={group.id === "later"} title={group.label + " (" + group.rows.length + ")"} note={group.note}>
            {group.rows.length ? (
              <div className="hd-rows">
                {group.rows.map((order) => {
                  const patient = patientById(data.patients, order.patientId);
                  const admission = admissionOfPatient(data.admissions, order.patientId);
                  return (
                    <div className={"hd-row" + (group.id === "later" ? " hd-row--quiet" : "")} key={order.id}>
                      <span className="hd-row__time">{new Date(order.nextDoseAt).toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit" })}</span>
                      <div className="hd-row__text">
                        <span className="hd-row__title">
                          <PersonCell name={patient.name} avatar={patient.avatar} size={26}
                            meta={(admission && admission.bed ? wardName(admission.ward) + " " + admission.bed : "Not on a ward") + " · " + patient.number}
                            onOpen={() => onNavigate("/patients/" + patient.id)} />
                        </span>
                        <span className="hd-row__note">
                          {order.drug} {order.dose} · {labelOf(DRUG_ROUTES, order.route)} · {order.frequency.toLowerCase()} · {order.indication}
                          {order.lastGivenAt ? " · last given " + formatWhen(order.lastGivenAt, now) : " · never given"}
                        </span>
                      </div>
                      <AllergyChips patient={patient} />
                      {MEDICATION_FLAGS.doseMissed(order, now) ? <Badge size="sm" variant="warning">{formatCountdown(order.nextDoseAt, now)}</Badge> : null}
                      <Transitions transitions={medicationTransitions(order, viewer).filter((t) => t.id === "record_dose")} onRun={(t) => onMedicationTransition(order, t)} />
                    </div>
                  );
                })}
              </div>
            ) : (
              <p className="hd-footnote">
                {group.id === "overdue" ? "Nothing is overdue. Every dose due before this hour has been recorded as given." : group.id === "now" ? "Nothing is due in this hour." : "Nothing further is due before midnight."}
              </p>
            )}
          </Band>
        ))}
      </>
    );
  }

  Object.assign(window, { WardsScreen, RotaScreen, RoundsScreen, BedGrid });
})();
