import { useState } from "react";
import { useNavigate } from "react-router-dom";
import {
  Stack,
  Group,
  Button,
  Modal,
  Text,
  TextInput,
  Textarea,
  Card,
  Select,
  NumberInput,
  Stepper,
  SimpleGrid,
  Paper,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { useTranslation } from "react-i18next";
import {
  IconPlus,
  IconInfoCircle,
  IconClipboardList,
  IconChecklist,
} from "@tabler/icons-react";
import { notify, useErrorHandler, AdvancedTable, useServerTable, ModalFooter, AmharicDatePicker } from "@ema-platform/ui";
import { LICENSE_PERMISSIONS, RequirePermission } from "@ema-platform/auth";
import { useGetCertificationsQuery } from "../../../certification/api/certification-api";
import { useGetRanksQuery, useLocalized } from "@ema-platform/api";
import {
  useGetExamsQuery,
  useCreateExamMutation,
  useUpdateExamMutation,
  useDeleteExamMutation,
} from "../../api/exam-api";
import type { Exam } from "../../types/exam";
import {
  LAST_STEP,
  stepOfError,
  validateAll,
  validateStep,
  type ExamFormValues,
} from "./validation";
import { examColumns } from "./columns";
import { examActionsColumn } from "./actions";
import { ErrorState, PageHeader } from '@ema-platform/ui';

function ReviewRow({ label, value }: { label: string; value?: string | null }) {
  return (
    <div>
      <Text fz="xs" c="dimmed">
        {label}
      </Text>
      <Text fz="sm">{value || "—"}</Text>
    </div>
  );
}

function ExamForm({
  editing,
  certOptions,
  isSubmitting,
  onSubmit,
  onCancel,
}: {
  editing: Exam | null;
  certOptions: { value: string; label: string }[];
  isSubmitting: boolean;
  onSubmit: (values: any, isEdit: boolean) => void;
  onCancel: () => void;
}) {
  const { t } = useTranslation();
  const [certificationId, setCertificationId] = useState<string | null>(
    editing?.certificationId ?? null,
  );
  const [titleEn, setTitleEn] = useState(editing?.title?.en ?? "");
  const [titleAm, setTitleAm] = useState(editing?.title?.am ?? "");
  const [directionEn, setDirectionEn] = useState(editing?.direction?.en ?? "");
  const [directionAm, setDirectionAm] = useState(editing?.direction?.am ?? "");
  const [date, setDate] = useState(editing?.date ?? "");
  const [days, setDays] = useState(editing?.givenTime?.days ?? 0);
  const [hours, setHours] = useState(editing?.givenTime?.hours ?? 0);
  const [minutes, setMinutes] = useState(editing?.givenTime?.minutes ?? 0);
  const [type, setType] = useState<string | null>(editing?.type ?? null);
  const [form, setForm] = useState<string | null>(editing?.form ?? null);
  const [venue, setVenue] = useState(editing?.venue ?? "");
  const [adminMethod, setAdminMethod] = useState<string | null>(
    editing?.administrationMethod ?? null,
  );
  const [evalMethod, setEvalMethod] = useState<string | null>(
    editing?.evaluationMethod ?? null,
  );
  const [selMethod, setSelMethod] = useState<string | null>(
    editing?.selectionMethod ?? null,
  );
  const [cuttingPoint, setCuttingPoint] = useState<number>(
    editing?.cuttingPoint ?? 0,
  );
  const [status, setStatus] = useState<string | null>(editing?.status ?? null);
  const [step, setStep] = useState(0);

  /**
   * Validation is per step, so "Next" only ever complains about what is in
   * front of the user. Submitting from Basic Info used to report the Settings
   * fields as missing — correct and unactionable at the same time, since that
   * step had not been shown yet. The rules live in ./validation so the
   * per-step check and the final one cannot drift apart.
   */
  const values: ExamFormValues = {
    certificationId,
    titleEn,
    titleAm,
    directionEn,
    directionAm,
    date,
    venue,
    type,
    form,
    adminMethod,
    evalMethod,
    cuttingPoint,
  };

  const goNext = () => {
    const error = validateStep(step, values);
    if (error) {
      notify.error(t(error));
      return;
    }
    setStep((current) => current + 1);
  };

  /** No validation going backwards — state lives in this component, so
   *  nothing entered is lost either way. */
  const goBack = () => setStep((current) => Math.max(0, current - 1));

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    const error = validateAll(values);
    if (error) {
      setStep(stepOfError(error));
      notify.error(t(error));
      return;
    }
    onSubmit(
      {
        certificationId,
        titleEn,
        titleAm,
        directionEn,
        directionAm,
        date,
        days,
        hours,
        minutes,
        type,
        form,
        venue,
        adminMethod,
        evalMethod,
        selMethod,
        cuttingPoint,
        status,
      },
      !!editing,
    );
  };

  return (
    <Modal opened onClose={onCancel} title={editing ? t("exam.update") : t("exam.add")} size="xl">
      <form onSubmit={handleSubmit}>
        {/* Stepper, not Tabs: the form is a sequence with a submit at the end,
            and the header has to say which step of how many rather than
            offering all of them at once. `allowStepSelect` on visited steps
            only — jumping ahead is what let the old form be submitted from
            Basic Info. */}
        <Stepper
          active={step}
          onStepClick={setStep}
          size="sm"
          radius="md"
          mb="md"
        >
          <Stepper.Step
            label={t("exam.form.basicInfo")}
            icon={<IconInfoCircle size={15} />}
            allowStepSelect={step > 0}
          >
            <Stack gap="sm">
              <Select
                label={t("exam.form.certification")}
                placeholder={t("exam.form.selectCertification")}
                data={certOptions}
                value={certificationId}
                onChange={setCertificationId}
                size="sm"
                searchable
                required
              />
              <TextInput
                label={t("exam.form.titleEn")}
                placeholder={t("exam.form.titleEnPlaceholder")}
                value={titleEn}
                onChange={(e) => setTitleEn(e.currentTarget.value)}
                size="sm"
                required
              />
              <TextInput
                label={t("exam.form.titleAm")}
                placeholder={t("exam.form.titleAmPlaceholder")}
                value={titleAm}
                onChange={(e) => setTitleAm(e.currentTarget.value)}
                size="sm"
                required
              />
              <Textarea
                label={t("exam.form.directionEn")}
                placeholder={t("exam.form.directionEnPlaceholder")}
                value={directionEn}
                onChange={(e) => setDirectionEn(e.currentTarget.value)}
                size="sm"
                autosize
                minRows={2}
              />
              <Textarea
                label={t("exam.form.directionAm")}
                placeholder={t("exam.form.directionAmPlaceholder")}
                value={directionAm}
                onChange={(e) => setDirectionAm(e.currentTarget.value)}
                size="sm"
                autosize
                minRows={2}
              />
              <AmharicDatePicker
                label={t("exam.form.examDate")}
                value={date}
                onChange={setDate}
                dateFormat="date"
                size="sm"
                required
              />
              <TextInput
                label={t("exam.form.venue")}
                placeholder={t("exam.form.venuePlaceholder")}
                value={venue}
                onChange={(e) => setVenue(e.currentTarget.value)}
                size="sm"
                required
              />

              <Text fz="sm" fw={500}>
                {t("exam.form.timeAllowed")}
              </Text>
              <Group gap="sm" grow>
                <NumberInput
                  label={t("exam.form.days")}
                  value={days}
                  onChange={(v) => setDays(Number(v))}
                  min={0}
                  size="sm"
                />
                <NumberInput
                  label={t("exam.form.hours")}
                  value={hours}
                  onChange={(v) => setHours(Number(v))}
                  min={0}
                  size="sm"
                />
                <NumberInput
                  label={t("exam.form.minutes")}
                  value={minutes}
                  onChange={(v) => setMinutes(Number(v))}
                  min={0}
                  size="sm"
                />
              </Group>
            </Stack>
          </Stepper.Step>

          <Stepper.Step
            label={t("exam.form.settings")}
            icon={<IconClipboardList size={15} />}
            allowStepSelect={step > 1}
          >
            <Stack gap="sm">
              <SimpleGrid cols={2} spacing="sm">
                <Select
                  label={t("exam.columns.type")}
                  placeholder="Written or Oral"
                  data={[
                    { value: "WRITTEN", label: t("exam.form.written") },
                    { value: "ORAL", label: t("exam.form.oral") },
                  ]}
                  value={type}
                  onChange={setType}
                  size="sm"
                  required
                />
                <Select
                  label={t("exam.columns.form")}
                  placeholder="Essay or Choice"
                  data={[
                    { value: "ESSAY", label: t("exam.form.essay") },
                    { value: "CHOICE", label: t("exam.form.choice") },
                    { value: "BOTH", label: t("exam.form.both") },
                  ]}
                  value={form}
                  onChange={setForm}
                  size="sm"
                  required
                />
                <Select
                  label={t("exam.detail.administration")}
                  placeholder="Offline or Online"
                  data={[
                    { value: "OFFLINE", label: t("exam.form.offline") },
                    { value: "ONLINE", label: t("exam.form.online") },
                  ]}
                  value={adminMethod}
                  onChange={setAdminMethod}
                  size="sm"
                  required
                />
                <Select
                  label={t("exam.detail.evaluation")}
                  placeholder="How to compute score"
                  data={[
                    { value: "SUM", label: t("exam.form.sum") },
                    { value: "AVERAGE", label: t("exam.form.average") },
                    { value: "PERCENTAGE", label: t("exam.form.percentage") },
                  ]}
                  value={evalMethod}
                  onChange={setEvalMethod}
                  size="sm"
                  required
                />
                <Select
                  label={t("exam.detail.selection")}
                  placeholder="Manual or Random"
                  data={[
                    { value: "MANUAL", label: t("exam.form.manual") },
                    { value: "RANDOM", label: t("exam.form.random") },
                  ]}
                  value={selMethod}
                  onChange={setSelMethod}
                  size="sm"
                />
                <NumberInput
                  label={t("exam.form.cuttingPoint")}
                  placeholder={
                    evalMethod === "PERCENTAGE"
                      ? t("exam.form.cuttingPointPercentagePlaceholder")
                      : t("exam.form.cuttingPointPlaceholder")
                  }
                  value={cuttingPoint}
                  onChange={(v) => setCuttingPoint(Number(v))}
                  min={0}
                  max={evalMethod === "PERCENTAGE" ? 100 : undefined}
                  size="sm"
                  withAsterisk
                  description={
                    evalMethod === "PERCENTAGE"
                      ? t("exam.form.cuttingPointPercentageHint")
                      : undefined
                  }
                />
              </SimpleGrid>
              {editing && (
                <Select
                  label={t("exam.form.status")}
                  placeholder={t("exam.form.statusPlaceholder")}
                  data={[
                    { value: "PENDING", label: t("exam.form.pending") },
                    { value: "ACTIVE", label: t("exam.form.active") },
                    { value: "COMPLETED", label: t("exam.form.completed") },
                    { value: "CANCELLED", label: t("exam.form.cancelled") },
                    { value: "POSTPONED", label: t("exam.form.postponed") },
                    { value: "PUBLISHED", label: t("exam.form.published") },
                  ]}
                  value={status}
                  onChange={setStatus}
                  size="sm"
                />
              )}
            </Stack>
          </Stepper.Step>

          {/* Read-only by design: the last step is for checking what is about
              to be created, not a third place to edit it. Back returns to the
              step that owns any field that looks wrong. */}
          <Stepper.Step
            label={t("exam.form.review")}
            icon={<IconChecklist size={15} />}
            allowStepSelect={false}
          >
            <Stack gap="xs">
              <Text fz="sm" c="dimmed">
                {t("exam.form.reviewHint")}
              </Text>
              <Paper withBorder radius="md" p="md">
                <SimpleGrid cols={{ base: 1, sm: 2 }} spacing="xs">
                  <ReviewRow
                    label={t("exam.form.certification")}
                    value={
                      certOptions.find((c) => c.value === certificationId)?.label
                    }
                  />
                  <ReviewRow label={t("exam.form.titleEn")} value={titleEn} />
                  <ReviewRow label={t("exam.form.titleAm")} value={titleAm} />
                  <ReviewRow label={t("exam.form.examDate")} value={date} />
                  <ReviewRow label={t("exam.form.venue")} value={venue} />
                  <ReviewRow
                    label={t("exam.detail.timeAllowed")}
                    value={t("exam.form.durationSummary", {
                      days,
                      hours,
                      minutes,
                    })}
                  />
                  <ReviewRow
                    label={t("exam.columns.type")}
                    value={type ? t(`exam.type.${type}`) : undefined}
                  />
                  <ReviewRow
                    label={t("exam.columns.form")}
                    value={form ? t(`exam.formType.${form}`) : undefined}
                  />
                  <ReviewRow
                    label={t("exam.detail.administration")}
                    value={adminMethod}
                  />
                  <ReviewRow
                    label={t("exam.detail.evaluation")}
                    value={evalMethod}
                  />
                  <ReviewRow
                    label={t("exam.detail.selection")}
                    value={selMethod}
                  />
                  <ReviewRow
                    label={t("exam.form.cuttingPoint")}
                    value={String(cuttingPoint)}
                  />
                </SimpleGrid>
              </Paper>
            </Stack>
          </Stepper.Step>
        </Stepper>

        <ModalFooter mt="md">
          <Button variant="default" onClick={onCancel} size="sm">
            {t("exam.cancel")}
          </Button>
          {step > 0 && (
            <Button variant="default" size="sm" onClick={goBack}>
              {t("exam.form.back")}
            </Button>
          )}
          {step < LAST_STEP ? (
            /* Deliberately not type="submit": only the last step submits, so
               there is no path from an earlier one into the API. */
            <Button size="sm" onClick={goNext}>
              {t("exam.form.next")}
            </Button>
          ) : (
            <Button type="submit" size="sm" loading={isSubmitting}>
              {editing ? t("exam.update") : t("exam.create")}
            </Button>
          )}
        </ModalFooter>
      </form>
    </Modal>
  );
}

