import type { ReactNode } from "react";
import type { CheckInPlanTemplate, PlanQuestion } from "../../api/types";
import { closingAvailable, moveQuestion, type ScriptLine } from "../../logic/questions";
import { windowLabel, type Window } from "../../logic/windows";
import { Button, checkClass, cn, fieldClass, Icon, type IconName, Tip } from "../kit";

/** A white card for one part of the plan: its title, a quiet note on the right, then the part. */
export function PlanCard({ title, icon, note, children }: { title: string; icon?: IconName; note?: ReactNode; children: ReactNode }) {
  return (
    <section aria-label={title} className="flex min-w-0 flex-col gap-3.5 rounded-2xl bg-page p-5 shadow-card max-sm:p-4">
      <div className="flex flex-wrap items-center justify-between gap-x-3 gap-y-1">
        <h2 className="m-0 flex items-center gap-2 text-[15px] leading-5 font-semibold tracking-[-0.01em] text-ink">
          {icon && <Icon name={icon} size={16} className="text-muted" />}
          {title}
        </h2>
        {note && <span className="font-mono text-[11.5px] text-muted">{note}</span>}
      </div>
      {children}
    </section>
  );
}

export const Hint = ({ children, id, className }: { children: ReactNode; id?: string; className?: string }) => (
  <small id={id} className={cn("block text-[12.5px] leading-[18px] text-muted", className)}>
    {children}
  </small>
);

/** A checkbox row: the box, the words, and a quiet line under them. */
export function CheckRow({ checked, disabled, onChange, children }: { checked: boolean; disabled?: boolean; onChange: (on: boolean) => void; children: ReactNode }) {
  return (
    <label className={cn("flex items-start gap-3 rounded-xl px-3 py-2.5 transition-colors duration-150", disabled ? "cursor-not-allowed opacity-60" : "cursor-pointer hover:bg-tile")}>
      <input type="checkbox" className={checkClass} checked={checked} disabled={disabled} onChange={(e) => onChange(e.target.checked)} />
      <span className="flex min-w-0 flex-col gap-0.5 text-[14px] leading-5 text-ink">{children}</span>
    </label>
  );
}

/** The chosen questions in the order Yasmar asks them, with the fixed last question under them. */
export function QuestionOrder({ chosen, alwaysLast, onChange }: { chosen: PlanQuestion[]; alwaysLast: string; onChange: (next: (c: PlanQuestion[]) => PlanQuestion[]) => void }) {
  const tool = (label: string, tip: string, icon: IconName, disabled: boolean, act: () => void) => (
    <Tip label={tip} disabled={disabled}>
      <Button variant="ghost" size="icon-sm" aria-label={label} disabled={disabled} onClick={act}>
        <Icon name={icon} size={15} />
      </Button>
    </Tip>
  );
  return (
    <ol className="m-0 flex list-none flex-col p-0">
      {chosen.map((q, i) => (
        <li key={q.id} className="flex items-start gap-3 py-2.5 shadow-[inset_0_-1px_0_var(--color-hairline)]">
          <span className="mt-px flex size-5 shrink-0 items-center justify-center rounded-full bg-quiet font-mono text-[11px] text-cell">{i + 1}</span>
          <span className="flex min-w-0 flex-1 flex-col gap-0.5 text-[14px] leading-5 text-ink">
            {q.text}
            <small className="text-[12.5px] leading-[18px] text-muted">{q.reason}</small>
          </span>
          <span className="flex shrink-0 items-center gap-0.5">
            {tool(`Move "${q.text}" up`, "Move up", "arrow-up-line", i === 0, () => onChange((c) => moveQuestion(c, q.id, -1)))}
            {tool(`Move "${q.text}" down`, "Move down", "arrow-down-line", i === chosen.length - 1, () => onChange((c) => moveQuestion(c, q.id, 1)))}
            {tool(`Remove "${q.text}"`, "Remove", "delete-bin-line", false, () => onChange((c) => c.filter((x) => x.id !== q.id)))}
          </span>
        </li>
      ))}
      <li className="flex items-start gap-3 py-2.5 text-muted">
        <Icon name="lock-line" size={15} label="Fixed" className="mt-0.5 text-subtle" />
        <span className="min-w-0 flex-1 text-[14px] leading-5">
          {alwaysLast} <small className="text-[12.5px] text-subtle">Always last</small>
        </span>
      </li>
    </ol>
  );
}

