"use client";

import { Pencil, Trash2 } from "lucide-react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useConfirmAction } from "@/hooks/use-confirm-action";
import { useAdminDateTimeFormatter } from "@/hooks/use-admin-datetime-formatter";
import { useExportLabels } from "@/hooks/use-export-labels";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";

import {
  deleteAdminPlayer,
  getAdminPlayers,
  postAdminPlayer,
  postAdminPlayerFreeze,
  postAdminPlayerUnfreeze,
  putAdminPlayer,
} from "@/api/admin-player";
import { AdminListPaginationFooter } from "@/components/admin/admin-list-pagination-footer";
import { AdminRowActionsMenu } from "@/components/admin/admin-row-actions-menu";
import { AdminTableExportButton } from "@/components/admin/admin-table-export-button";
import { AdminStatusBadge } from "@/components/admin/admin-status-badge";
import { ConfirmableSwitch } from "@/components/admin/confirmable-switch";
import { resolvePlayerStatusTone } from "@/lib/admin-status-tone";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { adminHasAnyPermission } from "@/lib/admin-permissions";
import { PRD_PLAYER_FREEZE_MANAGE, PRD_USERS_MANAGE } from "@/lib/admin-prd";
import { useAdminProfile } from "@/stores/admin-session";
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 { useAdminSiteCodeOptions } from "@/hooks/use-admin-site-code-options";
import { formatAdminMinorUnits } from "@/lib/money";
import { LotteryApiBizError } from "@/types/api/errors";
import type { AdminPlayerRow, AdminPlayerWalletRow } from "@/types/api/admin-player";

function playerStatusLabelT(status: number, t: (key: string) => string): string {
  if (status === 0) return t("statusNormal");
  if (status === 1) return t("statusFrozen");
  if (status === 2) return t("statusBanned");
  return String(status);
}

function preferredDisplayWallet(row: AdminPlayerRow): AdminPlayerWalletRow | null {
  const { wallets, default_currency } = row;
  if (wallets.length === 0) {
    return null;
  }
  const code = default_currency.trim().toUpperCase();
  return wallets.find((w) => w.currency_code.toUpperCase() === code) ?? wallets[0];
}

const PLAYER_STATUS_OPTIONS = [
  { value: 0, label: "statusNormal" },
  { value: 1, label: "statusFrozen" },
  { value: 2, label: "statusBanned" },
];

