import { useState } from "react";
import { clinicianApi } from "../../api/client";
import type { DeclineReason, Invitation } from "../../api/types";
import { formatDate } from "../../flow";
import { firstName, whenLabel } from "../../logic/format";
import { sharesLine, withLine } from "../../logic/patients";
import { Button, Checkbox, DialogActions, FieldError, Icon, labelClass, Modal, Radio, Textarea } from "../kit";
import { navigate } from "../router";
import { shortName, useClinician } from "../session";
import { errorText } from "../ui";

const reasons: { id: DeclineReason; label: string }[] = [
  { id: "not_my_patient", label: "Not my patient" },
  { id: "not_for_context", label: "I don't use Context for this" },
  { id: "other", label: "Another reason" },
];

/** INV-11 to INV-14: an invitation card with Decline and Accept. */
export function InvitationCard({ invitation, onDone }: { invitation: Invitation; onDone: (message: string) => void }) {
  const { me } = useClinician();
  const [dialog, setDialog] = useState<"accept" | "decline" | null>(null);
  const [confirmed, setConfirmed] = useState(false);
  const [link, setLink] = useState<"link" | "separate" | null>(null);
  const [reason, setReason] = useState<DeclineReason | null>(null);
  const [note, setNote] = useState("");
  const [error, setError] = useState("");
  const [busy, setBusy] = useState(false);
  const first = firstName(invitation.patientName);
  const match = invitation.possibleMatch;
  const close = () => {
    setDialog(null);
    setError("");
  };

  const accept = async () => {
    setBusy(true);
    setError("");
    try {
      const { patientId } = await clinicianApi.acceptInvitation(invitation.id, {
        confirmedMyPatient: true,
        linkToPatientId: match && link === "link" ? match.patientId : null,
      });
      navigate(`/app/patients/${patientId}`);
    } catch (e) {
      setError(errorText(e));
    } finally {
      setBusy(false);
    }
  };
  const decline = async () => {
    setBusy(true);
    setError("");
    try {
      await clinicianApi.declineInvitation(invitation.id, { reason, note: reason === "other" ? note.trim() || null : null });
      close();
      onDone(`Declined. ${first} sees: "${shortName(me)} couldn't accept your invite."`);
    } catch (e) {
      setError(errorText(e));
    } finally {
      setBusy(false);
    }
  };

  return (
    <article className="flex flex-wrap items-start gap-x-3.5 gap-y-3 rounded-2xl bg-page p-4 shadow-card">
      <span aria-hidden="true" className="flex size-9 shrink-0 items-center justify-center rounded-[10px] bg-indigo-fill text-indigo-icon">
        <Icon name="mail-open-line" size={18} />
      </span>
      <div className="flex min-w-0 flex-1 basis-60 flex-col gap-0.5">
        <b className="text-[14.5px] leading-5 font-medium text-ink">{invitation.patientName} invited you</b>
        <small className="text-[13px] leading-[18px] text-body">
          From MARMAR Health
          {invitation.withPerson ? ` · ${withLine(invitation.withPerson, invitation.patientPronoun)}` : ""} · {sharesLine(invitation.scopes)}
          {invitation.allowsCheckInCalls ? " · lets you ask Yasmar to check in" : ""}
        </small>
        <small className="text-[12.5px] leading-[18px] text-muted">
          Sent {whenLabel(invitation.sentAt)} · expires {formatDate(invitation.expiresAt.slice(0, 10))}
          {match ? ` · You have a clinic patient with the same name and date of birth` : ""}
        </small>
      </div>
      <div className="ml-auto flex gap-2 self-center">
        <Button onClick={() => setDialog("decline")}>Decline</Button>
        <Button variant="primary" onClick={() => setDialog("accept")}>
          Accept
        </Button>
      </div>

      <Modal open={dialog === "accept"} title={`Accept ${invitation.patientName}'s invite`} onClose={close}>
        <p className="m-0">
          You will see what {first} shares from MARMAR Health. {first} can pause or stop sharing at any time, and sees that
          you accepted.
        </p>
        <Checkbox checked={confirmed} onChange={(e) => setConfirmed(e.target.checked)}>
          <strong className="font-semibold text-ink">{invitation.patientName} is my patient.</strong>
        </Checkbox>
        {match && (
          <fieldset className="m-0 flex flex-col gap-2.5 rounded-xl border-0 bg-tile p-3.5">
            <legend className="float-left mb-1 p-0 text-[13px] leading-[19px] font-medium text-ink">
              You already have a clinic patient {match.name}
              {match.dateOfBirth ? `, born ${formatDate(match.dateOfBirth)}` : ""}. Is this the same person?
            </legend>
            <Radio name={`link-${invitation.id}`} checked={link === "link"} onChange={() => setLink("link")} className="clear-left">
              Yes, link them. The records you added stay, and the app data joins them.
            </Radio>
            <Radio name={`link-${invitation.id}`} checked={link === "separate"} onChange={() => setLink("separate")}>
              No, keep them separate.
            </Radio>
          </fieldset>
        )}
        {error && <FieldError>{error}</FieldError>}
        <DialogActions>
          <Button onClick={close}>Cancel</Button>
          <Button variant="primary" disabled={!confirmed || (!!match && !link) || busy} onClick={() => void accept()}>
            {busy ? "Accepting…" : "Accept and open"}
          </Button>
        </DialogActions>
      </Modal>

      <Modal open={dialog === "decline"} title={`Decline ${invitation.patientName}'s invite`} onClose={close}>
        <p className="m-0">
          {first} sees a kind message: "{shortName(me)} couldn't accept your invite." A reason is optional and only MARMAR
          sees it.
        </p>
        <fieldset className="m-0 flex flex-col gap-2.5 border-0 p-0">
          <legend className="mb-2 p-0 text-[12.5px] font-medium text-cell">Reason (optional)</legend>
          {reasons.map((r) => (
            <Radio key={r.id} name={`reason-${invitation.id}`} checked={reason === r.id} onChange={() => setReason(r.id)}>
              {r.label}
            </Radio>
          ))}
        </fieldset>
        {reason === "other" && (
          <label className={labelClass}>
            Tell us more (optional)
            <Textarea rows={2} maxLength={300} value={note} onChange={(e) => setNote(e.target.value)} />
          </label>
        )}
        {error && <FieldError>{error}</FieldError>}
        <DialogActions>
          <Button onClick={close}>Cancel</Button>
          <Button variant="primary" disabled={busy} onClick={() => void decline()}>
            {busy ? "Declining…" : "Decline invite"}
          </Button>
        </DialogActions>
      </Modal>
    </article>
  );
}

/** The patient's phone, always shared for connected patients so the clinic can call (INV-3). */
export const PhoneLink = ({ phone }: { phone: string }) => (
  <a className="phone-link" href={`tel:${phone.replace(/[^\d+]/g, "")}`}>
    <Icon name="phone-line" size={14} /> {phone}
  </a>
);