/** The approved closing lines: some need you to read the answers today or a reminder. */
export function Closing({
  template,
  first,
  readToday,
  reminder,
  closingIds,
  onReadToday,
  onReminder,
  onClosings,
}: {
  template: CheckInPlanTemplate;
  first: string;
  readToday: boolean;
  reminder: boolean;
  closingIds: string[];
  onReadToday: (on: boolean) => void;
  onReminder: (on: boolean) => void;
  onClosings: (next: (ids: string[]) => string[]) => void;
}) {
  return (
    <>
      <div className="flex flex-col">
        <CheckRow checked={readToday} onChange={onReadToday}>
          I will read the answers today
        </CheckRow>
        <CheckRow checked={reminder} onChange={onReminder}>
          Set me a reminder to call {first} back
        </CheckRow>
      </div>
      <fieldset className="m-0 flex flex-col border-0 p-0 shadow-[inset_0_1px_0_var(--color-hairline)] pt-2">
        <legend className="sr-only">Closing lines</legend>
        {template.closings.map((c) => {
          const available = closingAvailable(c, readToday, reminder);
          return (
            <CheckRow
              key={c.id}
              checked={c.fixed || (available && closingIds.includes(c.id))}
              disabled={c.fixed || !available}
              onChange={(on) => onClosings((ids) => (on ? [...ids, c.id] : ids.filter((x) => x !== c.id)))}
            >
              {c.text}
              {c.fixed ? <small className="text-[12.5px] text-muted">Always said</small> : !available && <small className="text-[12.5px] text-muted">{c.requires === "read_today" ? "Needs you to read them today" : "Needs a reminder"}</small>}
            </CheckRow>
          );
        })}
      </fieldset>
      <Hint className="flex items-start gap-1.5">
        <Icon name="lock-line" size={13} className="mt-0.5 text-subtle" /> <span>Always last: {template.safetyNet}</span>
      </Hint>
    </>
  );
}

/** When Yasmar may ring: now, or one of the allowed two-hour windows, as chips. */
export function WhenChoice({ nowOk, choices, when, patientOffset, now, onWhen }: { nowOk: boolean; choices: Window[]; when: "now" | number; patientOffset: number; now: Date; onWhen: (w: "now" | number) => void }) {
  const chip = (checked: boolean, disabled: boolean, label: string, key: string, pick: () => void) => (
    <label
      key={key}
      className={cn(
        "relative inline-flex h-9 cursor-pointer items-center rounded-full px-3.5 text-[13px] font-medium text-body shadow-[inset_0_0_0_1px_var(--color-line)] transition-[background-color,color,box-shadow] duration-150 select-none hover:bg-tile",
        "has-[:checked]:bg-ink has-[:checked]:text-white has-[:checked]:shadow-[inset_0_0_0_1px_var(--color-ink)] has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-brand",
        disabled && "pointer-events-none opacity-40",
      )}
    >
      <input type="radio" name="when" className="sr-only" checked={checked} disabled={disabled} onChange={pick} />
      {label}
    </label>
  );
  return (
    <div className="flex flex-wrap gap-2" role="radiogroup" aria-label="When Yasmar may ring">
      {chip(when === "now", !nowOk, "Now", "now", () => onWhen("now"))}
      {choices.map((w, i) => chip(when === i, false, windowLabel(w, patientOffset, now), w.start.toISOString(), () => onWhen(i)))}
    </div>
  );
}

/** The expiry choice, inline. */
export function Expiry({ value, max, onChange }: { value: number; max: number; onChange: (h: number) => void }) {
  return (
    <label className="flex flex-wrap items-center gap-2.5 text-[13px] font-medium text-cell">
      The request expires after
      <select className={cn(fieldClass, "h-[34px] w-auto pr-8 text-[13px]")} value={value} onChange={(e) => onChange(Number(e.target.value))}>
        {[24, 48, 72].filter((h) => h <= max).map((h) => (
          <option key={h} value={h}>
            {h} hours
          </option>
        ))}
      </select>
    </label>
  );
}

const fixedPart: ScriptLine["part"][] = ["opening", "identity", "consent", "feeling", "last", "safety"];

/** Exactly what Yasmar will say, in order: your questions in ink, the fixed lines quieter. */
export function ScriptPreview({ script }: { script: ScriptLine[] }) {
  return (
    <ol className="m-0 flex list-none flex-col gap-1 p-0">
      {script.map((l, i) => (
        <li
          key={i}
          className={cn(
            "rounded-lg px-3 py-2 text-[14px] leading-5",
            l.part === "question" ? "bg-tile font-medium text-ink" : fixedPart.includes(l.part) ? "text-cell" : "text-body",
          )}
        >
          {l.text}
          {l.reason && <small className="text-[12.5px] font-normal text-muted"> · {l.reason}</small>}
        </li>
      ))}
    </ol>
  );
}
