"use client";

import { Ban, Eye, Pencil, 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 {
  deleteAdminDraw,
  getAdminDraws,
  postAdminBatchDestroyDraws,
  postAdminCancelDraw,
  postAdminGenerateDrawPlan,
} from "@/api/admin-draws";
import { useAdminDateTimeFormatter } from "@/hooks/use-admin-datetime-formatter";
import { LOTTERY_SCHEDULE_TIMEZONE } from "@/lib/lottery-schedule-timezone";
import { AdminTableLoadingRow } from "@/components/admin/admin-loading-state";
import { AdminTableNoResourceRow } from "@/components/admin/admin-no-resource-state";
import { AdminRowActionsMenu } from "@/components/admin/admin-row-actions-menu";
import { Button } from "@/components/ui/button";
import { AdminTableExportButton } from "@/components/admin/admin-table-export-button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { AdminListPaginationFooter } from "@/components/admin/admin-list-pagination-footer";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Checkbox } from "@/components/ui/checkbox";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { useAdminCurrencyCatalog } from "@/hooks/use-admin-currency-catalog";
import { DrawCreateDialog } from "./draw-create-dialog";
import { DrawEditDialog } from "./draw-edit-dialog";
import {
  canCancelDrawRow,
  canDeleteDrawRow,
  canEditDrawRow,
} from "./draw-list-actions";
import { AdminTableMoney, adminMoneyCellClassName } from "@/components/admin/admin-table-money";
import { formatAdminMinorUnits } from "@/lib/money";
import { useConfirmAction } from "@/hooks/use-confirm-action";
import { useExportLabels } from "@/hooks/use-export-labels";
import { signedMoneyClass } from "@/lib/admin-signed-money";
import { cn } from "@/lib/utils";
import { useAdminProfile } from "@/stores/admin-session";
import { LotteryApiBizError } from "@/types/api/errors";
import type { AdminDrawListData, AdminDrawListItem } from "@/types/api/admin-draws";

import { drawStatusLabel } from "./draw-display";
import { canManageDrawResults, canViewDrawFinance } from "@/lib/draw-access";
import { DrawStatusBadge } from "./draw-status-badge";

/** 下拉「不限」；请求时不传 status */
const DRAW_FILTER_ALL = "__all__";

/** 与 {@see App\Lottery\DrawStatus} 一致 */
const DRAW_STATUS_OPTIONS: { value: string; label: string }[] = [
  { value: "pending", label: "statusOptions.pending" },
  { value: "open", label: "statusOptions.open" },
  { value: "closing", label: "statusOptions.closing" },
  { value: "closed", label: "statusOptions.closed" },
  { value: "drawing", label: "statusOptions.drawing" },
  { value: "review", label: "statusOptions.review" },
  { value: "cooldown", label: "statusOptions.cooldown" },
  { value: "settling", label: "statusOptions.settling" },
  { value: "settled", label: "statusOptions.settled" },
  { value: "cancelled", label: "statusOptions.cancelled" },
];

function drawAdminStatusSelectLabel(raw: unknown, t: (key: string) => string): string {
  const v = raw == null ? "" : String(raw);
  if (v === "" || v === DRAW_FILTER_ALL) {
    return t("statusOptions.all");
  }
  const key = DRAW_STATUS_OPTIONS.find((o) => o.value === v)?.label;
  return key ? t(key) : v;
}

export function DrawsIndexConsole() {
  const { t } = useTranslation(["draws", "common"]);
  const tRef = useTranslationRef(["draws", "common"]);
  const exportLabels = useExportLabels("drawsList");
  useAdminCurrencyCatalog();
  const defaultCurrency = "NPR";
  const profile = useAdminProfile();
  const canManageDraw = canManageDrawResults(profile?.permissions);
  const canViewFinance = canViewDrawFinance(profile?.permissions);
  const { request: requestConfirm, ConfirmDialog } = useConfirmAction();
  const [data, setData] = useState<AdminDrawListData | null>(null);
  const formatDt = useAdminDateTimeFormatter();
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [draftDrawNo, setDraftDrawNo] = useState("");
  const [draftStatus, setDraftStatus] = useState("");
  const [appliedDrawNo, setAppliedDrawNo] = useState("");
  const [appliedStatus, setAppliedStatus] = useState("");
  const [appliedAgentNodeId, setAppliedAgentNodeId] = useState<number | undefined>(undefined);
  const [page, setPage] = useState(1);
  const [perPage, setPerPage] = useState<number>(10);
  const [generating, setGenerating] = useState(false);
  const [createOpen, setCreateOpen] = useState(false);
  const [editDraw, setEditDraw] = useState<AdminDrawListItem | null>(null);
  const [selectedDrawIds, setSelectedDrawIds] = useState<Set<number>>(new Set());
  const [batchDeleting, setBatchDeleting] = useState(false);

  const drawStatusTriggerLabel = useMemo(
    () =>
      drawAdminStatusSelectLabel(
        draftStatus === "" || !DRAW_STATUS_OPTIONS.some((o) => o.value === draftStatus)
          ? DRAW_FILTER_ALL
          : draftStatus,
        t,
      ),
    [draftStatus, t],
  );

  const load = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const d = await getAdminDraws({
        page,
        per_page: perPage,
        draw_no: appliedDrawNo.trim() || undefined,
        status:
          appliedStatus.trim() === "" || appliedStatus === DRAW_FILTER_ALL
            ? undefined
            : appliedStatus.trim(),
        agent_node_id: appliedAgentNodeId,
      });
      setData(d);
    } catch (e) {
      const msg =
        e instanceof LotteryApiBizError ? e.message : tRef.current("loadFailed");
      setError(msg);
      setData(null);
    } finally {
      setLoading(false);
    }
  }, [page, perPage, appliedDrawNo, appliedStatus, appliedAgentNodeId, tRef]);

  async function generatePlan(): Promise<void> {
    setGenerating(true);
    try {
      const res = await postAdminGenerateDrawPlan();
      toast.success(
        t("generateSuccess", {
          created: res.created,
          upcoming: res.upcoming,
          target: res.buffer_target,
        }),
      );
      await load();
    } catch (e) {
      toast.error(e instanceof LotteryApiBizError ? e.message : t("generateFailed"));
    } finally {
      setGenerating(false);
    }
  }

  useAsyncEffect(() => {
    void load();
  }, [page, perPage, appliedDrawNo, appliedStatus, appliedAgentNodeId]);

  const handleSelectAll = useCallback((checked: boolean) => {
    if (checked && data) {
      const deletableIds = data.items
        .filter((row) => canDeleteDrawRow(row))
        .map((row) => row.id);
      setSelectedDrawIds(new Set(deletableIds));
    } else {
      setSelectedDrawIds(new Set());
    }
  }, [data]);

  const handleSelectRow = useCallback((drawId: number, checked: boolean) => {
    setSelectedDrawIds((prev) => {
      const next = new Set(prev);
      if (checked) {
        next.add(drawId);
      } else {
        next.delete(drawId);
      }
      return next;
    });
  }, []);

  const isAllSelected = useMemo(() => {
    if (!data) return false;
    const deletableIds = data.items.filter((row) => canDeleteDrawRow(row)).map((row) => row.id);
    return deletableIds.length > 0 && deletableIds.every((id) => selectedDrawIds.has(id));
  }, [data, selectedDrawIds]);

  const isSomeSelected = useMemo(() => {
    if (!data) return false;
    const deletableIds = data.items.filter((row) => canDeleteDrawRow(row)).map((row) => row.id);
    return deletableIds.some((id) => selectedDrawIds.has(id));
  }, [data, selectedDrawIds]);

  async function handleBatchDelete(): Promise<void> {
    if (selectedDrawIds.size === 0) return;
    
    setBatchDeleting(true);
    try {
      const result = await postAdminBatchDestroyDraws(Array.from(selectedDrawIds));
      
      if (result.failed.length > 0) {
        toast.error(
          t("batchDelete.partialFailed", {
            success: result.success.length,
            failed: result.failed.length,
          }),
        );
        result.failed.forEach((f) => {
          console.error(`Failed to delete draw ${f.id}: ${f.reason}`);
        });
      } else {
        toast.success(
          t("batchDelete.success", { count: result.success.length }),
        );
      }

      setSelectedDrawIds((prev) => {
        const next = new Set(prev);
        for (const id of result.success) {
          next.delete(id);
        }
        return next;
      });
      await load();
    } catch (e) {
      toast.error(e instanceof LotteryApiBizError ? e.message : t("batchDelete.failed"));
    } finally {
      setBatchDeleting(false);
    }
  }

  return (
    <>
    <Card className="admin-list-card">
      <CardHeader className="admin-list-header flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
        <CardTitle className="admin-list-title">{t("statusListTitle")}</CardTitle>
        {canManageDraw ? (
          <div className="flex flex-wrap gap-2">
            <Button type="button" variant="outline" onClick={() => setCreateOpen(true)}>
              {t("createDraw.open")}
            </Button>
            <Button
              type="button"
              onClick={() =>
                requestConfirm({
                  title: t("confirm.generatePlanTitle"),
                  description: t("confirm.generatePlanDescription"),
                  onConfirm: () => generatePlan(),
                })
              }
              disabled={generating}
            >
              {generating ? t("generating") : t("generatePlan")}
            </Button>
            {selectedDrawIds.size > 0 && (
              <Button
                type="button"
                variant="destructive"
                onClick={() =>
                  requestConfirm({
                    title: t("batchDelete.confirmTitle"),
                    description: t("batchDelete.confirmDescription", { count: selectedDrawIds.size }),
                    confirmVariant: "destructive",
                    onConfirm: () => handleBatchDelete(),
                  })
                }
                disabled={batchDeleting}
              >
                {batchDeleting ? t("batchDelete.deleting") : t("batchDelete.action", { count: selectedDrawIds.size })}
              </Button>
            )}
          </div>
        ) : null}
      </CardHeader>
      <CardContent className="admin-list-content">
        <div className="admin-list-toolbar">
          <div className="admin-list-field xl:min-w-0">
            <Label htmlFor="draw-filter-no" className="sm:w-10 sm:shrink-0">
              {t("drawNo")}
            </Label>
            <Input
              id="draw-filter-no"
              placeholder={t("fuzzyDrawNo")}
              value={draftDrawNo}
              className="w-full sm:w-[16rem] xl:w-[20rem]"
              onChange={(e) => setDraftDrawNo(e.target.value)}
            />
          </div>
          <div className="admin-list-field">
            <Label htmlFor="draw-filter-status" className="sm:w-10 sm:shrink-0">
              {t("status")}
            </Label>
            <div className="min-w-0">
              <Select
                modal={false}
                value={
                  draftStatus === "" ||
                  !DRAW_STATUS_OPTIONS.some((o) => o.value === draftStatus)
                    ? DRAW_FILTER_ALL
                    : draftStatus
                }
                onValueChange={(v) =>
                  setDraftStatus(v == null || v === DRAW_FILTER_ALL ? "" : String(v))
                }
              >
                <SelectTrigger id="draw-filter-status" className="h-8 w-full sm:w-44">
                  <SelectValue>{drawStatusTriggerLabel}</SelectValue>
                </SelectTrigger>
                <SelectContent align="start" sideOffset={6}>
                  <SelectItem value={DRAW_FILTER_ALL}>{t("statusOptions.all")}</SelectItem>
                  {DRAW_STATUS_OPTIONS.map((o) => (
                    <SelectItem key={o.value} value={o.value}>
                      {t(o.label)}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>
          <div className="admin-list-actions">
            <AdminTableExportButton
              tableId="draws-index-table"
              filename={exportLabels.filename}
              sheetName={exportLabels.sheetName}
            />
            <Button
              type="button"
              onClick={() => {
                setAppliedDrawNo(draftDrawNo);
                setAppliedStatus(draftStatus);
                setAppliedAgentNodeId(undefined);
                setPage(1);
              }}
            >
              {t("queryDraw")}
            </Button>
            <Button
              type="button"
              variant="outline"
              onClick={() => {
                setDraftDrawNo("");
                setDraftStatus("");
                setAppliedDrawNo("");
                setAppliedStatus("");
                setAppliedAgentNodeId(undefined);
                setPage(1);
              }}
            >
              {t("reset")}
            </Button>
          </div>
        </div>

        {error ? (
          <p className="text-sm text-destructive">{error}</p>
        ) : null}

        <div className="admin-table-shell">
          <Table id="draws-index-table">
            <TableHeader>
              <TableRow>
                <TableHead className="w-12">
                  {canManageDraw && data && data.items.some((row) => canDeleteDrawRow(row)) ? (
                    <Checkbox
                      checked={isAllSelected}
                      onCheckedChange={(checked) => handleSelectAll(checked === true)}
                      indeterminate={isSomeSelected && !isAllSelected}
                    />
                  ) : null}
                </TableHead>
                <TableHead>{t("drawNo")}</TableHead>
                <TableHead>{t("startTime")}</TableHead>
                <TableHead>{t("closeTime")}</TableHead>
                <TableHead>{t("drawTime")}</TableHead>
                <TableHead>{t("status")}</TableHead>
                {canViewFinance ? (
                  <>
                    <TableHead className="text-center">{t("betTotal")}</TableHead>
                    <TableHead className="text-center">{t("payoutTotal")}</TableHead>
                    <TableHead className="text-center">{t("profitLoss")}</TableHead>
                  </>
                ) : null}
                <TableHead className="sticky right-0 z-20 bg-muted w-14 text-center shadow-[-1px_0_0_rgba(203,213,225,0.7)]">{t("table.actions", { ns: "common" })}</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {loading ? (
                <AdminTableLoadingRow colSpan={canViewFinance ? 10 : 7} />
              ) : data === null || data.items.length === 0 ? (
                <AdminTableNoResourceRow colSpan={canViewFinance ? 10 : 7} className="text-muted-foreground" />
              ) : (
                data.items.map((row: AdminDrawListItem) => (
                  <TableRow key={row.id}>
                    <TableCell className="w-12">
                      {canManageDraw && canDeleteDrawRow(row) ? (
                        <Checkbox
                          checked={selectedDrawIds.has(row.id)}
                          onCheckedChange={(checked) => handleSelectRow(row.id, checked === true)}
                        />
                      ) : null}
                    </TableCell>
                    <TableCell className="font-mono text-xs">{row.draw_no}</TableCell>
                    <TableCell className="text-sm">{formatDt(row.start_time)}</TableCell>
                    <TableCell className="text-sm">{formatDt(row.close_time)}</TableCell>
                    <TableCell className="text-sm">{formatDt(row.draw_time)}</TableCell>
                    <TableCell>
                      <DrawStatusBadge
                        status={row.status}
                        label={drawStatusLabel(row.status, t)}
                      />
                    </TableCell>
                    {canViewFinance ? (
                      <>
                        <TableCell className={adminMoneyCellClassName("text-center text-xs")}>
                          {row.total_bet_minor != null ? (
                            <AdminTableMoney>
                              {formatAdminMinorUnits(row.total_bet_minor, defaultCurrency)}
                            </AdminTableMoney>
                          ) : "—"}
                        </TableCell>
                        <TableCell className={adminMoneyCellClassName("text-center text-xs")}>
                          {row.total_payout_minor != null ? (
                            <AdminTableMoney>
                              {formatAdminMinorUnits(row.total_payout_minor, defaultCurrency)}
                            </AdminTableMoney>
                          ) : "—"}
                        </TableCell>
                        <TableCell
                          className={adminMoneyCellClassName(
                            cn("text-center text-xs", signedMoneyClass(row.profit_loss_minor ?? 0, true)),
                          )}
                        >
                          {row.profit_loss_minor != null ? (
                            <AdminTableMoney>
                              {formatAdminMinorUnits(row.profit_loss_minor, defaultCurrency)}
                            </AdminTableMoney>
                          ) : "—"}
                        </TableCell>
                      </>
                    ) : null}
                    <TableCell className="sticky right-0 z-10 bg-card text-center shadow-[-1px_0_0_rgba(203,213,225,0.7)]">
                      <AdminRowActionsMenu
                        actions={[
                          {
                            key: "view",
                            label: t("viewDetails"),
                            icon: Eye,
                            href: `/admin/draws/${row.id}`,
                          },
                          {
                            key: "edit",
                            label: t("editDraw.action"),
                            icon: Pencil,
                            hidden: !(canManageDraw && canEditDrawRow(row)),
                            onClick: () => setEditDraw(row),
                          },
                          {
                            key: "cancel",
                            label: t("cancelFromList.action"),
                            icon: Ban,
                            hidden: !(
                              canManageDraw && canCancelDrawRow(row) && !canDeleteDrawRow(row)
                            ),
                            onClick: () =>
                              requestConfirm({
                                title: t("cancelFromList.title"),
                                description: t("cancelFromList.description", {
                                  drawNo: row.draw_no,
                                }),
                                onConfirm: async () => {
                                  try {
                                    await postAdminCancelDraw(row.id);
                                    toast.success(t("actionSuccess", { name: t("cancelDraw") }));
                                    await load();
                                  } catch (e) {
                                    toast.error(
                                      e instanceof LotteryApiBizError
                                        ? e.message
                                        : t("actionFailed", { name: t("cancelDraw") }),
                                    );
                                  }
                                },
                              }),
                          },
                          {
                            key: "delete",
                            label: t("deleteDraw.action"),
                            icon: Trash2,
                            destructive: true,
                            hidden: !(canManageDraw && canDeleteDrawRow(row)),
                            onClick: () =>
                              requestConfirm({
                                title: t("deleteDraw.title"),
                                description: t("deleteDraw.description", { drawNo: row.draw_no }),
                                confirmVariant: "destructive",
                                onConfirm: async () => {
                                  try {
                                    await deleteAdminDraw(row.id);
                                    toast.success(t("deleteDraw.success"));
                                    await load();
                                  } catch (e) {
                                    toast.error(
                                      e instanceof LotteryApiBizError
                                        ? e.message
                                        : t("deleteDraw.failed"),
                                    );
                                  }
                                },
                              }),
                          },
                        ]}
                      />
                    </TableCell>
                  </TableRow>
                ))
              )}
            </TableBody>
          </Table>
        </div>

        {data ? (
          <AdminListPaginationFooter
            selectId="draw-list-per-page"
            total={data.meta.total}
            page={page}
            lastPage={data.meta.last_page}
            perPage={perPage}
            loading={loading}
            onPerPageChange={(next) => {
              setPerPage(next);
              setPage(1);
            }}
            onPageChange={setPage}
          />
        ) : null}
      </CardContent>
    </Card>
    {canManageDraw ? (
      <DrawCreateDialog
        open={createOpen}
        onOpenChange={setCreateOpen}
        scheduleTimezone={LOTTERY_SCHEDULE_TIMEZONE}
        onCreated={load}
      />
    ) : null}
    {canManageDraw ? (
      <DrawEditDialog
        open={editDraw != null}
        onOpenChange={(open) => {
          if (!open) {
            setEditDraw(null);
          }
        }}
        draw={editDraw}
        scheduleTimezone={LOTTERY_SCHEDULE_TIMEZONE}
        onSaved={load}
      />
    ) : null}
    <ConfirmDialog />
    </>
  );
}