export function ExamPage() {
  const navigate = useNavigate();
  const { t, i18n } = useTranslation();
  const { handleError } = useErrorHandler();
  const locale = i18n.language as "en" | "am";
  const localized = useLocalized();
  const { data: certRes } = useGetCertificationsQuery();
  const { data: rankRes } = useGetRanksQuery();
  const rankLabelByKey = new Map((rankRes?.items ?? []).map((r) => [r.key, localized(r.name)]));
  const { data, isFetching, isError, refetch } = useGetExamsQuery();
  const { setPageIndex, pageSize, setPageSize, paginate } = useServerTable();
  const [createExam, { isLoading: isCreating }] = useCreateExamMutation();
  const [updateExam, { isLoading: isUpdating }] = useUpdateExamMutation();
  const [deleteExam] = useDeleteExamMutation();

  const certifications = certRes?.items ?? [];
  const exams = data?.items ?? [];

  const [editing, setEditing] = useState<Exam | null>(null);
  const [showForm, setShowForm] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<Exam | null>(null);
  const [deleteOpened, { open: openDelete, close: closeDelete }] =
    useDisclosure(false);
  const [changingStatusId, setChangingStatusId] = useState<string | null>(null);
  const [statusTarget, setStatusTarget] = useState<Exam | null>(null);
  const [pendingStatus, setPendingStatus] = useState<Exam["status"] | null>(null);
  const [statusOpened, { open: openStatus, close: closeStatus }] =
    useDisclosure(false);

  // Rank in the label: an exam inherits its STCW rank from the certification
  // it is created under (Certification.rankKey), so the officer sees which
  // rank a sitting will serve at the moment they pick the subject.
  const certOptions = certifications
    .filter((c) => c.isActive)
    .map((c) => {
      const rank = c.rankKey ? rankLabelByKey.get(c.rankKey) : undefined;
      return {
        value: c.id,
        label: rank ? `${c.name[locale]} — ${rank}` : c.name[locale],
      };
    });
  const getCertName = (id: string) =>
    certifications.find((c) => c.id === id)?.name?.[locale] ?? "-";

  const resetForm = () => {
    setEditing(null);
    setShowForm(false);
  };

  const handleSubmit = async (values: any, isEdit: boolean) => {
    const payload: any = {
      certificationId: values.certificationId,
      title: { en: values.titleEn, am: values.titleAm },
      direction:
        values.directionEn || values.directionAm
          ? { en: values.directionEn, am: values.directionAm }
          : undefined,
      date: values.date,
      givenTime: {
        days: values.days,
        hours: values.hours,
        minutes: values.minutes,
      },
      type: values.type,
      form: values.form,
      venue: values.venue,
      administrationMethod: values.adminMethod,
      evaluationMethod: values.evalMethod,
      selectionMethod: values.selMethod || "MANUAL",
      cuttingPoint: values.cuttingPoint,
    };
    if (isEdit) payload.status = values.status;

    try {
      if (isEdit && editing) {
        await updateExam({ id: editing.id, ...payload }).unwrap();
        notify.success(t("exam.updated"));
      } else {
        await createExam(payload).unwrap();
        notify.success(t("exam.created"));
      }
      resetForm();
    } catch (e) {
      handleError(e);
    }
  };

  const handleChangeStatus = async () => {
    if (!statusTarget || !pendingStatus) return;
    setChangingStatusId(statusTarget.id);
    try {
      await updateExam({ id: statusTarget.id, status: pendingStatus }).unwrap();
      notify.success(t("exam.updated"));
      closeStatus();
      setStatusTarget(null);
    } catch (e) {
      handleError(e);
    } finally {
      setChangingStatusId(null);
    }
  };

  const handleDelete = async () => {
    if (!deleteTarget) return;
    try {
      await deleteExam(deleteTarget.id).unwrap();
      notify.success(t("exam.deleted"));
      closeDelete();
      setDeleteTarget(null);
    } catch (e) {
      handleError(e);
    }
  };

  if (isError)
    return <ErrorState title={t("exam.loadError")} onRetry={refetch} />;

  const columns = [
    ...examColumns(t, locale, getCertName, (exam) => navigate(`/exams/${exam.id}`)),
    examActionsColumn(t, {
      onEdit: (exam) => {
        setEditing(exam);
        setShowForm(true);
      },
      onDelete: (exam) => {
        setDeleteTarget(exam);
        openDelete();
      },
      onDetails: (exam) => navigate(`/exams/${exam.id}`),
      onOpenStatusChange: (exam) => {
        setStatusTarget(exam);
        setPendingStatus(exam.status);
        openStatus();
      },
      changingStatusId,
    }),
  ];

  const page = paginate(exams);

  return (
    <Stack gap="lg">
      <PageHeader
        title={t("exam.title")}
        subtitle={t("exam.subtitle")}
        noMargin
        action={
          !showForm && (
            <RequirePermission anyOf={[LICENSE_PERMISSIONS.MANAGE_EXAMS]} hideOnly>
              <Button
                variant="light"
                leftSection={<IconPlus size={16} />}
                onClick={() => setShowForm(true)}
                size="sm"
              >
                {t("exam.add")}
              </Button>
            </RequirePermission>
          )
        }
      />

      {showForm && (
        <ExamForm
          editing={editing}
          certOptions={certOptions}
          isSubmitting={isCreating || isUpdating}
          onSubmit={handleSubmit}
          onCancel={resetForm}
        />
      )}

      <Card withBorder padding={0}>
        <AdvancedTable
          columns={columns}
          data={page.rows}
          tableName={t("exam.title")}
          itemCount={page.itemCount}
          pageIndex={page.pageIndex}
          onPageChange={setPageIndex}
          pageSize={pageSize}
          onPageSizeChange={setPageSize}
          refresh={refetch}
          isLoading={isFetching}
          emptyText={t("exam.noItems")}
        />
      </Card>

      {/* Delete confirmation */}
      <Modal
        opened={deleteOpened}
        onClose={closeDelete}
        title={t("exam.confirmDelete")}
        size="sm"
      >
        <Text mb="md">
          {t("exam.deleteConfirmText", {
            name: deleteTarget?.title?.[locale] ?? "",
          })}
        </Text>
        <ModalFooter>
          <Button variant="default" onClick={closeDelete} size="sm">
            {t("exam.cancel")}
          </Button>
          <Button color="red" onClick={handleDelete} size="sm">
            {t("exam.delete")}
          </Button>
        </ModalFooter>
      </Modal>

      {/* Quick status change — not the full edit form */}
      <Modal
        opened={statusOpened}
        onClose={closeStatus}
        title={t("exam.form.status")}
        size="sm"
      >
        <Stack gap="md">
          <Text fz="sm" c="dimmed">
            {statusTarget?.title?.[locale]}
          </Text>
          <Select
            label={t("exam.form.status")}
            data={[
              { value: "PENDING", label: t("exam.form.pending") },
              { value: "ACTIVE", label: t("exam.form.active") },
              { value: "COMPLETED", label: t("exam.form.completed") },
              { value: "CANCELLED", label: t("exam.form.cancelled") },
              { value: "POSTPONED", label: t("exam.form.postponed") },
              { value: "PUBLISHED", label: t("exam.form.published") },
            ]}
            value={pendingStatus}
            onChange={(value) => setPendingStatus(value as Exam["status"])}
            size="sm"
          />
          <ModalFooter>
            <Button variant="default" onClick={closeStatus} size="sm">
              {t("exam.cancel")}
            </Button>
            <Button
              onClick={handleChangeStatus}
              size="sm"
              loading={changingStatusId === statusTarget?.id}
              disabled={pendingStatus === statusTarget?.status}
            >
              {t("exam.update")}
            </Button>
          </ModalFooter>
        </Stack>
      </Modal>
    </Stack>
  );
}
