import { useMutation, useQuery } from "@tanstack/react-query";
import type { AxiosError } from "axios";
import {
  ChevronLeft,
  ChevronRight,
  FileDown,
  Pencil,
  Plus,
  RefreshCw,
  Search,
  Settings2,
  Trash2,
  User,
} from "lucide-react";
import * as React from "react";
import { Link, useNavigate } from "react-router-dom";
import { Badge } from "../../components/ui/badge";
import { Button } from "../../components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "../../components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "../../components/ui/dialog";
import { Input } from "../../components/ui/input";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "../../components/ui/table";
import { toast } from "../../components/ui/use-toast";
import {
  bulkDeleteUsers,
  bulkUpdateUsers,
  deleteUser,
  exportUsersCSVUrl,
  fetchMe,
  fetchTenant,
  fetchTenants,
  fetchUsers,
} from "../../lib/adminApi";
import { t } from "../../lib/i18n";
import { UserBulkMoveGroupModal } from "./components/UserBulkMoveGroupModal";
import { UserBulkUploadModal } from "./components/UserBulkUploadModal";

type UserSchemaField = {
  key: string;
  label: string;
  type: string;
};

function UserListPage() {
  const navigate = useNavigate();
  const [page, setPage] = React.useState(1);
  const [search, setSearch] = React.useState("");
  const [searchDraft, setSearchDraft] = React.useState("");
  const [selectedCompany, setSelectedCompany] = React.useState<string>("");
  const [visibleColumns, setVisibleColumns] = React.useState<
    Record<string, boolean>
  >({});
  const [selectedUserIds, setSelectedUserIds] = React.useState<string[]>([]);
  const limit = 50;
  const offset = (page - 1) * limit;

  const { data: profile } = useQuery({
    queryKey: ["me"],
    queryFn: fetchMe,
  });

  const { data: tenantsData } = useQuery({
    queryKey: ["tenants", { limit: 100 }],
    queryFn: () => fetchTenants(100, 0),
  });
  const tenants = tenantsData?.items ?? [];

  // Lock company for tenant_admin
  React.useEffect(() => {
    if (profile?.role === "tenant_admin" && profile.tenantSlug) {
      setSelectedCompany(profile.tenantSlug);
    }
  }, [profile]);

  const selectedTenantId = React.useMemo(() => {
    return tenants.find((t) => t.slug === selectedCompany)?.id ?? "";
  }, [tenants, selectedCompany]);

  const { data: tenantDetail } = useQuery({
    queryKey: ["tenant", selectedTenantId],
    queryFn: () => fetchTenant(selectedTenantId),
    enabled: selectedTenantId.length > 0,
  });

  const userSchema: UserSchemaField[] = Array.isArray(
    tenantDetail?.config?.userSchema,
  )
    ? (tenantDetail?.config?.userSchema as UserSchemaField[])
    : [];

  // Initialize visible columns when schema changes
  React.useEffect(() => {
    if (userSchema.length > 0) {
      const initial: Record<string, boolean> = {};
      for (const field of userSchema) {
        initial[field.key] = true;
      }
      setVisibleColumns((prev) => {
        // Only set if not already set for these keys to avoid reset on every render
        const next = { ...initial, ...prev };
        return next;
      });
    }
  }, [userSchema]);

  const toggleColumn = (key: string) => {
    setVisibleColumns((prev) => ({
      ...prev,
      [key]: !prev[key],
    }));
  };

  const query = useQuery({
    queryKey: ["users", { limit, offset, search, tenantSlug: selectedCompany }],
    queryFn: () => fetchUsers(limit, offset, search, selectedCompany),
    placeholderData: (previousData) => previousData,
  });

  const deleteMutation = useMutation({
    mutationFn: (userId: string) => deleteUser(userId),
    onSuccess: () => {
      query.refetch();
    },
  });

  const handleSearch = () => {
    setSearch(searchDraft);
    setPage(1);
  };

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === "Enter") {
      handleSearch();
    }
  };

  const handleExport = () => {
    const url = exportUsersCSVUrl(search, selectedCompany);
    window.open(url, "_blank");
  };

  const errorMsg = (query.error as AxiosError<{ error?: string }>)?.response
    ?.data?.error;
  const fallbackError =
    !errorMsg && query.isError
      ? t(
          "msg.admin.users.list.fetch_error",
          "사용자 목록 조회에 실패했습니다.",
        )
      : null;

  const items = query.data?.items ?? [];
  const total = query.data?.total ?? 0;
  const totalPages = Math.ceil(total / limit);

  const toggleSelectAll = () => {
    if (selectedUserIds.length === items.length) {
      setSelectedUserIds([]);
    } else {
      setSelectedUserIds(items.map((u) => u.id));
    }
  };

  const toggleSelectUser = (id: string) => {
    setSelectedUserIds((prev) =>
      prev.includes(id) ? prev.filter((i) => i !== id) : [...prev, id],
    );
  };

  const bulkDeleteMutation = useMutation({
    mutationFn: bulkDeleteUsers,
    onSuccess: () => {
      query.refetch();
      setSelectedUserIds([]);
      toast.success(
        t(
          "msg.admin.users.bulk.delete_success",
          "선택한 사용자들이 삭제되었습니다.",
        ),
      );
    },
  });

  const bulkUpdateMutation = useMutation({
    mutationFn: bulkUpdateUsers,
    onSuccess: () => {
      query.refetch();
      setSelectedUserIds([]);
      toast.success(
        t(
          "msg.admin.users.bulk.update_success",
          "선택한 사용자들의 정보가 수정되었습니다.",
        ),
      );
    },
  });

  const handleBulkStatusChange = (status: string) => {
    if (selectedUserIds.length === 0) return;
    bulkUpdateMutation.mutate({ userIds: selectedUserIds, status });
  };

  const handleBulkDelete = () => {
    if (selectedUserIds.length === 0) return;
    if (
      window.confirm(
        t(
          "msg.admin.users.bulk.delete_confirm",
          "{{count}}명의 사용자를 정말 삭제하시겠습니까?",
          { count: selectedUserIds.length },
        ),
      )
    ) {
      bulkDeleteMutation.mutate(selectedUserIds);
    }
  };

  const handleDelete = (userId: string, userName: string) => {
    if (
      !window.confirm(
        t(
          "msg.admin.users.list.delete_confirm",
          '사용자 "{{name}}"을(를) 정말 삭제하시겠습니까?',
          { name: userName },
        ),
      )
    ) {
      return;
    }
    deleteMutation.mutate(userId);
  };

  return (
    <div className="space-y-6 flex flex-col h-[calc(100vh-theme(spacing.32))]">
      <header className="flex flex-wrap items-start justify-between gap-4 flex-shrink-0 sticky top-[-2.5rem] z-20 bg-background/95 backdrop-blur pt-4 pb-2 -mt-4">
        <div className="space-y-2">
          <h2 className="text-3xl font-semibold" data-testid="page-title">
            {t("ui.admin.users.list.title", "사용자 관리")}
          </h2>
          <p className="text-sm text-[var(--color-muted)]">
            {t(
              "msg.admin.users.list.subtitle",
              "시스템 사용자를 조회하고 관리합니다.",
            )}
          </p>
        </div>
        <div className="flex items-center gap-2">
          <Button
            variant="outline"
            onClick={() => query.refetch()}
            disabled={query.isFetching}
          >
            <RefreshCw size={16} />
            {t("ui.common.refresh", "새로고침")}
          </Button>
          <Button variant="outline" onClick={handleExport} className="gap-2">
            <FileDown size={16} />
            {t("ui.common.export", "내보내기")}
          </Button>
          <UserBulkUploadModal onSuccess={() => query.refetch()} />
          <Dialog>
            <DialogTrigger asChild>
              <Button variant="outline" size="icon">
                <Settings2 size={16} />
              </Button>
            </DialogTrigger>
            <DialogContent>
              <DialogHeader>
                <DialogTitle>
                  {t("ui.admin.users.list.columns.title", "표시 컬럼 설정")}
                </DialogTitle>
                <DialogDescription>
                  {t(
                    "msg.admin.users.list.columns.description",
                    "사용자 목록에 표시할 커스텀 필드를 선택하세요.",
                  )}
                </DialogDescription>
              </DialogHeader>
              <div className="grid gap-4 py-4">
                {userSchema.length === 0 && (
                  <p className="text-sm text-muted-foreground text-center py-4">
                    {t(
                      "msg.admin.users.list.columns.no_custom",
                      "현재 테넌트에 정의된 커스텀 필드가 없습니다.",
                    )}
                  </p>
                )}
                {userSchema.map((field) => (
                  <label
                    key={field.key}
                    className="flex items-center gap-3 p-2 rounded-lg hover:bg-muted/50 cursor-pointer"
                  >
                    <input
                      type="checkbox"
                      className="w-4 h-4 rounded border-gray-300 text-primary focus:ring-primary"
                      checked={visibleColumns[field.key] !== false}
                      onChange={() => toggleColumn(field.key)}
                    />
                    <div className="flex flex-col">
                      <span className="text-sm font-medium">{field.label}</span>
                      <span className="text-xs text-muted-foreground font-mono">
                        {field.key}
                      </span>
                    </div>
                  </label>
                ))}
              </div>
              <DialogFooter>
                <DialogTrigger asChild>
                  <Button variant="secondary">
                    {t("ui.common.close", "닫기")}
                  </Button>
                </DialogTrigger>
              </DialogFooter>
            </DialogContent>
          </Dialog>
          <Button asChild>
            <Link to="/users/new">
              <Plus size={16} />
              {t("ui.admin.users.list.add", "사용자 추가")}
            </Link>
          </Button>
        </div>
      </header>

      <Card className="flex-1 flex flex-col min-h-0 bg-[var(--color-panel)] overflow-hidden">
        <CardHeader className="flex flex-row items-center justify-between flex-shrink-0">
          <div>
            <CardTitle>
              {t("ui.admin.users.list.registry.title", "User Registry")}
            </CardTitle>
            <CardDescription>
              {t(
                "msg.admin.users.list.registry.count",
                "총 {{count}}명의 사용자가 등록되어 있습니다.",
                { count: total },
              )}
            </CardDescription>
          </div>
        </CardHeader>
        <CardContent className="flex-1 flex flex-col min-h-0 pt-0">
          <div className="mb-6 flex flex-wrap items-center gap-4 flex-shrink-0">
            <div className="relative flex-1 min-w-[240px] max-w-sm">
              <Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
              <Input
                placeholder={t(
                  "ui.admin.users.list.search_placeholder",
                  "이름 또는 이메일 검색...",
                )}
                className="pl-9"
                value={searchDraft}
                onChange={(e) => setSearchDraft(e.target.value)}
                onKeyDown={handleKeyDown}
              />
            </div>

            <div className="flex items-center gap-2">
              <span className="text-sm font-medium text-muted-foreground whitespace-nowrap">
                {t("ui.admin.users.list.filter.tenant", "테넌트 필터:")}
              </span>
              <select
                className="flex h-9 w-[200px] rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:opacity-50"
                value={selectedCompany}
                onChange={(e) => {
                  setSelectedCompany(e.target.value);
                  setPage(1);
                }}
                disabled={profile?.role === "tenant_admin"}
              >
                <option value="">{t("ui.common.all", "전체")}</option>
                {tenants.map((t) => (
                  <option key={t.id} value={t.slug}>
                    {t.name}
                  </option>
                ))}
              </select>
            </div>

            <Button variant="secondary" onClick={handleSearch}>
              {t("ui.common.search", "검색")}
            </Button>
          </div>

          {(errorMsg || fallbackError) && (
            <div className="mb-4 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive flex-shrink-0">
              {errorMsg ?? fallbackError}
            </div>
          )}

          <div className="flex-1 rounded-md border overflow-hidden flex flex-col">
            <div className="flex-1 overflow-auto relative custom-scrollbar">
              <Table>
                <TableHeader className="sticky top-0 z-10 bg-secondary shadow-sm">
                  <TableRow>
                    <TableHead className="w-12">
                      <input
                        type="checkbox"
                        className="w-4 h-4 rounded border-gray-300 text-primary focus:ring-primary cursor-pointer"
                        checked={
                          items.length > 0 &&
                          selectedUserIds.length === items.length
                        }
                        onChange={toggleSelectAll}
                      />
                    </TableHead>
                    <TableHead className="min-w-[200px]">
                      {t(
                        "ui.admin.users.list.table.name_email",
                        "NAME / EMAIL",
                      )}
                    </TableHead>
                    <TableHead>
                      {t("ui.admin.users.list.table.login_id", "LOGIN ID")}
                    </TableHead>
                    <TableHead>
                      {t("ui.admin.users.list.table.role", "ROLE")}
                    </TableHead>
                    <TableHead>
                      {t("ui.admin.users.list.table.status", "STATUS")}
                    </TableHead>
                    <TableHead>
                      {t(
                        "ui.admin.users.list.table.tenant_dept",
                        "TENANT / DEPT",
                      )}
                    </TableHead>
                    {/* Dynamic Columns from Schema */}
                    {userSchema.map(
                      (field) =>
                        visibleColumns[field.key] !== false && (
                          <TableHead key={field.key} className="uppercase">
                            {field.label}
                          </TableHead>
                        ),
                    )}
                    <TableHead>
                      {t("ui.admin.users.list.table.created", "CREATED")}
                    </TableHead>
                    <TableHead className="text-right">
                      {t("ui.admin.users.list.table.actions", "ACTIONS")}
                    </TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {query.isLoading && (
                    <TableRow>
                      <TableCell
                        colSpan={7 + userSchema.length}
                        className="h-24 text-center"
                      >
                        {t("msg.common.loading", "로딩 중...")}
                      </TableCell>
                    </TableRow>
                  )}
                  {!query.isLoading && items.length === 0 && (
                    <TableRow>
                      <TableCell
                        colSpan={7 + userSchema.length}
                        className="h-24 text-center"
                      >
                        {t(
                          "msg.admin.users.list.empty",
                          "검색 결과가 없습니다.",
                        )}
                      </TableCell>
                    </TableRow>
                  )}
                  {items.map((user) => (
                    <TableRow
                      key={user.id}
                      className={
                        selectedUserIds.includes(user.id) ? "bg-primary/5" : ""
                      }
                    >
                      <TableCell>
                        <input
                          type="checkbox"
                          className="w-4 h-4 rounded border-gray-300 text-primary focus:ring-primary cursor-pointer"
                          checked={selectedUserIds.includes(user.id)}
                          onChange={() => toggleSelectUser(user.id)}
                        />
                      </TableCell>
                      <TableCell>
                        <div className="flex items-center gap-3">
                          <div className="flex h-9 w-9 items-center justify-center rounded-full bg-secondary text-secondary-foreground">
                            <User size={16} />
                          </div>
                          <div className="flex flex-col">
                            <span className="font-medium">{user.name}</span>
                            <span className="text-xs text-muted-foreground">
                              {user.email}
                            </span>
                          </div>
                        </div>
                      </TableCell>
                      <TableCell>
                        <span className="text-sm font-mono">
                          {user.loginId || "-"}
                        </span>
                      </TableCell>
                      <TableCell>
                        <Badge variant="outline">
                          {t(`ui.admin.role.${user.role}`, user.role)}
                        </Badge>
                      </TableCell>
                      <TableCell>
                        <Badge
                          variant={
                            user.status === "active" ? "default" : "secondary"
                          }
                        >
                          {t(`ui.common.status.${user.status}`, user.status)}
                        </Badge>
                      </TableCell>
                      <TableCell>
                        <div className="flex flex-col text-sm">
                          <span className="font-medium text-blue-600">
                            {user.tenant?.name || user.tenantSlug || "-"}
                          </span>
                          <span className="text-xs text-muted-foreground">
                            {user.department || "-"}
                          </span>
                        </div>
                      </TableCell>
                      {/* Dynamic Metadata Cells */}
                      {userSchema.map(
                        (field) =>
                          visibleColumns[field.key] !== false && (
                            <TableCell key={field.key} className="text-sm">
                              {String(user.metadata?.[field.key] ?? "-")}
                            </TableCell>
                          ),
                      )}
                      <TableCell className="text-sm text-muted-foreground">
                        {new Date(user.createdAt).toLocaleDateString()}
                      </TableCell>
                      <TableCell className="text-right">
                        <div className="flex justify-end gap-2">
                          <Button
                            variant="ghost"
                            size="icon"
                            onClick={() => navigate(`/users/${user.id}`)}
                          >
                            <Pencil size={16} />
                          </Button>
                          <Button
                            variant="ghost"
                            size="icon"
                            className="text-destructive hover:text-destructive"
                            onClick={() => handleDelete(user.id, user.name)}
                            disabled={deleteMutation.isPending}
                          >
                            <Trash2 size={16} />
                          </Button>
                        </div>
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </div>
          </div>

          {/* Bulk Action Bar */}
          {selectedUserIds.length > 0 && (
            <div
              className="fixed bottom-8 left-1/2 -translate-x-1/2 z-50 flex items-center gap-4 px-6 py-3 rounded-2xl bg-foreground text-background shadow-2xl animate-in slide-in-from-bottom-4 duration-300"
              data-testid="bulk-action-bar"
            >
              <span className="text-sm font-medium border-r border-background/20 pr-4 mr-2">
                {t("ui.admin.users.bulk.selected_count", "{{count}}명 선택됨", {
                  count: selectedUserIds.length,
                })}
              </span>
              <div className="flex items-center gap-2">
                <Button
                  variant="ghost"
                  size="sm"
                  className="text-background hover:bg-background/10 h-8"
                  onClick={() => handleBulkStatusChange("active")}
                  data-testid="bulk-active-btn"
                >
                  {t("ui.common.status.active", "활성화")}
                </Button>
                <Button
                  variant="ghost"
                  size="sm"
                  className="text-background hover:bg-background/10 h-8"
                  onClick={() => handleBulkStatusChange("inactive")}
                  data-testid="bulk-inactive-btn"
                >
                  {t("ui.common.status.inactive", "비활성화")}
                </Button>
                <UserBulkMoveGroupModal
                  userIds={selectedUserIds}
                  selectedUsers={items.filter((u) =>
                    selectedUserIds.includes(u.id),
                  )}
                  onSuccess={() => {
                    query.refetch();
                    setSelectedUserIds([]);
                  }}
                />
                <div className="w-px h-4 bg-background/20 mx-1" />
                <Button
                  variant="ghost"
                  size="sm"
                  className="text-destructive-foreground hover:bg-destructive/20 h-8 gap-1.5"
                  onClick={handleBulkDelete}
                  data-testid="bulk-delete-btn"
                >
                  <Trash2 size={14} />
                  {t("ui.common.delete", "삭제")}
                </Button>
              </div>
              <Button
                variant="ghost"
                size="icon"
                className="text-background/50 hover:text-background h-8 w-8 ml-2"
                onClick={() => setSelectedUserIds([])}
                aria-label={t("ui.common.close", "닫기")}
                data-testid="bulk-close-btn"
              >
                <Plus size={16} className="rotate-45" />
              </Button>
            </div>
          )}

          {/* Pagination */}
          {totalPages > 1 && (
            <div className="mt-4 flex flex-shrink-0 items-center justify-end gap-2">
              <Button
                variant="outline"
                size="sm"
                onClick={() => setPage((p) => Math.max(1, p - 1))}
                disabled={page === 1 || query.isFetching}
              >
                <ChevronLeft size={16} />
                {t("ui.common.previous", "Previous")}
              </Button>
              <div className="text-sm text-muted-foreground">
                {t("ui.common.page_of", "Page {{page}} of {{total}}", {
                  page,
                  total: totalPages,
                })}
              </div>
              <Button
                variant="outline"
                size="sm"
                onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
                disabled={page === totalPages || query.isFetching}
              >
                {t("ui.common.next", "Next")}
                <ChevronRight size={16} />
              </Button>
            </div>
          )}
        </CardContent>
      </Card>
    </div>
  );
}

export default UserListPage;
