import { useState } from "react";
import {
  Stack,
  Title,
  Group,
  Button,
  Badge,
  Modal,
  Text,
  TextInput,
  Card,
  Alert,
  Select,
  NumberInput,
  Textarea,
  Checkbox,
  ActionIcon,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { useTranslation } from "react-i18next";
import {
  IconPlus,
  IconInfoCircle,
  IconTrash,
  IconGripVertical,
} from "@tabler/icons-react";
import {
  AdvancedColumn,
  AdvancedTable,
  ErrorState,
  ModalFooter,
  notify,
  PageHeader,
  useErrorHandler,
  useServerTable,
} from "@ema-platform/ui";
import { extractErrorMessage } from "@ema-platform/api";
import { LICENSE_PERMISSIONS, RequirePermission } from "@ema-platform/auth";
import { useGetCertificationsQuery } from "../../../certification/api/certification-api";
import {
  useGetQuestionsQuery,
  useCreateQuestionMutation,
  useUpdateQuestionMutation,
  useDeleteQuestionMutation,
  useSubmitQuestionMutation,
  useReviewQuestionMutation,
  useSetQuestionOptionsMutation,
} from "../../api/question-api";
import type {
  Question,
  QuestionForm,
  QuestionOptionInput,
} from "../../types/question";
import { QuestionOptionsEditor } from "../../components/QuestionOptionsEditor";
import { questionColumns } from "./columns";
import { questionActionsColumn } from "./actions";

type DraftOption = { textEn: string; textAm: string; isCorrect: boolean };

const BLANK_DRAFT_OPTIONS: DraftOption[] = [
  { textEn: "", textAm: "", isCorrect: false },
  { textEn: "", textAm: "", isCorrect: false },
];

/**
 * Options for a brand-new CHOICE question, entered inline in the same
 * modal — no question id exists yet, so this is pure local state, only
 * turned into a real setOptions() call once the question itself is
 * created (see QuestionPage.handleSubmit).
 */
function InlineOptionsEditor({
  options,
  onChange,
}: {
  options: DraftOption[];
  onChange: (options: DraftOption[]) => void;
}) {
  const { t } = useTranslation();

  const update = (index: number, patch: Partial<DraftOption>) =>
    onChange(options.map((o, i) => (i === index ? { ...o, ...patch } : o)));

  return (
    <Stack gap="xs">
      {options.map((option, index) => (
        <Group key={index} gap="xs" wrap="nowrap" align="center">
          <IconGripVertical size={16} style={{ opacity: 0.4 }} />
          <Stack gap={6} style={{ flex: 1 }}>
            <TextInput
              label={t("question.options.optionEn", { number: index + 1 })}
              value={option.textEn}
              onChange={(e) => update(index, { textEn: e.currentTarget.value })}
              size="sm"
              required
            />
            <TextInput
              label={t("question.options.optionAm", { number: index + 1 })}
              value={option.textAm}
              onChange={(e) => update(index, { textAm: e.currentTarget.value })}
              size="sm"
              required
            />
          </Stack>
          <Checkbox
            label={t("question.options.correct")}
            checked={option.isCorrect}
            onChange={() => update(index, { isCorrect: !option.isCorrect })}
          />
          <ActionIcon
            variant="subtle"
            color="red"
            size="sm"
            disabled={options.length <= 2}
            onClick={() => onChange(options.filter((_, i) => i !== index))}
          >
            <IconTrash size={14} />
          </ActionIcon>
        </Group>
      ))}
      <Button
        variant="subtle"
        size="xs"
        leftSection={<IconPlus size={14} />}
        onClick={() =>
          onChange([...options, { textEn: "", textAm: "", isCorrect: false }])
        }
      >
        {t("question.options.addOption")}
      </Button>
    </Stack>
  );
}

function QuestionForm({
  editing,
  certOptions,
  isSubmitting,
  onSubmit,
  onCancel,
}: {
  editing: Question | null;
  certOptions: { value: string; label: string }[];
  isSubmitting: boolean;
  onSubmit: (
    values: {
      certificationId: string;
      titleEn: string;
      titleAm: string;
      form: string;
      points: number;
      days: number;
      hours: number;
      minutes: number;
      draftOptions: DraftOption[];
    },
    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 [form, setForm] = useState<string | null>(editing?.form ?? null);
  const [points, setPoints] = useState<number>(editing?.points ?? 0);
  const [days, setDays] = useState(editing?.time?.days ?? 0);
  const [hours, setHours] = useState(editing?.time?.hours ?? 0);
  const [minutes, setMinutes] = useState(editing?.time?.minutes ?? 0);
  const [draftOptions, setDraftOptions] =
    useState<DraftOption[]>(BLANK_DRAFT_OPTIONS);

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (!certificationId || !titleEn || !titleAm || !form) {
      notify.error("Please fill all required fields");
      return;
    }
    if (!editing && form === "CHOICE") {
      if (draftOptions.length < 2) {
        notify.error(t("question.options.needAtLeastTwo"));
        return;
      }
      if (!draftOptions.some((o) => o.isCorrect)) {
        notify.error(t("question.options.needOneCorrect"));
        return;
      }
      if (draftOptions.some((o) => !o.textEn.trim() || !o.textAm.trim())) {
        notify.error(t("question.options.textRequired"));
        return;
      }
    }
    onSubmit(
      {
        certificationId,
        titleEn,
        titleAm,
        form,
        points,
        days,
        hours,
        minutes,
        draftOptions: !editing && form === "CHOICE" ? draftOptions : [],
      },
      !!editing,
    );
  };

  return (
    <Modal
      opened
      onClose={onCancel}
      title={editing ? t("question.update") : t("question.addQuestion")}
      size="lg"
    >
      <form onSubmit={handleSubmit}>
        <Stack gap="sm">
          <Select
            label={t("question.form.certification")}
            placeholder={t("question.form.selectCertification")}
            data={certOptions}
            value={certificationId}
            onChange={setCertificationId}
            size="sm"
            searchable
            required
          />
          <TextInput
            label={t("question.form.titleEn")}
            placeholder={t("question.form.titleEnPlaceholder")}
            value={titleEn}
            onChange={(e) => setTitleEn(e.currentTarget.value)}
            size="sm"
            required
          />
          <TextInput
            label={t("question.form.titleAm")}
            placeholder={t("question.form.titleAmPlaceholder")}
            value={titleAm}
            onChange={(e) => setTitleAm(e.currentTarget.value)}
            size="sm"
            required
          />
          <Select
            label={t("question.form.form")}
            placeholder={t("question.form.selectForm")}
            data={[
              { value: "ESSAY", label: t("question.form.essay") },
              { value: "CHOICE", label: t("question.form.choice") },
            ]}
            value={form}
            onChange={setForm}
            size="sm"
            required
          />
          <NumberInput
            label={t("question.form.points")}
            placeholder={t("question.form.pointsPlaceholder")}
            value={points}
            onChange={(v) => setPoints(Number(v))}
            min={0}
            size="sm"
            required
          />
          <Text fz="sm" fw={500}>
            {t("question.form.timeAllowed")}
          </Text>
          <Group gap="sm" grow>
            <NumberInput
              label={t("question.form.days")}
              value={days}
              onChange={(v) => setDays(Number(v))}
              min={0}
              size="sm"
            />
            <NumberInput
              label={t("question.form.hours")}
              value={hours}
              onChange={(v) => setHours(Number(v))}
              min={0}
              size="sm"
            />
            <NumberInput
              label={t("question.form.minutes")}
              value={minutes}
              onChange={(v) => setMinutes(Number(v))}
              min={0}
              size="sm"
            />
          </Group>
          {editing && form === "CHOICE" && (
            <>
              <Text fz="sm" fw={500} mt="sm">
                {t("question.options.title")}
              </Text>
              <QuestionOptionsEditor questionId={editing.id} />
            </>
          )}
          {!editing && form === "CHOICE" && (
            <>
              <Text fz="sm" fw={500} mt="sm">
                {t("question.options.title")}
              </Text>
              <InlineOptionsEditor
                options={draftOptions}
                onChange={setDraftOptions}
              />
            </>
          )}
          <ModalFooter>
            <Button variant="default" onClick={onCancel} size="sm">
              {t("question.cancel")}
            </Button>
            <Button type="submit" size="sm" loading={isSubmitting}>
              {editing ? t("question.update") : t("question.create")}
            </Button>
          </ModalFooter>
        </Stack>
      </form>
    </Modal>
  );
}

export function QuestionPage() {
  const { t, i18n } = useTranslation();
  const locale = i18n.language as "en" | "am";
  const { handleError } = useErrorHandler();
  const { data: certRes } = useGetCertificationsQuery();
  const { data, isFetching, isError, refetch } = useGetQuestionsQuery();
  const { setPageIndex, pageSize, setPageSize, paginate } = useServerTable();
  const [createQ, { isLoading: isCreating }] = useCreateQuestionMutation();
  const [updateQ, { isLoading: isUpdating }] = useUpdateQuestionMutation();
  const [deleteQ] = useDeleteQuestionMutation();
  const [setOptions, { isLoading: isSavingOptions }] =
    useSetQuestionOptionsMutation();
  const [submitQ, { isLoading: isSubmittingReview }] =
    useSubmitQuestionMutation();
  const [reviewQ, { isLoading: isReviewing }] = useReviewQuestionMutation();

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

  const [editing, setEditing] = useState<Question | null>(null);
  const [showForm, setShowForm] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<Question | null>(null);
  const [deleteOpened, { open: openDelete, close: closeDelete }] =
    useDisclosure(false);
  const [certFilter, setCertFilter] = useState<string | null>(null);
  const [reviewTarget, setReviewTarget] = useState<Question | null>(null);
  const [reviewOutcome, setReviewOutcome] = useState<
    "APPROVED" | "REJECTED" | "RETIRED"
  >("APPROVED");
  const [reviewRemark, setReviewRemark] = useState("");

  const certOptions = certifications
    .filter((c) => c.isActive)
    .map((c) => ({ value: c.id, label: c.name[locale] }));

  const filtered = questions.filter(
    (q) => !certFilter || q.certificationId === certFilter,
  );
  const page = paginate(filtered);

  const getCertName = (id: string) =>
    certifications.find((c) => c.id === id)?.name?.[locale] ?? "-";

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

  const handleSubmit = async (
    values: {
      certificationId: string;
      titleEn: string;
      titleAm: string;
      form: string;
      points: number;
      days: number;
      hours: number;
      minutes: number;
      draftOptions: DraftOption[];
    },
    isEdit: boolean,
  ) => {
    const title = { en: values.titleEn, am: values.titleAm };
    const time = {
      days: values.days,
      hours: values.hours,
      minutes: values.minutes,
    };
    try {
      if (isEdit && editing) {
        await updateQ({
          id: editing.id,
          certificationId: values.certificationId,
          title,
          form: values.form as QuestionForm,
          points: values.points,
          time,
        }).unwrap();
        notify.success(t("question.updated"));
      } else {
        const created = await createQ({
          certificationId: values.certificationId,
          title,
          description: { en: "", am: "" },
          form: values.form as QuestionForm,
          points: values.points,
          time,
        }).unwrap();
        // The question needs an id to attach options to — this is the second
        // half of one "create" action from the user's point of view, not a
        // separate edit step, so it happens right here rather than waiting
        // for them to reopen the question later.
        if (values.form === "CHOICE" && values.draftOptions.length) {
          const options: QuestionOptionInput[] = values.draftOptions.map(
            (o) => ({
              text: { en: o.textEn, am: o.textAm },
              isCorrect: o.isCorrect,
            }),
          );
          await setOptions({ id: created.id, options }).unwrap();
        }
        notify.success(t("question.created"));
      }
      resetForm();
    } catch {
      notify.error(t("question.error"));
    }
  };

  const handleSubmitForApproval = async (question: Question) => {
    try {
      await submitQ(question.id).unwrap();
      notify.success(t("question.qc.submitted"));
    } catch (error) {
      notify.error(extractErrorMessage(error, t("question.qc.error")));
    }
  };

  const openReview = (
    question: Question,
    outcome: "APPROVED" | "REJECTED" | "RETIRED",
  ) => {
    setReviewTarget(question);
    setReviewOutcome(outcome);
    setReviewRemark("");
  };

  const handleReview = async () => {
    if (!reviewTarget) return;
    if (reviewOutcome !== "APPROVED" && !reviewRemark.trim()) {
      notify.error(t("question.qc.remarkRequired"));
      return;
    }
    try {
      await reviewQ({
        id: reviewTarget.id,
        outcome: reviewOutcome,
        remark: reviewRemark.trim() || undefined,
      }).unwrap();
      notify.success(t("question.qc.reviewed"));
      setReviewTarget(null);
    } catch (error) {
      notify.error(extractErrorMessage(error, t("question.qc.error")));
    }
  };

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

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

  const columns: AdvancedColumn<Question>[] = [
    ...questionColumns(t, { locale, getCertName }),
    questionActionsColumn(t, {
      isSubmittingReview,
      onSubmitForApproval: handleSubmitForApproval,
      onReview: openReview,
      onEdit: (q) => {
        setEditing(q);
        setShowForm(true);
      },
      onDelete: (q) => {
        setDeleteTarget(q);
        openDelete();
      },
    }),
  ];

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

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

      <AdvancedTable
        columns={columns}
        data={page.rows}
        title={t("question.pool")}
        tableName={t("question.title")}
        toolbar={
          <Select
            placeholder={t("question.filterByCertification")}
            data={[{ value: "", label: "All" }, ...certOptions]}
            value={certFilter}
            onChange={(v) => {
              setCertFilter(v ?? null);
              setPageIndex(0);
            }}
            size="sm"
            style={{ width: 280 }}
            clearable
          />
        }
        itemCount={page.itemCount}
        pageIndex={page.pageIndex}
        onPageChange={setPageIndex}
        pageSize={pageSize}
        onPageSizeChange={setPageSize}
        refresh={refetch}
        isLoading={isFetching}
        emptyText={t("question.noQuestions")}
      />

      <Modal
        opened={Boolean(reviewTarget)}
        onClose={() => setReviewTarget(null)}
        title={t("question.qc.reviewTitle")}
        size="md"
        radius="lg"
      >
        <Stack gap="sm">
          <Text fz="sm" fw={500}>
            {reviewTarget?.title?.[locale]}
          </Text>
          <Text fz="xs" c="dimmed">
            {t("question.qc.onlyApprovedUsable")}
          </Text>
          <Badge
            variant="light"
            color={
              reviewOutcome === "APPROVED"
                ? "teal"
                : reviewOutcome === "REJECTED"
                  ? "red"
                  : "dark"
            }
            w="fit-content"
          >
            {t(`question.qc.${reviewOutcome}`)}
          </Badge>
          <Textarea
            label={t("question.qc.remark")}
            minRows={3}
            autosize
            value={reviewRemark}
            onChange={(e) => setReviewRemark(e.currentTarget.value)}
            required={reviewOutcome !== "APPROVED"}
          />
          <Group justify="flex-end">
            <Button
              variant="default"
              size="sm"
              onClick={() => setReviewTarget(null)}
            >
              {t("question.cancel")}
            </Button>
            <Button size="sm" loading={isReviewing} onClick={handleReview}>
              {t(
                `question.qc.${reviewOutcome === "APPROVED" ? "approve" : reviewOutcome === "REJECTED" ? "reject" : "retire"}`,
              )}
            </Button>
          </Group>
        </Stack>
      </Modal>

      <Modal
        opened={deleteOpened}
        onClose={closeDelete}
        title={t("question.confirmDelete")}
        size="sm"
      >
        <Text mb="md">{t("question.deleteConfirmText")}</Text>
        <ModalFooter>
          <Button variant="default" onClick={closeDelete} size="sm">
            {t("question.cancel")}
          </Button>
          <Button color="red" onClick={handleDelete} size="sm">
            {t("question.delete")}
          </Button>
        </ModalFooter>
      </Modal>
    </Stack>
  );
}
