import { CheckCircle, EnvelopeSimple, Info } from "@phosphor-icons/react";
import { useState } from "react";
import type { FormEvent } from "react";
import { clinicianApi } from "../../api/client";
import type { AccessRequestReceipt, InvitePreview } from "../../api/types";
import {
  countries,
  emptyAccessForm,
  heardFromLabels,
  prefillFromInvite,
  toAccessRequest,
  validateAccess,
  type AccessErrors,
  type AccessForm,
} from "../../logic/access";
import { siteWords } from "../../logic/site";
import { Link } from "../router";
import { errorText, Field } from "../ui";
import { SiteLayout } from "./Landing";

/** ACC-3: the request form, pre-filled from a patient's invite when there is one (ACC-4). */
export function RequestAccessForm({ invite, inviteToken }: { invite: InvitePreview | null; inviteToken: string | null }) {
  const [form, setForm] = useState<AccessForm>(() => (invite ? prefillFromInvite(emptyAccessForm(), invite) : emptyAccessForm()));
  const [errors, setErrors] = useState<AccessErrors>({});
  const [sending, setSending] = useState(false);
  const [failure, setFailure] = useState("");
  const [receipt, setReceipt] = useState<AccessRequestReceipt | null>(null);
  const set = <K extends keyof AccessForm>(key: K, value: AccessForm[K]) => {
    setForm((f) => ({ ...f, [key]: value }));
    if (errors[key]) setErrors((e) => ({ ...e, [key]: undefined }));
  };
  const submit = async (e: FormEvent) => {
    e.preventDefault();
    const found = validateAccess(form);
    setErrors(found);
    const first = Object.keys(found)[0];
    if (first) {
      document.getElementById(`acc-${first}`)?.focus();
      return;
    }
    setSending(true);
    setFailure("");
    try {
      setReceipt(await clinicianApi.requestAccess(toAccessRequest(form, inviteToken)));
    } catch (error) {
      setFailure(errorText(error));
    } finally {
      setSending(false);
    }
  };
  const props = (key: keyof AccessForm) => ({
    id: `acc-${key}`,
    "aria-invalid": errors[key] ? true : undefined,
    "aria-describedby": errors[key] ? `acc-${key}-error` : undefined,
  });

  if (receipt)
    return (
      <div className="receipt" role="status">
        <CheckCircle size={28} weight="fill" />
        <h2>Request sent</h2>
        <p>
          We sent a confirmation to <strong>{form.workEmail.trim()}</strong>.{" "}
          {siteWords().receiptNext(form.profession === "doctor" ? "MDCN" : "PCN")}
        </p>
        {receipt.priority && invite && (
          <p>
            Because {invite.patientName} invited you, your request is near the front of the queue. The invite waits for you
            until you are verified.
          </p>
        )}
        {!receipt.countryOpen && (
          <p className="hint">Approvals in your country open once its regulatory and data checks are done. We keep your request until then.</p>
        )}
        <a className="button" href="/demo">
          Try a fictional patient meanwhile
        </a>
      </div>
    );

  return (
    <form className="access-form" onSubmit={submit} noValidate>
      <fieldset>
        <legend>You</legend>
        <Field id="acc-fullName" label="Full name" error={errors.fullName} hint="As it appears on your licence.">
          <input {...props("fullName")} autoComplete="name" value={form.fullName} onChange={(e) => set("fullName", e.target.value)} />
        </Field>
        <div className="field" role="radiogroup" aria-labelledby="acc-profession-label">
          <span className="label" id="acc-profession-label">
            Profession
          </span>
          <div className="choice-row">
            {(["doctor", "pharmacist"] as const).map((p, i) => (
              <label key={p} className={`choice ${form.profession === p ? "on" : ""}`}>
                <input
                  type="radio"
                  name="profession"
                  id={i === 0 ? "acc-profession" : undefined}
                  checked={form.profession === p}
                  onChange={() => set("profession", p)}
                />
                {p === "doctor" ? "Doctor (MDCN)" : "Pharmacist (PCN)"}
              </label>
            ))}
          </div>
          {errors.profession && (
            <small className="field-error" role="alert">
              {errors.profession}
            </small>
          )}
        </div>
        <Field
          id="acc-licenceNumber"
          label={form.profession === "pharmacist" ? "PCN registration number" : "MDCN folio number"}
          error={errors.licenceNumber}
          hint={form.profession === "pharmacist" ? "From your PCN licence." : "For example MDCN/R/123456."}
        >
          <input {...props("licenceNumber")} value={form.licenceNumber} autoCapitalize="characters" onChange={(e) => set("licenceNumber", e.target.value)} />
        </Field>
        <Field id="acc-workEmail" label="Work email" error={errors.workEmail} hint="We send your sign-in codes here.">
          <input {...props("workEmail")} type="email" autoComplete="email" inputMode="email" value={form.workEmail} onChange={(e) => set("workEmail", e.target.value)} />
        </Field>
        <Field id="acc-mobile" label="Mobile number" error={errors.mobile}>
          <input {...props("mobile")} type="tel" autoComplete="tel" inputMode="tel" placeholder="+234" value={form.mobile} onChange={(e) => set("mobile", e.target.value)} />
        </Field>
      </fieldset>
      <fieldset>
        <legend>Your clinic</legend>
        <Field id="acc-clinicName" label="Clinic or facility name" error={errors.clinicName}>
          <input {...props("clinicName")} autoComplete="organization" value={form.clinicName} onChange={(e) => set("clinicName", e.target.value)} />
        </Field>
        <Field id="acc-clinicPhone" label="Clinic phone" error={errors.clinicPhone} hint="Shown to patients after a check-in.">
          <input {...props("clinicPhone")} type="tel" inputMode="tel" placeholder="+234" value={form.clinicPhone} onChange={(e) => set("clinicPhone", e.target.value)} />
        </Field>
        <Field id="acc-country" label="Country" error={errors.country} hint={countries.find((c) => c.code === form.country)?.open ? undefined : "Requests from this country wait until its checks are done."}>
          <select {...props("country")} value={form.country} onChange={(e) => set("country", e.target.value)}>
            {countries.map((c) => (
              <option key={c.code} value={c.code}>
                {c.name}
              </option>
            ))}
          </select>
        </Field>
        <Field id="acc-heardFrom" label="How did you hear about Context?" error={errors.heardFrom}>
          <select {...props("heardFrom")} value={form.heardFrom} onChange={(e) => set("heardFrom", e.target.value as AccessForm["heardFrom"])}>
            <option value="">Choose one</option>
            {Object.entries(heardFromLabels).map(([value, label]) => (
              <option key={value} value={value}>
                {label}
              </option>
            ))}
          </select>
        </Field>
        {form.heardFrom === "other" && (
          <Field id="acc-heardFromOther" label="Where?" error={errors.heardFromOther}>
            <input {...props("heardFromOther")} value={form.heardFromOther} onChange={(e) => set("heardFromOther", e.target.value)} />
          </Field>
        )}
      </fieldset>
      <label className={`check terms ${errors.acceptedTerms ? "has-error" : ""}`}>
        <input
          type="checkbox"
          id="acc-acceptedTerms"
          checked={form.acceptedTerms}
          aria-invalid={errors.acceptedTerms ? true : undefined}
          onChange={(e) => set("acceptedTerms", e.target.checked)}
        />
        <span>
          I accept the <a href="/terms/clinician" target="_blank" rel="noreferrer">clinician terms</a>. Context shows
          information and its source; I make the clinical decisions.
        </span>
      </label>
      {errors.acceptedTerms && (
        <small className="field-error" role="alert">
          {errors.acceptedTerms}
        </small>
      )}
      {failure && (
        <div className="banner error" role="alert">
          <Info size={16} />
          <div>{failure}</div>
        </div>
      )}
      <div className="form-actions">
        <button className="button primary large" disabled={sending}>
          <EnvelopeSimple size={16} />
          {sending ? "Sending…" : "Send request"}
        </button>
        <span className="hint">Takes about two minutes. We confirm by email.</span>
      </div>
    </form>
  );
}

export default function RequestAccess() {
  const intro = siteWords().requestIntro;
  return (
    <SiteLayout>
      <div className="narrow">
        <header className="page-head">
          <h1>Request access</h1>
          {intro && <p className="lead">{intro}</p>}
          <p>
            For doctors registered with the MDCN and pharmacists registered with the PCN. Already verified?{" "}
            <Link to="/sign-in">Sign in</Link>.
          </p>
        </header>
        <RequestAccessForm invite={null} inviteToken={null} />
      </div>
    </SiteLayout>
  );
}