export function PlayersConsole(): React.ReactElement {
  const { t } = useTranslation(["players", "common"]);
  const { request: requestConfirm, ConfirmDialog, busy: confirmBusy } = useConfirmAction();
  const formatDt = useAdminDateTimeFormatter();
  const exportLabels = useExportLabels("players");
  const profile = useAdminProfile();
  useAdminCurrencyCatalog();
  const canManagePlayers = adminHasAnyPermission(profile?.permissions, [PRD_USERS_MANAGE]);
  const canFreezePlayers = adminHasAnyPermission(profile?.permissions, [PRD_PLAYER_FREEZE_MANAGE]);
  const [page, setPage] = useState(1);
  const [perPage, setPerPage] = useState(10);
  const { sites: siteOptions, canChooseSite } = useAdminSiteCodeOptions();
  const [keyword, setKeyword] = useState("");
  const [query, setQuery] = useState("");
  const [siteCode, setSiteCode] = useState("");
  const [appliedSiteCode, setAppliedSiteCode] = useState("");

  const [items, setItems] = useState<AdminPlayerRow[]>([]);
  const [total, setTotal] = useState(0);
  const [lastPage, setLastPage] = useState(1);
  const [loading, setLoading] = useState(true);
  const [err, setErr] = useState<string | null>(null);

  const [accountOpen, setAccountOpen] = useState(false);
  const [accountMode, setAccountMode] = useState<"create" | "edit">("create");
  const [accountSaving, setAccountSaving] = useState(false);
  const [editingAccountId, setEditingAccountId] = useState<number | null>(null);
  const [formSiteCode, setFormSiteCode] = useState("");
  const [formSitePlayerId, setFormSitePlayerId] = useState("");
  const [formUsername, setFormUsername] = useState("");
  const [formNickname, setFormNickname] = useState("");
  const [formDefaultCurrency, setFormDefaultCurrency] = useState("NPR");
  const [formStatus, setFormStatus] = useState(0);

  const [deleteTarget, setDeleteTarget] = useState<AdminPlayerRow | null>(null);
  const [deleteBusy, setDeleteBusy] = useState(false);
  const [freezeBusyId, setFreezeBusyId] = useState<number | null>(null);

  const editingPlayer = useMemo(
    () => items.find((p) => p.id === editingAccountId) ?? null,
    [items, editingAccountId],
  );

  const load = useCallback(async () => {
    setLoading(true);
    setErr(null);
    try {
      const data = await getAdminPlayers({
        page,
        per_page: perPage,
        keyword: query.trim() || undefined,
        site_code: appliedSiteCode.trim() || undefined,
      });
      setItems(data.items);
      setTotal(data.meta.total);
      setLastPage(Math.max(1, data.meta.last_page));
    } catch (e) {
      const msg = e instanceof LotteryApiBizError ? e.message : t("loadFailed");
      setErr(msg);
      setItems([]);
      setTotal(0);
      setLastPage(1);
    } finally {
      setLoading(false);
    }
  }, [page, perPage, query, appliedSiteCode, t]);

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

  function openCreateAccount(): void {
    setAccountMode("create");
    setEditingAccountId(null);
    setFormSiteCode("");
    setFormSitePlayerId("");
    setFormUsername("");
    setFormNickname("");
    setFormDefaultCurrency("NPR");
    setFormStatus(0);
    setAccountOpen(true);
  }

  function openEditAccount(row: AdminPlayerRow): void {
    setAccountMode("edit");
    setEditingAccountId(row.id);
    setFormSiteCode(row.site_code);
    setFormSitePlayerId(row.site_player_id);
    setFormUsername(row.username ?? "");
    setFormNickname(row.nickname ?? "");
    setFormDefaultCurrency(row.default_currency);
    setFormStatus(row.status);
    setAccountOpen(true);
  }

  function handleAccountDialogOpenChange(open: boolean): void {
    setAccountOpen(open);
    if (!open) {
      setEditingAccountId(null);
    }
  }

  async function submitAccount(): Promise<void> {
    if (accountMode === "create") {
      if (formSiteCode.trim() === "") {
        toast.error(t("siteCodeRequired"));
        return;
      }
      if (formSitePlayerId.trim() === "") {
        toast.error(t("sitePlayerIdRequired"));
        return;
      }
      setAccountSaving(true);
      try {
        const created = await postAdminPlayer({
          site_code: formSiteCode.trim(),
          site_player_id: formSitePlayerId.trim(),
          username: formUsername.trim() || null,
          nickname: formNickname.trim() || null,
          default_currency: formDefaultCurrency,
          status: formStatus,
        });
        setItems((prev) => [created, ...prev]);
        setTotal((t) => t + 1);
        toast.success(t("createSuccess", { name: created.username ?? created.site_player_id }));
        handleAccountDialogOpenChange(false);
      } catch (e) {
        const msg = e instanceof LotteryApiBizError ? e.message : t("createFailed");
        toast.error(msg);
      } finally {
        setAccountSaving(false);
      }
    } else {
      const id = editingAccountId;
      if (id === null) return;

      const body: Parameters<typeof putAdminPlayer>[1] = {};
      if (formUsername.trim() !== "") {
        body.username = formUsername.trim();
      }
      if (formNickname !== editingPlayer?.nickname) {
        body.nickname = formNickname.trim() || null;
      }
      if (formDefaultCurrency !== editingPlayer?.default_currency) {
        body.default_currency = formDefaultCurrency.trim().toUpperCase();
      }
      if (formStatus !== editingPlayer?.status) {
        body.status = formStatus;
      }

      if (Object.keys(body).length === 0) {
        toast.success(t("noChanges"));
        handleAccountDialogOpenChange(false);
        return;
      }

      setAccountSaving(true);
      try {
        const updated = await putAdminPlayer(id, body);
        setItems((prev) => prev.map((row) => (row.id === updated.id ? updated : row)));
        toast.success(t("updateSuccess", { name: updated.username ?? updated.site_player_id }));
        handleAccountDialogOpenChange(false);
      } catch (e) {
        const msg = e instanceof LotteryApiBizError ? e.message : t("updateFailed");
        toast.error(msg);
      } finally {
        setAccountSaving(false);
      }
    }
  }

  async function toggleFreeze(row: AdminPlayerRow, freeze: boolean): Promise<void> {
    setFreezeBusyId(row.id);
    try {
      const updated = freeze
        ? await postAdminPlayerFreeze(row.id)
        : await postAdminPlayerUnfreeze(row.id);
      setItems((prev) => prev.map((r) => (r.id === updated.id ? updated : r)));
      const name = updated.username ?? updated.site_player_id;
      toast.success(freeze ? t("freezeSuccess", { name }) : t("unfreezeSuccess", { name }));
    } catch (e) {
      const msg =
        e instanceof LotteryApiBizError
          ? e.message
          : freeze
            ? t("freezeFailed")
            : t("unfreezeFailed");
      toast.error(msg);
    } finally {
      setFreezeBusyId(null);
    }
  }

  async function confirmDelete(): Promise<void> {
    if (!deleteTarget) return;
    setDeleteBusy(true);
    try {
      await deleteAdminPlayer(deleteTarget.id);
      setItems((prev) => prev.filter((r) => r.id !== deleteTarget.id));
      setTotal((t) => Math.max(0, t - 1));
      toast.success(t("deleteSuccess", { name: deleteTarget.username ?? deleteTarget.site_player_id }));
      setDeleteTarget(null);
    } catch (e) {
      const msg = e instanceof LotteryApiBizError ? e.message : t("deleteFailed");
      toast.error(msg);
    } finally {
      setDeleteBusy(false);
    }
  }

  return (
    <div className="flex w-full max-w-none flex-col gap-6">
      <Card className="admin-list-card">
        <CardHeader className="admin-list-header flex flex-col gap-4">
          <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3">
            <CardTitle className="admin-list-title">{t("listTitle")}</CardTitle>
            {canManagePlayers ? (
              <Button type="button" size="sm" onClick={() => openCreateAccount()}>
                {t("createPlayer")}
              </Button>
            ) : null}
          </div>
          <div className="admin-list-toolbar">
            {canChooseSite ? (
              <div className="admin-list-field">
                <Label className="sm:w-20 sm:shrink-0">{t("filterSite")}</Label>
                <Select
                  value={siteCode || "__all__"}
                  onValueChange={(v) => setSiteCode(v === "__all__" ? "" : v ?? "")}
                >
                  <SelectTrigger className="w-full sm:w-[12rem]">
                    <SelectValue>
                      {(v) => {
                        const value = String(v ?? "__all__");
                        if (value === "__all__") {
                          return t("filterAllSites");
                        }
                        const site = siteOptions.find((item) => item.code === value);
                        return site ? `${site.code} — ${site.name}` : value;
                      }}
                    </SelectValue>
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="__all__">{t("filterAllSites")}</SelectItem>
                    {siteOptions.map((site) => (
                      <SelectItem key={site.code} value={site.code}>
                        {site.code} — {site.name}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
            ) : null}
            <div className="admin-list-field xl:min-w-0">
              <Label htmlFor="player-search" className="sm:w-20 sm:shrink-0">
                {t("search")}
              </Label>
              <Input
                id="player-search"
                value={keyword}
                className="w-full sm:w-[18rem] xl:w-[24rem]"
                placeholder={t("searchPlaceholder")}
                onChange={(e) => setKeyword(e.target.value)}
                onKeyDown={(e) => {
                  if (e.key === "Enter") {
                    setPage(1);
                    setQuery(keyword.trim());
                    setAppliedSiteCode(siteCode.trim());
                  }
                }}
              />
            </div>
            <div className="admin-list-actions">
              <AdminTableExportButton
                tableId="players-table"
                filename={exportLabels.filename}
              sheetName={exportLabels.sheetName}
              />
              <Button
                type="button"
                onClick={() => {
                  setPage(1);
                  setQuery(keyword.trim());
                  setAppliedSiteCode(siteCode.trim());
                }}
              >
                {t("search")}
              </Button>
              <Button type="button" variant="secondary" onClick={() => void load()}>
                {t("refresh")}
              </Button>
            </div>
          </div>
        </CardHeader>
        <CardContent className="admin-list-content">
          {err ? <p className="text-sm text-red-600 dark:text-red-400">{err}</p> : null}
          {loading && items.length === 0 ? (
            <p className="text-sm text-muted-foreground">{t("states.loading", { ns: "common" })}</p>
          ) : null}
          <div className="admin-table-shell">
            <Table id="players-table">
              <TableHeader>
                <TableRow>
                  <TableHead className="w-16">{t("table.id", { ns: "common" })}</TableHead>
                  <TableHead>{t("site")}</TableHead>
                  <TableHead>{t("sitePlayerId")}</TableHead>
                  <TableHead>{t("username")}</TableHead>
                  <TableHead>{t("nickname")}</TableHead>
                  <TableHead className="whitespace-nowrap">{t("currency")}</TableHead>
                  <TableHead className="whitespace-nowrap text-center">{t("balance")}</TableHead>
                  <TableHead className="whitespace-nowrap text-center">{t("available")}</TableHead>
                  <TableHead className="w-20 whitespace-nowrap">{t("status")}</TableHead>
                  <TableHead className="whitespace-nowrap">{t("lastLogin")}</TableHead>
                  <TableHead className="w-14 text-center">{t("actions")}</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {items.length === 0 && !loading ? (
                  <TableRow>
                    <TableCell colSpan={11} className="text-muted-foreground">
                      {t("states.noData", { ns: "common" })}
                    </TableCell>
                  </TableRow>
                ) : (
                  items.map((row) => {
                    const displayWallet = preferredDisplayWallet(row);
                    return (
                    <TableRow key={row.id}>
                      <TableCell className="tabular-nums">#{row.id}</TableCell>
                      <TableCell>
                        <span className="font-mono text-xs">{row.site_code}</span>
                      </TableCell>
                      <TableCell>
                        <span className="font-mono text-xs">{row.site_player_id}</span>
                      </TableCell>
                      <TableCell>{row.username ?? "—"}</TableCell>
                      <TableCell>{row.nickname ?? "—"}</TableCell>
                      <TableCell>{row.default_currency}</TableCell>
                      <TableCell className="whitespace-nowrap text-center tabular-nums text-xs">
                        {displayWallet
                          ? formatAdminMinorUnits(displayWallet.balance, displayWallet.currency_code)
                          : "—"}
                      </TableCell>
                      <TableCell className="whitespace-nowrap text-center tabular-nums text-xs">
                        {displayWallet
                          ? formatAdminMinorUnits(
                              displayWallet.available_balance,
                              displayWallet.currency_code,
                            )
                          : "—"}
                      </TableCell>
                      <TableCell>
                        {row.status === 2 ? (
                          <div className="flex justify-center">
                            <AdminStatusBadge status={row.status} tone={resolvePlayerStatusTone(row.status)}>
                              {playerStatusLabelT(row.status, t)}
                            </AdminStatusBadge>
                          </div>
                        ) : canFreezePlayers ? (
                          <div className="flex justify-center">
                            <ConfirmableSwitch
                              checked={row.status === 0}
                              confirmBusy={confirmBusy}
                              disabled={freezeBusyId === row.id}
                              aria-label={t("status")}
                              onCheckedChange={(checked) => {
                                const name = row.username ?? row.site_player_id;
                                if (checked) {
                                  requestConfirm({
                                    title: t("confirmUnfreezeTitle"),
                                    description: t("confirmUnfreezeDescription", { name }),
                                    onConfirm: () => toggleFreeze(row, false),
                                  });
                                  return;
                                }
                                requestConfirm({
                                  title: t("confirmFreezeTitle"),
                                  description: t("confirmFreezeDescription", { name }),
                                  onConfirm: () => toggleFreeze(row, true),
                                });
                              }}
                            />
                          </div>
                        ) : (
                          <span className="text-xs text-muted-foreground">
                            {playerStatusLabelT(row.status, t)}
                          </span>
                        )}
                      </TableCell>
                      <TableCell className="whitespace-nowrap text-xs text-muted-foreground">
                        {row.last_login_at ? formatDt(row.last_login_at) : "—"}
                      </TableCell>
                      <TableCell className="text-center">
                        {canManagePlayers ? (
                          <AdminRowActionsMenu
                            actions={[
                              {
                                key: "edit",
                                label: t("edit"),
                                icon: Pencil,
                                onClick: () => openEditAccount(row),
                              },
                              {
                                key: "delete",
                                label: t("delete"),
                                icon: Trash2,
                                destructive: true,
                                onClick: () => setDeleteTarget(row),
                              },
                            ]}
                          />
                        ) : (
                          <span className="text-xs text-muted-foreground">—</span>
                        )}
                      </TableCell>
                    </TableRow>
                    );
                  })
                )}
              </TableBody>
            </Table>
          </div>
          <AdminListPaginationFooter
            selectId="admin-players-per-page"
            total={total}
            page={page}
            lastPage={lastPage}
            perPage={perPage}
            loading={loading}
            onPerPageChange={(n) => {
              setPerPage(n);
              setPage(1);
            }}
            onPageChange={setPage}
          />
        </CardContent>
      </Card>

      <Dialog open={accountOpen} onOpenChange={handleAccountDialogOpenChange}>
        <DialogContent showCloseButton className="max-h-[90vh] max-w-lg gap-4 overflow-y-auto sm:max-w-xl">
          <DialogHeader>
            <DialogTitle>{accountMode === "create" ? t("createDialogTitle") : t("editDialogTitle")}</DialogTitle>
            <DialogDescription>
              {accountMode === "create" ? t("createDialogDesc") : t("editDialogDesc")}
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-3">
            {accountMode === "create" && (
              <>
                <div className="space-y-1.5">
                  <Label htmlFor="player-site-code">{t("siteCode")}</Label>
                  <Input
                    id="player-site-code"
                    value={formSiteCode}
                    placeholder={t("siteCodePlaceholder")}
                    onChange={(e) => setFormSiteCode(e.target.value)}
                  />
                </div>
                <div className="space-y-1.5">
                  <Label htmlFor="player-site-id">{t("sitePlayerIdLabel")}</Label>
                  <Input
                    id="player-site-id"
                    value={formSitePlayerId}
                    placeholder={t("sitePlayerIdPlaceholder")}
                    onChange={(e) => setFormSitePlayerId(e.target.value)}
                  />
                </div>
              </>
            )}
            <div className="space-y-1.5">
              <Label htmlFor="player-username">{t("username")}</Label>
              <Input
                id="player-username"
                value={formUsername}
                disabled={accountMode === "edit"}
                placeholder={accountMode === "create" ? t("usernamePlaceholderOptional") : ""}
                onChange={(e) => setFormUsername(e.target.value)}
              />
            </div>
            <div className="space-y-1.5">
              <Label htmlFor="player-nickname">{t("nickname")}</Label>
              <Input
                id="player-nickname"
                value={formNickname}
                placeholder={t("nicknamePlaceholderOptional")}
                onChange={(e) => setFormNickname(e.target.value)}
              />
            </div>
            {accountMode === "create" && (
              <>
                <div className="space-y-1.5">
                  <Label htmlFor="player-currency">{t("defaultCurrency")}</Label>
                  <Input
                    id="player-currency"
                    value={formDefaultCurrency}
                    placeholder="NPR"
                    onChange={(e) => setFormDefaultCurrency(e.target.value.toUpperCase())}
                  />
                </div>
                <div className="space-y-1.5">
                  <Label htmlFor="player-status">{t("status")}</Label>
                  <Select
                    value={String(formStatus)}
                    onValueChange={(v) => setFormStatus(Number(v))}
                  >
                    <SelectTrigger id="player-status">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      {PLAYER_STATUS_OPTIONS.map((o) => (
                        <SelectItem key={o.value} value={String(o.value)}>
                          {t(o.label)}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
              </>
            )}
            {accountMode === "edit" && (
              <div className="space-y-1.5">
                <Label htmlFor="player-edit-status">{t("status")}</Label>
                <Select
                  value={String(formStatus)}
                  onValueChange={(v) => setFormStatus(Number(v))}
                >
                  <SelectTrigger id="player-edit-status">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    {PLAYER_STATUS_OPTIONS.map((o) => (
                      <SelectItem key={o.value} value={String(o.value)}>
                        {t(o.label)}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
            )}
          </div>
          <div className="flex justify-end gap-2">
            <Button
              type="button"
              variant="outline"
              onClick={() => handleAccountDialogOpenChange(false)}
            >
              {t("cancel")}
            </Button>
            <Button
              type="button"
              disabled={accountSaving}
              onClick={() => void submitAccount()}
            >
              {accountSaving ? t("saving") : t("save")}
            </Button>
          </div>
        </DialogContent>
      </Dialog>

      <Dialog open={deleteTarget !== null} onOpenChange={(open) => !open && setDeleteTarget(null)}>
        <DialogContent showCloseButton className="max-w-sm">
          <DialogHeader>
            <DialogTitle>{t("confirmDelete")}</DialogTitle>
            <DialogDescription>
              {deleteTarget
                ? t("confirmDeleteDesc", {
                    name: deleteTarget.username ?? deleteTarget.site_player_id,
                  })
                : null}
            </DialogDescription>
          </DialogHeader>
          <div className="flex justify-end gap-2">
            <Button type="button" variant="outline" onClick={() => setDeleteTarget(null)}>
              {t("cancel")}
            </Button>
            <Button type="button" variant="destructive" disabled={deleteBusy} onClick={() => void confirmDelete()}>
              {deleteBusy ? t("actions.submitting", { ns: "common" }) : t("delete")}
            </Button>
          </div>
        </DialogContent>
      </Dialog>
      <ConfirmDialog />
    </div>
  );
}
