"use client";

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

import {
  deleteAdminUser,
  getAdminUserPermissionCatalog,
  getAdminUsers,
  postAdminUser,
  putAdminUser,
  putAdminUserRoles,
} from "@/api/admin-users";
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 { Badge } from "@/components/ui/badge";
import { resolveAdminUserStatusTone } from "@/lib/admin-status-tone";
import { Button } from "@/components/ui/button";
import { Switch } from "@/components/ui/switch";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { adminHasAnyPermission } from "@/lib/admin-permissions";
import { PRD_ADMIN_USER_MANAGE } from "@/lib/admin-prd";
import { cn } from "@/lib/utils";
import { useAdminProfile } from "@/stores/admin-session";
import type { AdminPermissionCatalogData, AdminUserPermissionRow } from "@/types/api/index";
import { LotteryApiBizError } from "@/types/api/errors";

export function AdminUsersConsole(): React.ReactElement {
  const { t } = useTranslation(["adminUsers", "common"]);
  const { request: requestConfirm, ConfirmDialog } = useConfirmAction();
  const exportLabels = useExportLabels("adminUsers");
  const profile = useAdminProfile();
  const canManageUsers = adminHasAnyPermission(profile?.permissions, [PRD_ADMIN_USER_MANAGE]);
  const [page, setPage] = useState(1);
  const [perPage, setPerPage] = useState(10);
  const [keyword, setKeyword] = useState("");
  const [query, setQuery] = useState("");

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

  const [selectedId, setSelectedId] = useState<number | null>(null);
  const [draftRoles, setDraftRoles] = useState<string[]>([]);
  const [savingRoles, setSavingRoles] = useState(false);
  const [permissionOpen, setPermissionOpen] = useState(false);

  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 [formUsername, setFormUsername] = useState("");
  const [formNickname, setFormNickname] = useState("");
  const [formEmail, setFormEmail] = useState("");
  const [formPassword, setFormPassword] = useState("");
  const [formStatus, setFormStatus] = useState(0);
  const [formCreateRoles, setFormCreateRoles] = useState<string[]>([]);

  const [deleteTarget, setDeleteTarget] = useState<AdminUserPermissionRow | null>(null);
  const [deleteBusy, setDeleteBusy] = useState(false);

  const selectedUser = useMemo(
    () => items.find((u) => u.id === selectedId) ?? null,
    [items, selectedId],
  );
  const roleNameBySlug = useMemo(
    () => new Map((catalog?.roles ?? []).map((role) => [role.slug, role.name])),
    [catalog],
  );

  const load = useCallback(async () => {
    setLoading(true);
    setErr(null);
    try {
      const [catalogData, listData] = await Promise.all([
        getAdminUserPermissionCatalog(),
        getAdminUsers({
          page,
          per_page: perPage,
          keyword: query.trim() || undefined,
        }),
      ]);
      setCatalog(catalogData);
      setItems(listData.items);
      setTotal(listData.meta.total);
      setLastPage(Math.max(1, listData.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, t]);

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

  function toggleFormCreateRole(slug: string, checked: boolean): void {
    setFormCreateRoles((prev) => {
      if (checked) {
        return Array.from(new Set([...prev, slug])).sort();
      }
      return prev.filter((value) => value !== slug);
    });
  }

  function toggleRole(slug: string, checked: boolean): void {
    setDraftRoles((prev) => {
      if (checked) {
        return Array.from(new Set([...prev, slug])).sort();
      }
      return prev.filter((value) => value !== slug);
    });
  }

  function openPermissionEditor(row: AdminUserPermissionRow): void {
    setSelectedId(row.id);
    setDraftRoles([...row.roles].sort());
    setPermissionOpen(true);
  }

  function handlePermissionDialogOpenChange(open: boolean): void {
    setPermissionOpen(open);
    if (!open) {
      setSelectedId(null);
    }
  }

  function openCreateAccount(): void {
    setAccountMode("create");
    setEditingAccountId(null);
    setFormUsername("");
    setFormNickname("");
    setFormEmail("");
    setFormPassword("");
    setFormStatus(0);
    setFormCreateRoles([]);
    setAccountOpen(true);
  }

  function openEditAccount(row: AdminUserPermissionRow): void {
    setAccountMode("edit");
    setEditingAccountId(row.id);
    setFormUsername(row.username);
    setFormNickname(row.nickname);
    setFormEmail(row.email ?? "");
    setFormPassword("");
    setFormStatus(row.status);
    setAccountOpen(true);
  }

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

  async function submitAccount(): Promise<void> {
    const nickname = formNickname.trim();
    if (nickname === "") {
      toast.error(t("nicknameRequired"));
      return;
    }
    if (accountMode === "edit" && formPassword !== "" && formPassword.length < 8) {
      toast.error(t("newPasswordMin"));
      return;
    }
    if (accountMode === "create" && formCreateRoles.length === 0) {
      toast.error(t("roleRequired"));
      return;
    }

    setAccountSaving(true);
    try {
      if (accountMode === "create") {
        const username = formUsername.trim();
        if (username === "") {
          toast.error(t("usernameRequired"));
          return;
        }
        if (formPassword.length < 8) {
          toast.error(t("passwordMin"));
          return;
        }
        const created = await postAdminUser({
          username: username.toLowerCase(),
          nickname,
          email: formEmail.trim() === "" ? null : formEmail.trim(),
          password: formPassword,
          status: formStatus,
          role_slugs: formCreateRoles,
        });
        setItems((prev) => [created, ...prev]);
        setTotal((prev) => prev + 1);
        toast.success(t("createSuccess", { name: created.username }));
        handleAccountDialogOpenChange(false);
      } else {
        const id = editingAccountId;
        if (id === null) {
          return;
        }
        const body: {
          nickname: string;
          email: string | null;
          status: number;
          password?: string;
        } = {
          nickname,
          email: formEmail.trim() === "" ? null : formEmail.trim(),
          status: formStatus,
        };
        if (formPassword.trim() !== "") {
          body.password = formPassword.trim();
        }
        const updated = await putAdminUser(id, body);
        setItems((prev) => prev.map((row) => (row.id === updated.id ? updated : row)));
        toast.success(t("updateSuccess", { name: updated.username }));
        handleAccountDialogOpenChange(false);
      }
    } catch (e) {
      const msg = e instanceof LotteryApiBizError ? e.message : t("saveAccountFailed");
      toast.error(msg);
    } finally {
      setAccountSaving(false);
    }
  }

  async function saveRoles(): Promise<void> {
    if (!selectedUser) {
      return;
    }
    setSavingRoles(true);
    try {
      const result = await putAdminUserRoles(selectedUser.id, draftRoles);
      setDraftRoles([...result.roles].sort());
      setItems((prev) =>
        prev.map((row) =>
          row.id === result.id
            ? {
                ...row,
                roles: result.roles,
                effective_permissions: result.effective_permissions,
              }
            : row,
        ),
      );
      toast.success(t("saveRoleSuccess", { name: result.username }));
    } catch (e) {
      const msg = e instanceof LotteryApiBizError ? e.message : t("saveRoleFailed");
      toast.error(msg);
    } finally {
      setSavingRoles(false);
    }
  }

  async function confirmDelete(): Promise<void> {
    if (!deleteTarget) {
      return;
    }
    setDeleteBusy(true);
    try {
      await deleteAdminUser(deleteTarget.id);
      setItems((prev) => prev.filter((row) => row.id !== deleteTarget.id));
      setTotal((prev) => Math.max(0, prev - 1));
      toast.success(t("deleteSuccess", { name: deleteTarget.username }));
      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>
            {canManageUsers ? (
              <Button type="button" size="sm" onClick={() => openCreateAccount()}>
                {t("createAdmin")}
              </Button>
            ) : null}
          </div>
          <div className="admin-list-toolbar">
            <div className="admin-list-field xl:min-w-0">
              <Label htmlFor="admin-user-search" className="sm:w-20 sm:shrink-0">
                {t("actions.search", { ns: "common" })}
              </Label>
              <Input
                id="admin-user-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());
                  }
                }}
              />
            </div>
            <div className="admin-list-actions">
              <AdminTableExportButton
                tableId="admin-users-table"
                filename={exportLabels.filename}
              sheetName={exportLabels.sheetName}
              />
              <Button
                type="button"
                onClick={() => {
                  setPage(1);
                  setQuery(keyword.trim());
                }}
              >
                {t("actions.search", { ns: "common" })}
              </Button>
              <Button type="button" variant="secondary" onClick={() => void load()}>
                {t("actions.refresh", { ns: "common" })}
              </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="admin-users-table">
              <TableHeader>
                <TableRow>
                  <TableHead className="w-16">{t("table.id", { ns: "common" })}</TableHead>
                  <TableHead>{t("table.account")}</TableHead>
                  <TableHead>{t("table.nickname")}</TableHead>
                  <TableHead className="w-20 whitespace-nowrap">{t("table.status")}</TableHead>
                  <TableHead>{t("table.roles")}</TableHead>
                  <TableHead>{t("table.effective")}</TableHead>
                  <TableHead className="w-14 whitespace-nowrap text-center">{t("table.actions")}</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {items.length === 0 ? (
                  <TableRow>
                    <TableCell colSpan={7} className="text-muted-foreground">
                      {t("states.noData", { ns: "common" })}
                    </TableCell>
                  </TableRow>
                ) : (
                  items.map((row) => (
                    <TableRow key={row.id}>
                      <TableCell>{row.id}</TableCell>
                      <TableCell>
                        <div className="flex flex-col">
                          <span className="font-medium">{row.username}</span>
                          <span className="text-xs text-muted-foreground">{row.email ?? ""}</span>
                        </div>
                      </TableCell>
                      <TableCell>{row.nickname ?? ""}</TableCell>
                      <TableCell>
                        <AdminStatusBadge status={row.status} tone={resolveAdminUserStatusTone(row.status)}>
                          {row.status === 0 ? t("status.enabled") : t("status.disabled")}
                        </AdminStatusBadge>
                      </TableCell>
                      <TableCell>
                        <div className="flex flex-wrap gap-1">
                          {row.roles.length === 0 ? (
                            <span className="text-xs text-muted-foreground">{t("common.none")}</span>
                          ) : (
                            row.roles.map((slug) => (
                              <Badge key={slug} variant="secondary">
                                {roleNameBySlug.get(slug) ?? slug}
                              </Badge>
                            ))
                          )}
                        </div>
                      </TableCell>
                      <TableCell className="tabular-nums">{row.effective_permissions.length}</TableCell>
                      <TableCell className="text-center">
                        {canManageUsers ? (
                          <AdminRowActionsMenu
                            actions={[
                              {
                                key: "permissions",
                                label: t("actions.permissions"),
                                icon: KeyRound,
                                onClick: () => openPermissionEditor(row),
                              },
                              {
                                key: "edit",
                                label: t("actions.edit"),
                                icon: Pencil,
                                onClick: () => openEditAccount(row),
                              },
                              {
                                key: "delete",
                                label: t("actions.delete"),
                                icon: Trash2,
                                destructive: true,
                                disabled: profile?.id === row.id,
                                onClick: () => setDeleteTarget(row),
                              },
                            ]}
                          />
                        ) : (
                          <span className="text-xs text-muted-foreground">—</span>
                        )}
                      </TableCell>
                    </TableRow>
                  ))
                )}
              </TableBody>
            </Table>
          </div>
          <AdminListPaginationFooter
            selectId="admin-users-per-page"
            total={total}
            page={page}
            lastPage={lastPage}
            perPage={perPage}
            loading={loading}
            onPerPageChange={(value) => {
              setPerPage(value);
              setPage(1);
            }}
            onPageChange={setPage}
          />
        </CardContent>
      </Card>

      <Dialog open={permissionOpen} onOpenChange={handlePermissionDialogOpenChange}>
        <DialogContent
          showCloseButton
          className="flex max-h-[90vh] w-[calc(100%-2rem)] max-w-[calc(100%-2rem)] flex-col gap-0 overflow-hidden p-0 sm:max-w-2xl"
        >
          <DialogHeader className="shrink-0 space-y-1 border-b px-4 py-3 pr-12">
            <DialogTitle>{t("permissionDialog.title")}</DialogTitle>
            <DialogDescription>
              {selectedUser ? (
                <>
                  <span className="font-medium text-foreground">{selectedUser.username}</span>
                  <span className="text-muted-foreground"> · {selectedUser.nickname}</span>
                </>
              ) : null}
            </DialogDescription>
          </DialogHeader>

          <div className="min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-4">
            <div className="space-y-3">
              <p className="text-xs text-muted-foreground">{t("permissionDialog.rolesDescription")}</p>
              <div className="grid gap-3 rounded-md border p-3 sm:grid-cols-2">
                {(catalog?.roles ?? []).map((role) => {
                  const checked = draftRoles.includes(role.slug);
                  return (
                    <label key={role.slug} className="flex items-start gap-2 text-sm">
                      <Checkbox
                        checked={checked}
                        onCheckedChange={(value) => toggleRole(role.slug, value === true)}
                      />
                      <span className="space-y-0.5">
                        <span className="block leading-none font-medium">{role.name}</span>
                        <span className="text-xs text-muted-foreground">{role.description ?? ""}</span>
                      </span>
                    </label>
                  );
                })}
              </div>
            </div>
          </div>

          <div className="flex shrink-0 flex-col gap-3 border-t bg-muted/40 px-4 py-3 sm:flex-row sm:items-center sm:justify-between">
            <Button
              type="button"
              variant="outline"
              className="w-full shrink-0 sm:w-auto"
              onClick={() => handlePermissionDialogOpenChange(false)}
            >
              {t("actions.close", { ns: "common" })}
            </Button>
            <Button
              type="button"
              className="w-full shrink-0 sm:w-auto"
              disabled={!selectedUser || savingRoles}
              onClick={() =>
                selectedUser &&
                requestConfirm({
                  title: t("confirmSaveRolesTitle"),
                  description: t("confirmSaveRolesDescription", { name: selectedUser.username }),
                  confirmLabel: t("confirm.confirmSave", { ns: "common" }),
                  onConfirm: () => saveRoles(),
                })
              }
            >
              {savingRoles ? t("saving") : t("permissionDialog.saveRoles")}
            </Button>
          </div>
        </DialogContent>
      </Dialog>

      <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("accountDialog.createTitle") : t("accountDialog.editTitle")}
            </DialogTitle>
            <DialogDescription>
              {accountMode === "create"
                ? t("accountDialog.createDescription")
                : t("accountDialog.editDescription")}
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-3">
            <div className="space-y-1.5">
              <div className="text-sm font-medium leading-none">{t("accountDialog.username")}</div>
              <Input
                value={formUsername}
                disabled={accountMode === "edit"}
                placeholder={t("accountDialog.usernamePlaceholder")}
                autoComplete="off"
                onChange={(e) => setFormUsername(e.target.value)}
              />
            </div>
            <div className="space-y-1.5">
              <div className="text-sm font-medium leading-none">{t("accountDialog.nickname")}</div>
              <Input
                value={formNickname}
                placeholder={t("accountDialog.nicknamePlaceholder")}
                onChange={(e) => setFormNickname(e.target.value)}
              />
            </div>
            <div className="space-y-1.5">
              <div className="text-sm font-medium leading-none">{t("accountDialog.emailOptional")}</div>
              <Input
                type="email"
                value={formEmail}
                placeholder={t("accountDialog.emailPlaceholder")}
                onChange={(e) => setFormEmail(e.target.value)}
              />
            </div>
            <div className="space-y-1.5">
              <div className="text-sm font-medium leading-none">
                {accountMode === "edit" ? t("accountDialog.passwordOptional") : t("accountDialog.password")}
              </div>
              <Input
                type="password"
                value={formPassword}
                placeholder={
                  accountMode === "create"
                    ? t("accountDialog.passwordPlaceholderCreate")
                    : t("accountDialog.passwordPlaceholderEdit")
                }
                autoComplete="new-password"
                onChange={(e) => setFormPassword(e.target.value)}
              />
            </div>
            {accountMode === "create" ? (
              <div className="space-y-2">
                <div className="text-sm font-medium leading-none">{t("accountDialog.rolesRequired")}</div>
                <p className="text-xs text-muted-foreground">{t("accountDialog.rolesDescription")}</p>
                <div className="max-h-52 space-y-2 overflow-y-auto rounded-md border p-2.5 sm:grid sm:max-h-56 sm:grid-cols-2 sm:gap-2 sm:space-y-0">
                  {(catalog?.roles ?? []).length === 0 ? (
                    <p className="col-span-full text-xs text-muted-foreground">
                      {t("accountDialog.noRoles")}
                    </p>
                  ) : (
                    (catalog?.roles ?? []).map((role) => {
                      const checked = formCreateRoles.includes(role.slug);
                      return (
                        <label key={role.slug} className="flex items-start gap-2 text-sm">
                          <Checkbox
                            checked={checked}
                            onCheckedChange={(value) =>
                              toggleFormCreateRole(role.slug, value === true)
                            }
                          />
                          <span className="space-y-0.5">
                            <span className="block leading-none font-medium">{role.name}</span>
                            <span className="text-xs text-muted-foreground">{role.description ?? ""}</span>
                          </span>
                        </label>
                      );
                    })
                  )}
                </div>
              </div>
            ) : null}
            <div className="flex items-center justify-between rounded-xl border border-border/70 p-3">
              <div className="space-y-1">
                <p className="text-sm font-medium">{t("table.status")}</p>
                <p className="text-xs text-muted-foreground">
                  {formStatus === 0 ? t("status.enabled") : t("status.disabled")}
                </p>
              </div>
              <Switch
                checked={formStatus === 0}
                disabled={accountSaving}
                aria-label={t("table.status")}
                onCheckedChange={(checked) => setFormStatus(checked ? 0 : 1)}
              />
            </div>
          </div>
          <div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
            <Button
              type="button"
              variant="outline"
              onClick={() => handleAccountDialogOpenChange(false)}
            >
              {t("actions.cancel")}
            </Button>
            <Button
              type="button"
              disabled={accountSaving}
              onClick={() =>
                requestConfirm({
                  title: t("confirmSaveAccountTitle"),
                  description:
                    accountMode === "create"
                      ? t("confirmSaveAccountCreateDescription")
                      : t("confirmSaveAccountEditDescription", {
                          name: formUsername || "—",
                        }),
                  confirmLabel: t("confirm.confirmSave", { ns: "common" }),
                  onConfirm: () => submitAccount(),
                })
              }
            >
              {accountSaving ? t("saving") : t("actions.save")}
            </Button>
          </div>
        </DialogContent>
      </Dialog>

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