"use client";

import { ChevronDown, ChevronRight, Dices, Rocket, Trash2 } from "lucide-react";
import { useCallback, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { useAsyncEffect } from "@/hooks/use-async-effect";
import { useTranslationRef } from "@/hooks/use-translation-ref";
import { toast } from "sonner";

import {
  deleteAdminPendingResultBatch,
  getAdminDrawResultBatches,
  postAdminCreateManualResultBatch,
} from "@/api/admin-draws";
import { AdminRowActionsMenu } from "@/components/admin/admin-row-actions-menu";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { AdminNoResourceState } from "@/components/admin/admin-no-resource-state";
import { AdminLoadingState } from "@/components/admin/admin-loading-state";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { useConfirmAction } from "@/hooks/use-confirm-action";
import { adminHasAnyPermission } from "@/lib/admin-permissions";

import { useAdminProfile } from "@/stores/admin-session";
import { LotteryApiBizError } from "@/types/api/errors";
import type { AdminDrawBatchRow, AdminDrawBatchesData } from "@/types/api/admin-draws";
import { DrawPublishDialog } from "@/modules/draws/draw-publish-dialog";
import { useDrawDetail } from "@/modules/draws/draw-detail-context";

import { PRD_DRAW_RESULT_MANAGE } from "./draw-prd";

const RESULT_SLOTS = [
  { prize_type: "first", prize_index: 0, label: "resultSlots.first" },
  { prize_type: "second", prize_index: 0, label: "resultSlots.second" },
  { prize_type: "third", prize_index: 0, label: "resultSlots.third" },
  ...Array.from({ length: 10 }, (_, i) => ({
    prize_type: "starter",
    prize_index: i,
    label: `resultSlots.starter`,
    labelIndex: i + 1,
  })),
  ...Array.from({ length: 10 }, (_, i) => ({
    prize_type: "consolation",
    prize_index: i,
    label: `resultSlots.consolation`,
    labelIndex: i + 1,
  })),
] as const;

function randomDrawNumber4d(): string {
  return String(Math.floor(Math.random() * 10_000)).padStart(4, "0");
}

export function DrawReviewConsole({ drawId }: { drawId: string }): React.ReactElement {
  const { t } = useTranslation(["draws", "common"]);
  const tRef = useTranslationRef(["draws", "common"]);
  const profile = useAdminProfile();
  const canManageDraw = adminHasAnyPermission(profile?.permissions, [PRD_DRAW_RESULT_MANAGE]);
  const { refresh: refreshDraw } = useDrawDetail();
  const idNum = Number(drawId);
  const [data, setData] = useState<AdminDrawBatchesData | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [savingManual, setSavingManual] = useState(false);
  const [discardingBatchId, setDiscardingBatchId] = useState<number | null>(null);
  const [manualOpen, setManualOpen] = useState(false);
  const [publishBatch, setPublishBatch] = useState<AdminDrawBatchRow | null>(null);
  const { request: requestConfirm, ConfirmDialog } = useConfirmAction();
  const [manualNumbers, setManualNumbers] = useState<string[]>(() => RESULT_SLOTS.map(() => ""));

  const load = useCallback(async () => {
    if (!Number.isFinite(idNum)) {
      setError(tRef.current("invalidDrawId"));
      setLoading(false);
      return;
    }
    setLoading(true);
    setError(null);
    try {
      setData(await getAdminDrawResultBatches(idNum));
    } catch (e) {
      setData(null);
      setError(e instanceof LotteryApiBizError ? e.message : tRef.current("errors.loadFailed", { ns: "common" }));
    } finally {
      setLoading(false);
    }
  }, [idNum, tRef]);

  useAsyncEffect(() => {
    void load();
  }, [load]);

  const pending = useMemo(() => data?.batches.filter((b) => b.status === "pending_review") ?? [], [data]);

  function fillRandomManualNumbers(): void {
    setManualNumbers(RESULT_SLOTS.map(() => randomDrawNumber4d()));
  }

  async function discardPendingBatch(batchId: number): Promise<void> {
    if (!Number.isFinite(idNum)) return;
    setDiscardingBatchId(batchId);
    try {
      await deleteAdminPendingResultBatch(idNum, batchId);
      toast.success(t("discardPendingBatchSuccess"));
      await load();
      await refreshDraw();
    } catch (e) {
      toast.error(e instanceof LotteryApiBizError ? e.message : t("discardPendingBatchFailed"));
    } finally {
      setDiscardingBatchId(null);
    }
  }

  async function saveManualDraft(): Promise<void> {
    if (!Number.isFinite(idNum)) return;
    const invalid = manualNumbers.some((n) => !/^[0-9]{4}$/.test(n));
    if (invalid) {
      toast.error(t("enter23Numbers"));
      return;
    }

    setSavingManual(true);
    try {
      const res = await postAdminCreateManualResultBatch(idNum, {
        items: RESULT_SLOTS.map((slot, i) => ({
          prize_type: slot.prize_type,
          prize_index: slot.prize_index,
          number_4d: manualNumbers[i],
        })),
      });
      toast.success(t("draftSaved", { version: res.batch.result_version }));
      setManualNumbers(RESULT_SLOTS.map(() => ""));
      setManualOpen(false);
      await load();
      await refreshDraw();
    } catch (e) {
      toast.error(e instanceof LotteryApiBizError ? e.message : t("saveFailed"));
    } finally {
      setSavingManual(false);
    }
  }

  async function onPublishFlowDone(): Promise<void> {
    await load();
    await refreshDraw();
  }

  if (loading && !data) {
    return <AdminLoadingState minHeight="6rem" className="py-6" />;
  }

  if (error) {
    return <p className="text-sm text-destructive">{error}</p>;
  }
  if (!data) {
    return <AdminNoResourceState />;
  }

  return (
    <div className="space-y-4">
      <div className="rounded-lg border border-border/60">
        <div className="border-b border-border/60 px-3 py-2.5">
          <h2 className="text-sm font-semibold">{t("pendingBatches")}</h2>
        </div>
        <div className="p-3">
          {pending.length === 0 ? (
            <AdminNoResourceState className="py-6" message={t("noPendingBatches")} />
          ) : (
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>{t("version", { version: "" }).replace(" v", "").trim()}</TableHead>
                  <TableHead>{t("numberCount")}</TableHead>
                  <TableHead className="w-14 text-center">{t("table.actions", { ns: "common" })}</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {pending.map((b) => (
                  <TableRow key={b.id}>
                    <TableCell>v{b.result_version}</TableCell>
                    <TableCell className="tabular-nums">{b.items.length}</TableCell>
                    <TableCell className="text-center">
                      {canManageDraw ? (
                        <AdminRowActionsMenu
                          busy={discardingBatchId === b.id}
                          actions={[
                            {
                              key: "publish",
                              label: t("reviewAndPublishAction"),
                              icon: Rocket,
                              onClick: () => setPublishBatch(b),
                            },
                            {
                              key: "discard",
                              label: t("discardPendingBatch"),
                              icon: Trash2,
                              destructive: true,
                              disabled: discardingBatchId !== null,
                              onClick: () =>
                                requestConfirm({
                                  title: t("confirm.discardPendingBatchTitle"),
                                  description: t("confirm.discardPendingBatchDescription"),
                                  confirmVariant: "destructive",
                                  onConfirm: () => discardPendingBatch(b.id),
                                }),
                            },
                          ]}
                        />
                      ) : (
                        <span className="text-xs text-muted-foreground">—</span>
                      )}
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          )}
        </div>
      </div>

      {canManageDraw ? (
        <div className="rounded-lg border border-border/60">
          <button
            type="button"
            className="flex w-full items-center justify-between px-3 py-2.5 text-left text-sm font-semibold"
            onClick={() => setManualOpen((open) => !open)}
          >
            {t("manualResultEntry")}
            {manualOpen ? (
              <ChevronDown className="size-4 text-muted-foreground" />
            ) : (
              <ChevronRight className="size-4 text-muted-foreground" />
            )}
          </button>
          {manualOpen ? (
            <div className="space-y-3 border-t border-border/60 px-3 py-3">
              <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
                {RESULT_SLOTS.map((slot, i) => (
                  <label key={`${slot.prize_type}-${slot.prize_index}`} className="space-y-1">
                    <span className="text-xs text-muted-foreground">
                      {t(slot.label, { index: "labelIndex" in slot ? slot.labelIndex : undefined })}
                    </span>
                    <Input
                      inputMode="numeric"
                      maxLength={4}
                      value={manualNumbers[i]}
                      disabled={savingManual}
                      placeholder="0000"
                      className="h-8 font-mono"
                      onChange={(e) => {
                        const next = e.target.value.replace(/\D/g, "").slice(0, 4);
                        setManualNumbers((old) => old.map((v, idx) => (idx === i ? next : v)));
                      }}
                    />
                  </label>
                ))}
              </div>
              <div className="flex flex-wrap justify-end gap-2">
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  className="h-8"
                  disabled={savingManual}
                  onClick={fillRandomManualNumbers}
                >
                  <Dices className="size-3.5" aria-hidden />
                  {t("fillRandomNumbers")}
                </Button>
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  className="h-8"
                  disabled={savingManual}
                  onClick={() => setManualNumbers(RESULT_SLOTS.map(() => ""))}
                >
                  {t("clear")}
                </Button>
                <Button
                  type="button"
                  size="sm"
                  className="h-8"
                  disabled={savingManual || !["closed", "review"].includes(data.draw_status)}
                  onClick={() =>
                    requestConfirm({
                      title: t("confirm.saveManualDraftTitle"),
                      description: t("confirm.saveManualDraftDescription"),
                      onConfirm: () => saveManualDraft(),
                    })
                  }
                >
                  {savingManual ? t("saving") : t("saveDraft")}
                </Button>
              </div>
            </div>
          ) : null}
        </div>
      ) : null}

      <DrawPublishDialog
        open={publishBatch != null}
        onOpenChange={(open) => {
          if (!open) {
            setPublishBatch(null);
          }
        }}
        drawId={idNum}
        batch={publishBatch}
        onPublished={() => void onPublishFlowDone()}
        onDiscarded={() => void onPublishFlowDone()}
      />
      <ConfirmDialog />
    </div>
  );
}