"use client";

import { useState } from "react";
import clsx from "clsx";
import { Loader2 } from "lucide-react";
import { updateNonUnitProgressAction } from "@/app/actions/assessment";
import { Badge, Callout, Card, CardHeader, selectClass, TableShell, Td, Th } from "@/components/ui";
import { useToast } from "@/components/toast";
import { NON_UNIT_PROGRESS_STATUSES, type NonUnitProgressStatus } from "@/types";

/**
 * Summer training and clinical clerkship tracking (SPEC 52.7, 52.8, 54).
 *
 * These requirements are duration-based. They are deliberately excluded from
 * the credited-unit numerator and the total-program-unit denominator.
 */

export interface NonUnitRequirementView {
  id: string;
  title: string;
  code: string | null;
  requirementType: "SUMMER_TRAINING" | "CLERKSHIP_CORE" | "CLERKSHIP_ELECTIVE";
  academicYear: number | null;
  hours: number | null;
  months: number | null;
  elective: boolean;
  minimumSelections: number | null;
  selected: boolean;
  status: NonUnitProgressStatus;
  remarks: string;
}

const STATUS_LABELS: Record<NonUnitProgressStatus, string> = {
  NOT_STARTED: "Not started",
  IN_PROGRESS: "In progress",
  COMPLETED: "Completed",
  WAIVED: "Waived",
};

const SECTION_TITLES: Record<NonUnitRequirementView["requirementType"], string> = {
  SUMMER_TRAINING: "Summer training requirements",
  CLERKSHIP_CORE: "Clinical clerkship — core rotations",
  CLERKSHIP_ELECTIVE: "Clinical clerkship — elective rotations",
};

function formatDuration(requirement: NonUnitRequirementView): string {
  if (requirement.months !== null) {
    return requirement.months === 0.5 ? "½ month" : `${requirement.months} month${requirement.months === 1 ? "" : "s"}`;
  }
  if (requirement.hours !== null) return `${requirement.hours} hours`;
  return "—";
}

