import { useEffect, useMemo, useState } from "react";
import { clinicianApi } from "../../api/client";
import { asOfLabel } from "../../logic/format";
import { searchPatients, sortPatients } from "../../logic/patients";
import { needsAttention } from "../../logic/today";
import { Button, Count, EmptyState, Icon, SearchField, SectionHeader, Segmented } from "../kit";
import { useLocation } from "../router";
import Shell from "../Shell";
import { ErrorNote, Spinner, useLoad, useToast } from "../ui";
import { InvitationCard } from "./Invitations";
import { NewPatient } from "./NewPatient";
import { PatientTable } from "./PatientTable";
import { PatientTile } from "./PatientTile";

type Show = "all" | "needs";
const showFrom = (param: string | null): Show => (param === "needs-you" ? "needs" : "all");

/** PAT-2: invitations first, then patients by what needs attention, with search and a Needs you filter. */
export default function PatientsPage() {
  const { query: params } = useLocation();
  const invitations = useLoad(() => clinicianApi.invitations(), []);
  const patients = useLoad(() => clinicianApi.patients(), []);
  const [query, setQuery] = useState("");
  const [show, setShow] = useState<Show>(() => showFrom(params.get("show")));
  const [adding, setAdding] = useState(false);
  const toast = useToast();
  // Each navigation (the sidebar link, Today's "See all") sets the filter from the address again.
  useEffect(() => setShow(showFrom(params.get("show"))), [params]);
  useEffect(() => {
    const t = setInterval(() => patients.reload(true), 30_000);
    return () => clearInterval(t);
  }, [patients.reload]);
  const all = useMemo(() => sortPatients(patients.data?.patients ?? []), [patients.data]);
  const needs = useMemo(() => all.filter(needsAttention), [all]);
  const list = useMemo(() => searchPatients(show === "needs" ? needs : all, query), [all, needs, show, query]);
  const pending = invitations.data?.invitations ?? [];
  const pick = (next: Show) => {
    setShow(next);
    // The filter keeps its own address without a new history entry or a jump to the top.
    history.replaceState(history.state, "", next === "needs" ? "/app/patients?show=needs-you" : "/app/patients");
  };

  return (
    <Shell crumbs={[{ label: "Patients" }]} active="patients">
      <div className="flex flex-col gap-6 pb-12 md:pt-2">
        <header className="flex flex-wrap items-end justify-between gap-4">
          <div className="flex min-w-0 max-w-2xl flex-col gap-1.5">
            <h1 className="m-0 flex items-center gap-2.5 text-[26px] leading-8 font-semibold tracking-[-0.02em] text-ink md:text-[30px] md:leading-9">
              Patients
              {patients.data && <Count className="h-[22px] min-w-[22px] text-[12px]">{all.length}</Count>}
            </h1>
            <p className="m-0 text-[14px] leading-5 text-muted">
              People who invited you from MARMAR Health, and patients you added. Those who need you most come first.
            </p>
          </div>
          <Button onClick={() => setAdding(true)}>
            <Icon name="add-line" size={16} />
            Add a patient
          </Button>
        </header>
        {toast.node}
        <ErrorNote error={invitations.error} onRetry={() => invitations.reload()} />
        {pending.length > 0 && (
          <section aria-label="Invitations" className="flex flex-col gap-3">
            <SectionHeader title="Invitations" count={pending.length} />
            {pending.map((inv) => (
              <InvitationCard
                key={inv.id}
                invitation={inv}
                onDone={(message) => {
                  toast.show(message);
                  invitations.reload(true);
                }}
              />
            ))}
          </section>
        )}
        <section aria-label="Your patients" className="flex flex-col gap-3">
          <div className="flex flex-wrap items-center gap-3">
            <h2 className="m-0 mr-auto flex items-center gap-2 text-[15px] leading-5 font-semibold tracking-[-0.01em] text-ink">
              <Icon name="team-line" size={16} className="text-grey-icon" />
              Your patients
              {patients.data && <Count>{list.length}</Count>}
            </h2>
            <Segmented
              label="Show"
              value={show}
              onChange={pick}
              options={[
                { value: "all", label: "All" },
                { value: "needs", label: needs.length ? `Needs you · ${needs.length}` : "Needs you" },
              ]}
            />
            <SearchField label="Search patients by name" placeholder="Search by name" value={query} onChange={setQuery} className="w-full sm:w-64" />
          </div>
          {patients.loading && !patients.data && <Spinner label="Loading patients" />}
          <ErrorNote error={patients.error} onRetry={() => patients.reload()} />
          {patients.data && !list.length && (
            <EmptyState
              title={query ? `No patient matches "${query}".` : show === "needs" ? "Nobody needs you right now." : "No patients yet."}
              body={
                query
                  ? undefined
                  : show === "needs"
                    ? "Urgent notes, unread check-in notes and new information since your last check show here."
                    : "Invitations from MARMAR Health appear above."
              }
              action={
                show === "needs" ? (
                  <Button size="sm" onClick={() => pick("all")}>
                    Show all patients
                  </Button>
                ) : undefined
              }
            />
          )}
          {list.length > 0 && (
            <>
              <div className="hidden md:block">
                <PatientTable patients={list} />
              </div>
              <div className="flex flex-col gap-2.5 md:hidden">
                {list.map((p) => (
                  <PatientTile key={p.id} patient={p} />
                ))}
              </div>
            </>
          )}
          {patients.data && <p className="m-0 text-[12px] text-subtle">Updated {asOfLabel(patients.data.asOf)}</p>}
        </section>
      </div>
      <NewPatient open={adding} onClose={() => setAdding(false)} />
    </Shell>
  );
}
