/* Admissions and interventions — the ward board and the theatre list.
   Commit model: INSTANT on both screens. Consequential moves apply immediately
   and raise an undo toast; the two irreversible ones (discharging somebody,
   recording a procedure as abandoned) open a confirm dialog from App.jsx. The
   two creation actions are staged dialogs opened from these instant screens. */
(() => {
  const {
    Button, Badge, Checkbox, Alert, AlertTitle, AlertDescription, Avatar,
    Table, TableHeader, TableBody, TableRow, TableHead, TableCell,
  } = window.OriginDesignSystem_7c998b;

  const ADM_STATUS_FILTER = [{ value: "all", label: "All statuses" }].concat(ADMISSION_STATUS.map((s) => ({ value: s.id, label: s.label })));
  const ADM_WARD_FILTER = [{ value: "all", label: "All wards" }].concat(WARDS.map((w) => ({ value: w.value, label: wardName(w.value) })));
  const canMarkFit = (admission, viewer) => admissionTransitions(admission, viewer).some((t) => t.id === "mark_fit" && !t.disabled);

  function AdmissionsScreen({ data, now, viewer, onNavigate, onAdmissionTransition, onBulkMarkFit, onNewAdmission, onImport, onExport }) {
    const [query, setQuery] = React.useState("");
    const [status, setStatus] = React.useState("all");
    const [ward, setWard] = React.useState("all");
    const [selected, setSelected] = React.useState([]);
    const { sort, onSort } = useSort("clock", "asc");

    const dirty = !!query || status !== "all" || ward !== "all";
    const clear = () => { setQuery(""); setStatus("all"); setWard("all"); };
    const patientOf = (admission) => patientById(data.patients, admission.patientId);

    const filtered = data.admissions.filter((admission) => {
      if (status !== "all" && admission.status !== status) return false;
      if (ward !== "all" && admission.ward !== ward) return false;
      if (query) {
        const q = query.toLowerCase();
        const patient = patientOf(admission);
        if ((patient.name + " " + patient.number + " " + admission.reason + " " + (admission.bed || "")).toLowerCase().indexOf(q) < 0) return false;
      }
      return true;
    });
    const rows = sortRows(filtered, sort, {
      clock: (a) => a.admittedAt || a.requestedAt,
      patient: (a) => patientOf(a).name,
      stay: (a) => ADMISSION_FLAGS.lengthOfStayDays(a, now),
    });
    const chosen = data.admissions.filter((a) => selected.indexOf(a.id) > -1);
    const fitable = chosen.filter((a) => canMarkFit(a, viewer));

    return (
      <>
        <PageHeader
          path="/admissions"
          title="Admissions"
          sub={bedsWaiting(data.admissions).length + " waiting for a bed · " + onWard(data.admissions).length + " on the wards · " + fitForDischarge(data.admissions).length + " fit for discharge and still here"}
          actions={
            <>
              <ImportButton viewer={viewer} onImport={onImport} />
              <ExportMenu scope={dirty ? filtered.length + " admissions matching the filters" : "All " + data.admissions.length + " admissions"}
                onExport={(format) => onExport("Admissions", dirty ? "Filtered admissions" : "All admissions", filtered.length, format)} />
              <Button size="sm" onClick={onNewAdmission}><Icon name="plus" />New admission</Button>
            </>
          }
        />
        <Band flush>
          <FilterBar query={query} onQuery={setQuery} placeholder="Search patient, bed or reason…" dirty={dirty} onClear={clear}
            selects={[
              { id: "status", label: "Status", items: ADM_STATUS_FILTER, value: status, onChange: setStatus },
              { id: "ward", label: "Ward", items: ADM_WARD_FILTER, value: ward, onChange: setWard },
            ]} />
          <BulkBar count={chosen.length}
            note={fitable.length ? fitable.length + " of them can be marked fit for discharge" : "None of the selected admissions can be marked fit — that only applies to somebody already on a ward"}
            onClear={() => setSelected([])}>
            {fitable.length ? <Button size="sm" onClick={() => { onBulkMarkFit(fitable); setSelected([]); }}>Mark {fitable.length} fit for discharge</Button> : null}
            <ExportMenu scope={chosen.length + " selected admissions"} onExport={(format) => { onExport("Admission selection", chosen.map((a) => patientOf(a).name).join(", "), chosen.length, format); setSelected([]); }} />
          </BulkBar>
          {rows.length === 0 ? <NoResults noun="admissions" onClear={clear} /> : (
            <>
              <TableWrap>
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead style={{ width: 36 }}>
                        <Checkbox aria-label="Select every admission in this list"
                          checked={rows.length > 0 && rows.every((a) => selected.indexOf(a.id) > -1)}
                          indeterminate={selected.length > 0 && !rows.every((a) => selected.indexOf(a.id) > -1)}
                          onCheckedChange={(on) => setSelected(on ? rows.map((a) => a.id) : [])} />
                      </TableHead>
                      <TableHead><SortHead label="Patient" sortKey="patient" sort={sort} onSort={onSort} /></TableHead>
                      <TableHead>Status</TableHead>
                      <TableHead>Ward and bed</TableHead>
                      <TableHead>From</TableHead>
                      <TableHead><SortHead label="On the clock since" sortKey="clock" sort={sort} onSort={onSort} /></TableHead>
                      <TableHead className="hd-num"><SortHead label="Days" sortKey="stay" sort={sort} onSort={onSort} /></TableHead>
                      <TableHead>Consultant</TableHead>
                      <TableHead>Action</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {rows.map((admission) => {
                      const patient = patientOf(admission);
                      const waiting = admission.status === "awaiting_bed";
                      const over = ADMISSION_FLAGS.overExpectedStay(admission, now);
                      return (
                        <TableRow key={admission.id}>
                          <TableCell>
                            <Checkbox aria-label={"Select the admission for " + patient.name} checked={selected.indexOf(admission.id) > -1}
                              onCheckedChange={(on) => setSelected((list) => (on ? list.concat([admission.id]) : list.filter((id) => id !== admission.id)))} />
                          </TableCell>
                          <TableCell>
                            <PersonCell name={patient.name} avatar={patient.avatar} meta={patient.number + " · " + admission.reason}
                              onOpen={() => onNavigate("/patients/" + patient.id)} />
                          </TableCell>
                          <TableCell><StatusBadge values={ADMISSION_STATUS} value={admission.status} /></TableCell>
                          <TableCell>{admission.bed ? wardName(admission.ward) + " " + admission.bed : <span className="hd-muted">{wardName(admission.ward)} — no bed</span>}</TableCell>
                          <TableCell>{labelOf(ADMISSION_SOURCES, admission.source)}</TableCell>
                          <TableCell>
                            <Clock at={admission.admittedAt || admission.requestedAt} now={now} problem={waiting && ADMISSION_FLAGS.bedWaitBreached(admission, now)} />
                            {waiting ? <span className={ADMISSION_FLAGS.bedWaitBreached(admission, now) ? "hd-warn" : "hd-muted"}> · {formatCountdown(admission.requestedAt, now)}</span> : null}
                          </TableCell>
                          <TableCell className="hd-num">
                            <span className={over ? "hd-warn" : ""}>{admission.admittedAt ? ADMISSION_FLAGS.lengthOfStayDays(admission, now) : "—"}</span>
                            {admission.admittedAt ? <span className="hd-muted"> / {admission.expectedStayDays}</span> : null}
                          </TableCell>
                          <TableCell>{staffName(data.staff, admission.consultantId)}</TableCell>
                          <TableCell><RowActions transitions={admissionTransitions(admission, viewer)} onRun={(t) => onAdmissionTransition(admission, t)} label={"Actions for " + patient.name + "'s admission"} /></TableCell>
                        </TableRow>
                      );
                    })}
                  </TableBody>
                </Table>
              </TableWrap>
              <TableFoot shown={rows.length} total={data.admissions.length} noun="admissions" />
            </>
          )}
        </Band>
      </>
    );
  }

  const INT_STATUS_FILTER = [{ value: "all", label: "All statuses" }].concat(INTERVENTION_STATUS.map((s) => ({ value: s.id, label: s.label })));
  const INT_SPECIALTY_FILTER = [{ value: "all", label: "All specialties" }].concat(SPECIALTIES);

  function InterventionsScreen({ data, now, viewer, onNavigate, onInterventionTransition, onNewIntervention, onExport }) {
    const [query, setQuery] = React.useState("");
    const [status, setStatus] = React.useState("all");
    const [specialty, setSpecialty] = React.useState("all");
    const { sort, onSort } = useSort("scheduled", "asc");

    const dirty = !!query || status !== "all" || specialty !== "all";
    const clear = () => { setQuery(""); setStatus("all"); setSpecialty("all"); };
    const today = interventionsToday(data.interventions, now);
    const unscheduled = unscheduledInterventions(data.interventions);

    const filtered = data.interventions.filter((intervention) => {
      if (status !== "all" && intervention.status !== status) return false;
      if (specialty !== "all" && intervention.specialty !== specialty) return false;
      if (query) {
        const q = query.toLowerCase();
        const patient = patientById(data.patients, intervention.patientId);
        if ((intervention.name + " " + patient.name + " " + patient.number).toLowerCase().indexOf(q) < 0) return false;
      }
      return true;
    });
    const rows = sortRows(filtered, sort, {
      scheduled: (i) => i.scheduledAt || i.requestedAt,
      patient: (i) => patientById(data.patients, i.patientId).name,
      length: (i) => i.plannedMin,
    });

    return (
      <>
        <PageHeader
          path="/interventions"
          title="Interventions"
          sub={today.length + " in a theatre today · " + consentMissing(data.interventions).length + " without consent recorded · " + unscheduled.length + " requested and not yet scheduled"}
          actions={
            <>
              <ExportMenu scope={dirty ? filtered.length + " interventions matching the filters" : "All " + data.interventions.length + " interventions"}
                onExport={(format) => onExport("Interventions", dirty ? "Filtered interventions" : "All interventions", filtered.length, format)} />
              <Button size="sm" onClick={onNewIntervention}><Icon name="plus" />New intervention</Button>
            </>
          }
        />

        <Band title={"Theatre list, today (" + today.length + ")"} note="Scheduled for today and not cancelled, in time order. A procedure cannot start until consent is on the record.">
          <TheatreLadder rows={today} data={data} now={now} viewer={viewer} onNavigate={onNavigate} onInterventionTransition={onInterventionTransition} />
        </Band>

        <Band flush title={"Everything requested (" + data.interventions.length + ")"}>
          <FilterBar query={query} onQuery={setQuery} placeholder="Search procedure or patient…" dirty={dirty} onClear={clear}
            selects={[
              { id: "status", label: "Status", items: INT_STATUS_FILTER, value: status, onChange: setStatus },
              { id: "specialty", label: "Specialty", items: INT_SPECIALTY_FILTER, value: specialty, onChange: setSpecialty },
            ]} />
          {rows.length === 0 ? <NoResults noun="interventions" onClear={clear} /> : (
            <>
              <TableWrap>
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead>Procedure</TableHead>
                      <TableHead><SortHead label="Patient" sortKey="patient" sort={sort} onSort={onSort} /></TableHead>
                      <TableHead>Status</TableHead>
                      <TableHead>Priority</TableHead>
                      <TableHead>Theatre</TableHead>
                      <TableHead><SortHead label="Scheduled" sortKey="scheduled" sort={sort} onSort={onSort} /></TableHead>
                      <TableHead>Consent</TableHead>
                      <TableHead>Surgeon</TableHead>
                      <TableHead>Action</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {rows.map((intervention) => {
                      const patient = patientById(data.patients, intervention.patientId);
                      return (
                        <TableRow key={intervention.id}>
                          <TableCell>
                            <span className="hd-person__text">
                              <span className="hd-person__name"><button type="button" className="hd-linkbtn" onClick={() => onNavigate("/interventions/" + intervention.id)}>{intervention.name}</button></span>
                              <span className="hd-person__meta">{labelOf(SPECIALTIES, intervention.specialty)} · {intervention.plannedMin} min</span>
                            </span>
                          </TableCell>
                          <TableCell><PersonCell name={patient.name} avatar={patient.avatar} size={24} onOpen={() => onNavigate("/patients/" + patient.id)} /></TableCell>
                          <TableCell><StatusBadge values={INTERVENTION_STATUS} value={intervention.status} /></TableCell>
                          <TableCell>{labelOf(PRIORITIES, intervention.priority)}</TableCell>
                          <TableCell>{intervention.theatre ? labelOf(THEATRES, intervention.theatre) : <span className="hd-muted">Not allocated</span>}</TableCell>
                          <TableCell>{intervention.scheduledAt ? <Clock at={intervention.scheduledAt} now={now} /> : <span className="hd-warn">Not scheduled</span>}</TableCell>
                          <TableCell>{intervention.consentAt ? formatWhen(intervention.consentAt, now) : INTERVENTION_FLAGS.consentMissing(intervention) ? <Badge size="sm" variant="warning">Not recorded</Badge> : <span className="hd-muted">—</span>}</TableCell>
                          <TableCell>{staffName(data.staff, intervention.surgeonId)}</TableCell>
                          <TableCell><RowActions transitions={interventionTransitions(intervention, viewer)} onRun={(t) => onInterventionTransition(intervention, t)} label={"Actions for " + intervention.name} /></TableCell>
                        </TableRow>
                      );
                    })}
                  </TableBody>
                </Table>
              </TableWrap>
              <TableFoot shown={rows.length} total={data.interventions.length} noun="interventions" />
            </>
          )}
        </Band>
      </>
    );
  }

  function InterventionScreen({ data, now, viewer, interventionId, onNavigate, onInterventionTransition, onPostNote, onReactToNote, onExport }) {
    const intervention = data.interventions.find((i) => i.id === interventionId);
    const patient = patientById(data.patients, intervention.patientId);
    const notes = commentsFor(data.comments, "intervention", intervention.id);
    const noConsent = INTERVENTION_FLAGS.consentMissing(intervention);

    return (
      <>
        <PageHeader path="/interventions/:id" params={{ id: intervention.id }} crumb={intervention.name} title={intervention.name}
          actions={<ExportMenu scope={"This procedure and its " + notes.length + " notes"} onExport={(format) => onExport("Intervention record", intervention.name + " · " + patient.name, 1, format)} />} />

        <div className="hd-record">
          <div className="hd-record__id">
            <Avatar size={56} src={patient.avatar} alt={"Photograph of " + patient.name} fallback={initialsOf(patient.name)} />
            <div className="hd-record__text">
              <span className="hd-record__name">{patient.name}</span>
              <span className="hd-record__meta">
                <button type="button" className="hd-linkbtn" onClick={() => onNavigate("/patients/" + patient.id)}>{patient.number}</button>
                <span>{labelOf(PRIORITIES, intervention.priority)}</span>
                <StatusBadge values={INTERVENTION_STATUS} value={intervention.status} />
                <AllergyChips patient={patient} />
              </span>
            </div>
          </div>
          <div className="hd-record__actions">
            <Transitions transitions={interventionTransitions(intervention, viewer)} onRun={(t) => onInterventionTransition(intervention, t)} />
          </div>
        </div>

        {noConsent ? (
          <div className="hd-alertwrap">
            <Alert variant="warning">
              <AlertTitle>Consent is not on the record</AlertTitle>
              <AlertDescription>
                {intervention.scheduledAt
                  ? "This is booked for " + formatWhen(intervention.scheduledAt, now) + " and cannot start until the clinician taking consent records it here."
                  : "Nothing can be booked until the clinician taking consent records it here."}
              </AlertDescription>
            </Alert>
          </div>
        ) : null}

        <Band title="The procedure" note={intervention.notes}>
          <Pairs items={[
            { label: "Specialty", value: labelOf(SPECIALTIES, intervention.specialty) },
            { label: "Theatre", value: intervention.theatre ? labelOf(THEATRES, intervention.theatre) : "Not allocated" },
            { label: "Scheduled", value: intervention.scheduledAt ? formatWhen(intervention.scheduledAt, now) + " · " + formatCountdown(intervention.scheduledAt, now) : "Not scheduled" },
            { label: "Planned length", value: intervention.plannedMin + " minutes" },
            { label: "Requested", value: <Clock at={intervention.requestedAt} now={now} /> },
            { label: "Consent recorded", value: intervention.consentAt ? formatWhen(intervention.consentAt, now) : "Not recorded" },
            { label: "Surgeon", value: staffName(data.staff, intervention.surgeonId) },
            { label: "Anaesthetist", value: intervention.anaesthetistId ? staffName(data.staff, intervention.anaesthetistId) : "Not allocated" },
            { label: "Completed", value: intervention.completedAt ? formatWhen(intervention.completedAt, now) : "Not yet" },
          ]} />
        </Band>

        <Band title={"Notes (" + notes.length + ")"} note="Written on this procedure. Posting is immediate.">
          <NoteThread comments={notes} staff={data.staff} viewer={viewer} now={now}
            onReact={onReactToNote} onPost={(body) => onPostNote({ type: "intervention", id: intervention.id }, body)}
            placeholder="Anything theatre or the ward needs to know…" />
        </Band>
      </>
    );
  }

  Object.assign(window, { AdmissionsScreen, InterventionsScreen, InterventionScreen, canMarkFit });
})();