export function NonUnitRequirementsPanel({
  studentId,
  requirements,
  electiveSelectionCount,
  electiveSelectionsRequired,
  canEdit,
}: {
  studentId: string;
  requirements: NonUnitRequirementView[];
  electiveSelectionCount: number;
  electiveSelectionsRequired: number;
  canEdit: boolean;
}) {
  const { toast } = useToast();
  const [state, setState] = useState(() => new Map(requirements.map((r) => [r.id, r])));
  const [pending, setPending] = useState<string | null>(null);
  const [electiveCount, setElectiveCount] = useState(electiveSelectionCount);

  const save = async (requirement: NonUnitRequirementView, patch: Partial<NonUnitRequirementView>) => {
    const next = { ...requirement, ...patch };
    setPending(requirement.id);

    const formData = new FormData();
    formData.set("student_id", studentId);
    formData.set("non_unit_requirement_id", requirement.id);
    formData.set("selected", String(next.selected));
    formData.set("status", next.status);
    formData.set("remarks", next.remarks ?? "");

    const result = await updateNonUnitProgressAction({ ok: false, message: null }, formData);
    setPending(null);

    if (result.ok) {
      setState((current) => new Map(current).set(requirement.id, next));
      if (requirement.elective) {
        setElectiveCount((count) => count + (next.selected ? 1 : 0) - (requirement.selected ? 1 : 0));
      }
      toast({ tone: "success", title: result.message ?? "Saved." });
    } else {
      toast({ tone: "error", title: result.message ?? "The requirement could not be updated." });
    }
  };

  const sections = (["SUMMER_TRAINING", "CLERKSHIP_CORE", "CLERKSHIP_ELECTIVE"] as const).filter((type) =>
    requirements.some((r) => r.requirementType === type),
  );

  const totalMonths = requirements
    .filter((r) => r.requirementType !== "SUMMER_TRAINING")
    .filter((r) => !r.elective || state.get(r.id)?.selected)
    .reduce((sum, r) => sum + (r.months ?? 0), 0);

  return (
    <Card>
      <CardHeader
        title="Non-unit requirements"
        description="Summer training and the clinical clerkship are duration-based. They are tracked here but never enter the credited-unit numerator or the total-program-unit denominator."
      />

      <div className="space-y-5 px-5 py-4">
        {electiveSelectionsRequired > 0 ? (
          <Callout tone={electiveCount === electiveSelectionsRequired ? "success" : "warning"}>
            {electiveCount} of exactly {electiveSelectionsRequired} elective rotations selected.
            {electiveCount === electiveSelectionsRequired
              ? ` Core plus selected electives total ${totalMonths} months.`
              : ` Select ${electiveSelectionsRequired - electiveCount} more to complete the 12-month clerkship.`}
          </Callout>
        ) : null}

        {sections.map((type) => (
          <section key={type}>
            <h3 className="mb-2 text-[11px] font-semibold uppercase tracking-wider text-ink-500">
              {SECTION_TITLES[type]}
            </h3>
            <div className="overflow-hidden rounded-lg border border-ink-200">
              <TableShell>
                <thead>
                  <tr>
                    {type === "CLERKSHIP_ELECTIVE" ? <Th className="w-16">Selected</Th> : null}
                    <Th>Requirement</Th>
                    <Th>Year</Th>
                    <Th>Duration</Th>
                    <Th className="w-44">Status</Th>
                  </tr>
                </thead>
                <tbody>
                  {requirements
                    .filter((r) => r.requirementType === type)
                    .map((requirement) => {
                      const current = state.get(requirement.id) ?? requirement;
                      return (
                        <tr key={requirement.id} className="hover:bg-ink-50">
                          {type === "CLERKSHIP_ELECTIVE" ? (
                            <Td align="center">
                              <input
                                type="checkbox"
                                checked={current.selected}
                                disabled={!canEdit || pending === requirement.id}
                                onChange={(event) => void save(current, { selected: event.target.checked })}
                                aria-label={`Select ${requirement.title} as an elective`}
                                className="h-4 w-4 rounded border-ink-300 text-brand-600 focus:ring-brand-500"
                              />
                            </Td>
                          ) : null}
                          <Td>
                            <span className="font-medium text-ink-800">{requirement.title}</span>
                            {requirement.code ? (
                              <span className="ml-2 text-[11px] text-ink-500">{requirement.code}</span>
                            ) : null}
                          </Td>
                          <Td className="text-[13px] text-ink-600">
                            {requirement.academicYear ? `Year ${requirement.academicYear}` : "—"}
                          </Td>
                          <Td className="tabular whitespace-nowrap text-[13px] text-ink-600">
                            {formatDuration(requirement)}
                          </Td>
                          <Td>
                            <div className="flex items-center gap-2">
                              <select
                                value={current.status}
                                disabled={!canEdit || pending === requirement.id}
                                onChange={(event) =>
                                  void save(current, { status: event.target.value as NonUnitProgressStatus })
                                }
                                aria-label={`Status for ${requirement.title}`}
                                className={clsx(selectClass, "h-8 py-0 text-[13px]")}
                              >
                                {NON_UNIT_PROGRESS_STATUSES.map((status) => (
                                  <option key={status} value={status}>
                                    {STATUS_LABELS[status]}
                                  </option>
                                ))}
                              </select>
                              {pending === requirement.id ? (
                                <Loader2 className="h-3.5 w-3.5 animate-spin text-ink-400" aria-label="Saving" />
                              ) : null}
                            </div>
                          </Td>
                        </tr>
                      );
                    })}
                </tbody>
              </TableShell>
            </div>
          </section>
        ))}

        <p className="text-[12px] text-ink-500">
          <Badge tone="info">Excluded from OCCP</Badge>{" "}
          These requirements are never converted into academic units.
        </p>
      </div>
    </Card>
  );
}
