"use client";

import * as React from "react";
import { useSearchParams } from "next/navigation";
import { useUrlPagination } from "@/hooks/use-url-pagination";
import Link from "next/link";
import Image from "next/image";
import { useRouter } from "next/navigation";
import {
  useGetUsersQuery,
  useGetRolesQuery,
  useGetProfileQuery,
  useCreateUserMutation,
  useUpdateUserMutation,
  useDeleteUserMutation,
  useUpdateUserStatusMutation,
  useRestoreUserMutation,
} from "@/api/rtk";
import type { ApiUser } from "@/api/users/types";
import { getApiEntityId, type Role as ApiRole } from "@/api/permissions/types";
import { Can, useAbility } from "@/components/providers/ability-provider";
import { useAppSelector } from "@/store/hooks";
import { useAuthToken } from "@/hooks/use-auth-token";
import {
  Search,
  Plus,
  Pencil,
  Trash2,
  Users,
  UserCheck,
  ShieldCheck,
  ArrowUp,
  ArrowDown,
  Camera,
  TriangleAlert,
  ChevronLeft,
  ChevronRight,
  Eye,
  EyeOff,
  Activity,
  RotateCcw,
  KeyRound,
  Shield,
  Lock,
} from "lucide-react";
import { useForm, Controller } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
// import * as XLSX from "xlsx"; // Lazy loaded for tree shaking / bundle size
import { Loading } from "@/components/ui/loading";
import { NoDataFound } from "@/components/ui/no-data-found";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import {
  AlertDialog,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogMedia,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import {
  ReactSelect,
} from "@/components/ui/react-select";
import {
  Combobox,
  ComboboxContent,
  ComboboxEmpty,
  ComboboxInput,
  ComboboxItem,
  ComboboxList,
} from "@/components/ui/combobox";
import { toast } from "sonner";
import { cn } from "@/lib/utils";
import { KPICard } from "@/components/ui/kpi-card";
import { Switch } from "@/components/ui/switch";
import { Checkbox } from "@/components/ui/checkbox";
import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
  PopoverHeader,
  PopoverTitle,
} from "@/components/ui/popover";
import { apiBaseUrl } from "@/api/client";
import type { Permission } from "@/api/permissions/types";
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip";

const getFullImageUrl = (url: string | undefined) => {
  if (!url) return undefined;
  if (url.startsWith("http")) return url;
  return `${apiBaseUrl}${url.startsWith("/") ? "" : "/"}${url}`;
};

function getRoleName(role: ApiUser["role"]): string {
  if (!role) return "—";
  return typeof role === "string" ? role : role.name;
}

function SortIcon({
  col,
  sortCol,
  sortDir,
}: {
  col: "name" | "email" | "role";
  sortCol: "name" | "email" | "role";
  sortDir: 1 | -1;
}) {
  if (sortCol !== col) return null;
  return sortDir === 1 ? (
    <ArrowUp size={12} className="ml-1 inline" />
  ) : (
    <ArrowDown size={12} className="ml-1 inline" />
  );
}

function getRoleId(role: ApiUser["role"]): string | undefined {
  if (!role) return undefined;
  return typeof role === "string" ? role : role.id;
}

function getRoleWithPermissions(
  user: ApiUser,
): { name: string; description?: string; permissions: Permission[] } | null {
  const role = user.role;
  if (!role) return null;
  const name = typeof role === "string" ? role : role.name;
  const description = typeof role === "string" ? undefined : role.description;
  const raw = typeof role === "string" ? [] : (role.permissions ?? []);
  const permissions: Permission[] = Array.isArray(raw)
    ? raw.filter(
        (p): p is Permission =>
          typeof p === "object" &&
          p != null &&
          "action" in p &&
          "resource" in p,
      )
    : [];
  return { name, description, permissions };
}

function formatPermission(p: Permission): string {
  return `${p.action} • ${p.resource}`;
}

function UserRolePermissionPopover({
  user,
  children,
  getFullImageUrl,
}: {
  user: ApiUser;
  children: React.ReactNode;
  getFullImageUrl: (url: string | undefined) => string | undefined;
}) {
  const roleInfo = getRoleWithPermissions(user);
  const hasRole = !!roleInfo;
  const hasPermissions = hasRole && roleInfo.permissions.length > 0;

  return (
    <Popover>
      <PopoverTrigger asChild>
        <button
          type="button"
          className="flex items-center gap-3 w-full text-left min-w-0 rounded-lg py-1 -my-1 px-1 -mx-1 hover:bg-muted/50 transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
          onClick={(e) => e.stopPropagation()}
        >
          {children}
        </button>
      </PopoverTrigger>
      <PopoverContent
        align="start"
        side="right"
        sideOffset={8}
        className="flex max-h-[min(90vh,560px)] w-[320px] flex-col overflow-hidden rounded-xl border border-border/80 bg-card p-0 shadow-lg"
        onClick={(e) => e.stopPropagation()}
      >
        <div className="bg-gradient-to-br from-accent/10 via-background to-background border-b border-border/60 px-4 pt-4 pb-3">
          <PopoverHeader>
            <PopoverTitle className="flex items-center gap-2 text-base font-semibold text-foreground">
              <div className="relative size-8 rounded-full flex items-center justify-center text-xs font-bold text-white bg-accent shrink-0 overflow-hidden">
                {user.avatar?.url ? (
                  <Image
                    src={getFullImageUrl(user.avatar.url)}
                    alt={user.name}
                    fill
                    sizes="32px"
                    className="object-cover"
                  />
                ) : (
                  user.name
                    .split(/\s+/)
                    .map((s) => s[0])
                    .join("")
                    .slice(0, 2)
                    .toUpperCase()
                )}
              </div>
              <div className="min-w-0">
                <p className="truncate">{user.name}</p>
                <p className="text-xs font-normal text-muted-foreground truncate">
                  {user.email}
                </p>
              </div>
            </PopoverTitle>
          </PopoverHeader>
        </div>
        <div className="flex min-h-0 flex-1 flex-col gap-3 overflow-hidden px-4 py-3">
          {hasRole ? (
            <>
              <div className="shrink-0 space-y-1.5">
                <p className="text-[11px] font-semibold uppercase tracking-wider text-muted-foreground flex items-center gap-1.5">
                  <Shield className="size-3.5" />
                  Role
                </p>
                <div className="rounded-lg bg-muted/60 px-3 py-2 border border-border/40">
                  <p className="text-sm font-semibold text-foreground">
                    {roleInfo.name}
                  </p>
                  {roleInfo.description && (
                    <p className="text-xs text-muted-foreground mt-0.5">
                      {roleInfo.description}
                    </p>
                  )}
                </div>
              </div>
              <div className="flex min-h-0 flex-1 flex-col gap-1.5 overflow-hidden">
                <p className="shrink-0 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground flex items-center gap-1.5">
                  <Lock className="size-3.5" />
                  Permissions
                </p>
                {hasPermissions ? (
                  <div className="min-h-0 flex-1 overflow-y-auto overscroll-contain rounded-lg border border-border/40 bg-muted/20 px-2 py-2 scrollbar-themed">
                    <div className="flex flex-wrap gap-1.5">
                      {roleInfo.permissions.map((p) => (
                        <span
                          key={`${p.action}-${p.resource}`}
                          className="inline-flex items-center gap-1 rounded-md bg-primary/10 text-primary px-2 py-1 text-[11px] font-medium border border-primary/20"
                        >
                          <KeyRound className="size-3 shrink-0" />
                          {formatPermission(p)}
                        </span>
                      ))}
                    </div>
                  </div>
                ) : (
                  <p className="text-xs text-muted-foreground italic">
                    No permissions assigned
                  </p>
                )}
              </div>
            </>
          ) : (
            <p className="text-sm text-muted-foreground italic flex items-center gap-2">
              <Shield className="size-4 shrink-0" />
              No role assigned
            </p>
          )}
        </div>
      </PopoverContent>
    </Popover>
  );
}

function getUserStatus(user: ApiUser): "Active" | "Inactive" {
  return (user.accountStatus?.status as "Active" | "Inactive") || "Active";
}

type UserDialogMode = "create" | "edit" | null;

const userFormSchema = yup.object({
  name: yup
    .string()
    .min(2, "Name must be at least 2 characters")
    .required("Name is required"),
  email: yup
    .string()
    .email("Invalid email address")
    .required("Email is required"),
  password: yup
    .string()
    .transform((v) => (v === "" ? undefined : v))
    .min(6, "Password must be at least 6 characters")
    .notRequired(),
  role: yup.string().notRequired(),
  file: yup.mixed().notRequired(),
});

type UserFormData = yup.InferType<typeof userFormSchema>;

const DEFAULT_PAGE_SIZE = 10;
const SEARCH_DEBOUNCE_MS = 400;

/** Pill select surface: soft blue-grey field, layered edge, Lexend — aligned with design reference. */
const usersRoleComboboxInputClassName = cn(
  "h-9 min-h-9 min-w-0 text-[13px] font-medium text-[#101828] font-['Lexend']",
  "rounded-[14px] border border-[#b9c7d0] bg-[#d1dbe1]",
  "shadow-[0px_2px_12px_rgba(15,23,42,0.07),inset_0_1px_0_rgba(255,255,255,0.55),0_0_0_2px_rgba(255,255,255,0.55)]",
  "pl-3.5 pr-0 transition-[box-shadow,border-color]",
  "focus-within:border-[#9eb0bc] focus-within:shadow-[0px_2px_16px_rgba(15,23,42,0.1),inset_0_1px_0_rgba(255,255,255,0.65),0_0_0_2px_rgba(255,255,255,0.75)]",
  "[&_[data-slot=input-group-addon]_svg]:text-[#575a62] [&_[data-slot=combobox-trigger-icon]]:text-[#575a62]",
  "[&_input::placeholder]:text-[#575a62]",
);

/** Same panel treatment as the role select dropdown. */
const usersRoleComboboxContentClassName =
  "rounded-[14px] border border-white/80 bg-white/95 backdrop-blur-[15px] text-[#0a0a0a] shadow-[0px_2px_15px_0px_rgba(0,0,0,0.1)]";

export default function UsersPage() {
  const router = useRouter();
  const { token: accessToken } = useAuthToken();
  const ability = useAbility();
  const canCreateUser = ability.can("create", "user");
  const canManageUser = ability.can("manage", "user");
  const canUpdateUser = ability.can("update", "user");
  /** Status, edit, delete, restore — same access as New User (create/manage) plus normal USER update grants. */
  const canMutateUserRows = canManageUser || canCreateUser || canUpdateUser;

  const handleViewLogs = (user: ApiUser) => {
    // Navigate to activity logs page with user filter
    const userName = user.name || user.email;
    toast.success(`Opening activity logs for ${userName}...`);
    router.push(
      `/activity-logs?userId=${user.id}&userName=${encodeURIComponent(userName)}`,
    );
  };
  const searchParams = useSearchParams();
  const { page, setPage, limit, setLimit } = useUrlPagination(DEFAULT_PAGE_SIZE);
  
  const [search, setSearch] = React.useState(searchParams.get("search") || "");
  const [roleId, setRoleId] = React.useState(searchParams.get("role") || "");
  const [sortBy, setSortBy] = React.useState(searchParams.get("sortBy") || "name");
  const [sortOrder, setSortOrder] = React.useState(searchParams.get("sortOrder") || "asc");
  const [includeDeleted, setIncludeDeleted] = React.useState(searchParams.get("includeDeleted") === "true");

  const [searchInput, setSearchInput] = React.useState(search);
  const searchDebounceRef = React.useRef<ReturnType<typeof setTimeout> | null>(
    null,
  );

  React.useEffect(() => {
    setSearchInput(search);
  }, [search]);

  const applySearchToUrl = React.useCallback(
    (value: string) => {
      setSearch(value);
      setPage(1);
    },
    [setSearch, setPage],
  );

  const handleSearchChange = React.useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const value = e.target.value;
      setSearchInput(value);
      if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);
      searchDebounceRef.current = setTimeout(() => {
        searchDebounceRef.current = null;
        applySearchToUrl(value);
      }, SEARCH_DEBOUNCE_MS);
    },
    [applySearchToUrl],
  );

  React.useEffect(
    () => () => {
      if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);
    },
    [],
  );

  const {
    data: usersResponse,
    isLoading: usersLoading,
    isFetching: usersFetching,
  } = useGetUsersQuery(
    {
      page,
      limit,
      search: search || undefined,
      roleId: roleId || undefined,
      sortBy: (sortBy === "email" || sortBy === "role" ? sortBy : "name") as
        | "name"
        | "email"
        | "role",
      sortOrder: sortOrder === "desc" ? "desc" : "asc",
      includeDeleted: canManageUser && includeDeleted ? true : undefined,
    },
    { skip: !accessToken },
  );
  const users = usersResponse?.data ?? [];
  const total = usersResponse?.total ?? 0;
  const totalPages = usersResponse?.totalPages ?? 1;

  const { data: roles = [], isLoading: rolesLoading } = useGetRolesQuery(
    undefined,
    {
      skip: !accessToken,
    },
  );
  const { data: profile } = useGetProfileQuery(undefined, {
    skip: !accessToken,
  });
  const currentUserId = (profile as { id?: string })?.id;
  const [createUser, { isLoading: creating }] = useCreateUserMutation();
  const [updateUser, { isLoading: updating }] = useUpdateUserMutation();
  const [deleteUser, { isLoading: deleting }] = useDeleteUserMutation();
  const [updateUserStatus] = useUpdateUserStatusMutation();
  const [restoreUser, { isLoading: restoring }] = useRestoreUserMutation();
  const handleRestoreUser = React.useCallback(
    async (u: ApiUser) => {
      try {
        await restoreUser(u.id).unwrap();
        toast.success(`Restored ${u.name || u.email}`);
      } catch (e: unknown) {
        let message = "Failed to restore user";
        if (e && typeof e === "object" && "data" in e) {
          const d = (e as { data?: { message?: string } }).data;
          if (typeof d?.message === "string") message = d.message;
        }
        toast.error(message);
      }
    },
    [restoreUser],
  );

  const sortCol = sortBy === "email" || sortBy === "role" ? sortBy : "name";
  const sortDir = sortOrder === "desc" ? -1 : 1;

  const roleFilterItems = React.useMemo(
    () => ["all", ...roles.map((r) => getApiEntityId(r) ?? "").filter(Boolean)],
    [roles],
  );

  const pageLimitOptions = React.useMemo(
    () => [
      { value: "10", label: "10 per page" },
      { value: "20", label: "20 per page" },
      { value: "50", label: "50 per page" },
    ],
    [],
  );

  const roleSelectOptions = React.useMemo(
    () => [
      { value: "none", label: "No role" },
      ...roles.flatMap((r: ApiRole) => {
        const id = getApiEntityId(r) ?? "";
        if (!id) return [];
        return [{ value: id, label: r.name }];
      }),
    ],
    [roles],
  );

  const [userDialogOpen, setUserDialogOpen] = React.useState(false);
  const [userDialogMode, setUserDialogMode] =
    React.useState<UserDialogMode>(null);
  const [deleteDialogOpen, setDeleteDialogOpen] = React.useState(false);
  const [userToDelete, setUserToDelete] = React.useState<ApiUser | null>(null);
  const [editingUser, setEditingUser] = React.useState<ApiUser | null>(null);
  const [showPassword, setShowPassword] = React.useState(false);

  const {
    control,
    handleSubmit,
    reset,
    setValue,
    watch,
    formState: { errors },
  } = useForm<UserFormData>({
    resolver: yupResolver(userFormSchema),
    defaultValues: {
      name: "",
      email: "",
      password: "",
      role: "",
    },
  });

  const selectedFile = watch("file");
  const [filePreview, setFilePreview] = React.useState<string | null>(null);

  React.useEffect(() => {
    if (selectedFile instanceof FileList && selectedFile.length > 0) {
      const file = selectedFile[0];
      const reader = new FileReader();
      reader.onloadend = () => setFilePreview(reader.result as string);
      reader.readAsDataURL(file);
    } else if (selectedFile instanceof File) {
      const reader = new FileReader();
      reader.onloadend = () => setFilePreview(reader.result as string);
      reader.readAsDataURL(selectedFile);
    } else {
      setFilePreview(null);
    }
  }, [selectedFile]);

  const waitingForToken = !accessToken;
  const isLoading = usersLoading || rolesLoading;

  const openCreateDialog = () => {
    setShowPassword(false);
    reset({
      name: "",
      email: "",
      password: "",
      role: roles[0]?.id ?? "",
      file: undefined,
    });
    setEditingUser(null);
    setUserDialogMode("create");
    setUserDialogOpen(true);
  };

  const openEditDialog = (user: ApiUser) => {
    setShowPassword(false);
    reset({
      name: user.name,
      email: user.email,
      password: "",
      role: getRoleId(user.role) ?? "",
      file: undefined,
    });
    setUserDialogMode("edit");
    setUserDialogOpen(true);
    setEditingUser(user);
  };

  const handleUserDialogSubmit = handleSubmit(async (data) => {
    if (userDialogMode === "create") {
      if (!data.password || data.password.length < 6) {
        toast.error("Password is required (min 6 characters)");
        return;
      }
    }

    const formData = new FormData();
    formData.append("name", data.name.trim());
    formData.append("email", data.email.trim().toLowerCase());
    if (data.password) formData.append("password", data.password);
    const normalizedRole = (() => {
      const v = (data.role ?? "").trim();
      return v && v !== "none" ? v : "";
    })();
    if (userDialogMode === "edit") {
      formData.append("role", normalizedRole);
    } else if (normalizedRole) {
      formData.append("role", normalizedRole);
    }

    if (data.file) {
      const fileObj = data.file instanceof FileList ? data.file[0] : data.file;
      if (fileObj) formData.append("file", fileObj);
    }

    try {
      if (userDialogMode === "create") {
        await createUser(formData).unwrap();
        toast.success("User created");
      } else if (userDialogMode === "edit" && editingUser) {
        await updateUser({ id: editingUser.id, body: formData }).unwrap();
        toast.success("User updated");
      }
      setUserDialogOpen(false);
      setEditingUser(null);
      reset();
    } catch (e: unknown) {
      let message: string = "Failed to save user";
      if (e && typeof e === "object" && "data" in e) {
        const data = (e as { data?: { message?: string } }).data;
        if (typeof data?.message === "string") message = data.message;
      }
      toast.error(message);
    }
  });

  const confirmDelete = (user: ApiUser) => {
    setUserToDelete(user);
    setDeleteDialogOpen(true);
  };

  const cancelDelete = () => {
    if (deleting) return;
    setDeleteDialogOpen(false);
    setUserToDelete(null);
  };

  const handleDeleteConfirm = async () => {
    if (!userToDelete?.id) return;
    try {
      await deleteUser(userToDelete.id).unwrap();
      setDeleteDialogOpen(false);
      setUserToDelete(null);
      toast.success("User deleted");
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "Failed to delete user");
      throw e;
    }
  };

  const handleSort = (col: "name" | "email" | "role") => {
    if (sortCol === col) {
      setSortOrder(sortOrder === "asc" ? "desc" : "asc");
    } else {
      setSortBy(col);
      setSortOrder("asc");
    }
    setPage(1);
  };

  return (
    <div className="flex flex-col h-full gap-4 p-4 sm:p-6 md:p-6 lg:p-8 max-[1500px]:p-5 animate-in fade-in duration-500 overflow-y-auto scrollbar-themed">
      <div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-6 border-b border-border/60 pb-5 shrink-0">
        <div className="flex flex-col gap-1">
          <h1 className="text-2xl sm:text-3xl font-extrabold text-[#101828] font-['Lexend'] tracking-tight">
            User Management
          </h1>
          <p className="text-sm text-[#475467] font-normal">
            Manage platform access, roles, and security permissions.
          </p>
        </div>

        <div className="flex flex-wrap items-center gap-3 w-full md:w-auto mt-2 md:mt-0">
          <div className="relative flex-1 min-w-[240px] md:flex-none md:w-[280px]">
            <Search
              size={16}
              className="absolute left-3.5 top-1/2 -translate-y-1/2 text-[#667085] stroke-[2px]"
            />
            <Input
              type="search"
              placeholder="Search by name or email..."
              className="pl-10 pr-4 h-10 max-[1500px]:h-8 rounded-xl max-[1500px]:rounded-lg border-[#d0d5dd] text-[14px] max-[1500px]:text-[11px] bg-white shadow-sm focus:ring-accent/20 transition-all font-medium"
              value={searchInput}
              onChange={handleSearchChange}
              aria-label="Search users by name or email"
            />
          </div>
          <Combobox
            items={roleFilterItems}
            value={roleId || "all"}
            itemToStringLabel={(v) => {
              if (v === "all") return "All roles";
              const role = roles.find((r) => (getApiEntityId(r) ?? "") === v);
              return role?.name ?? String(v);
            }}
            onValueChange={(value) => {
              setRoleId(value === "all" ? "" : value);
              setPage(1);
            }}
          >
            <ComboboxInput
              placeholder="All roles"
              className={cn(
                usersRoleComboboxInputClassName,
                "w-full sm:w-[150px] h-10 max-[1500px]:h-8 max-[1500px]:min-h-8 max-[1500px]:text-[11px] max-[1500px]:rounded-lg translate-y-0 shadow-sm border-[#d0d5dd]",
              )}
              aria-label="Filter by role"
            />
            <ComboboxContent className={usersRoleComboboxContentClassName}>
              <ComboboxEmpty>No roles found.</ComboboxEmpty>
              <ComboboxList>
                {(itemValue) => {
                  if (itemValue === "all") {
                    return (
                      <ComboboxItem key="all" value="all">
                        All roles
                      </ComboboxItem>
                    );
                  }
                  const role = roles.find(
                    (r) => (getApiEntityId(r) ?? "") === itemValue,
                  );
                  if (!role) return null;
                  return (
                    <ComboboxItem key={itemValue} value={itemValue}>
                      {role.name}
                    </ComboboxItem>
                  );
                }}
              </ComboboxList>
            </ComboboxContent>
          </Combobox>
          {canManageUser ? (
            <div className="flex items-center gap-2 shrink-0">
              <Checkbox
                id="users-include-deleted"
                checked={includeDeleted}
                onCheckedChange={(v) => {
                  setIncludeDeleted(v === true);
                  setPage(1);
                }}
              />
              <Label
                htmlFor="users-include-deleted"
                className="text-[13px] font-medium text-[#475467] cursor-pointer whitespace-nowrap"
              >
                Show deleted
              </Label>
            </div>
          ) : null}
        </div>
      </div>

      <div className="flex flex-col flex-1 min-h-0">
        <div className="flex flex-wrap items-center justify-end gap-3 mb-4">
          {(canCreateUser || canManageUser) && (
            <Button className="max-[1500px]:h-8 max-[1500px]:px-3 max-[1500px]:text-[11px] max-[1500px]:[&_svg]:size-3.5 max-[1500px]:rounded-lg" size="cta" onClick={openCreateDialog}>
              <Plus size={18} className="stroke-[2px]" /> New User
            </Button>
          )}
        </div>
        {waitingForToken ? (
          <Loading message="Loading..." className="py-24" />
        ) : isLoading ? (
          <Loading message="Loading users..." className="py-24" />
        ) : (
          <div className="space-y-6 pb-12">
            <div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 gap-6 shrink-0">
              <KPICard
                label="Total Users"
                value={total.toString()}
                subtext="platform accounts"
                icon={<Users size={20} className="text-accent" />}
                className="bg-white/40 backdrop-blur-sm border-white/60 shadow-sm rounded-2xl"
              />
              <KPICard
                label="Assigned Roles"
                value={users.filter((u) => u.role).length.toString()}
                subtext="active permissions"
                icon={<UserCheck size={20} className="text-accent" />}
                className="bg-white/40 backdrop-blur-sm border-white/60 shadow-sm rounded-2xl"
              />
              <KPICard
                label="Available Roles"
                value={roles.length.toString()}
                subtext="system definitions"
                icon={<ShieldCheck size={20} className="text-accent" />}
                className="bg-white/40 backdrop-blur-sm border-white/60 shadow-sm rounded-2xl sm:col-span-2 xl:col-span-1"
              />
            </div>

            <div className="flex flex-col shrink-0">
              <div className="rounded-[20px] border border-[#eaecf0] overflow-hidden bg-white/70 backdrop-blur-md shadow-sm">
                <div className="overflow-x-auto scrollbar-themed">
                  <TooltipProvider delayDuration={300}>
                    <Table variant="transparent">
                      <TableHeader>
                        <TableRow className="hover:bg-transparent border-b border-[#eaecf0] bg-[#f9fafb]/80">
                          <TableHead
                            className="w-[320px] cursor-pointer font-bold text-[#475467] py-4"
                            onClick={() => handleSort("name")}
                          >
                            <div className="flex items-center gap-1.5 px-1 uppercase tracking-wider text-[11px] font-bold">
                              User{" "}
                              <SortIcon
                                col="name"
                                sortCol={sortCol}
                                sortDir={sortDir}
                              />
                            </div>
                          </TableHead>
                          <TableHead
                            className="hidden md:table-cell cursor-pointer font-bold text-[#475467] py-4"
                            onClick={() => handleSort("role")}
                          >
                            <div className="flex items-center gap-1.5 uppercase tracking-wider text-[11px] font-bold">
                              Role{" "}
                              <SortIcon
                                col="role"
                                sortCol={sortCol}
                                sortDir={sortDir}
                              />
                            </div>
                          </TableHead>
                          <TableHead className="font-bold text-[#475467] py-4">
                            <div className="uppercase tracking-wider text-[11px] font-bold">
                              Status
                            </div>
                          </TableHead>
                          <TableHead className="text-right font-bold text-[#475467] py-4">
                            <div className="px-2 uppercase tracking-wider text-[11px] font-bold">
                              Actions
                            </div>
                          </TableHead>
                        </TableRow>
                      </TableHeader>
                      <TableBody>
                        {users.length === 0 ? (
                          <TableRow>
                            <TableCell colSpan={4} className="p-6 align-middle">
                              <NoDataFound
                                message="No users found"
                                description={
                                  search.trim()
                                    ? "Try a different search or adjust filters."
                                    : includeDeleted
                                      ? "No users match the current filters."
                                      : "When you add users, they will appear in this list."
                                }
                                variant="card"
                                size="sm"
                                action={
                                  canCreateUser ? (
                                    <Button
                                      size="ctaCompact"
                                      className="max-[1500px]:h-8 max-[1500px]:px-3 max-[1500px]:text-[11px] max-[1500px]:[&_svg]:size-3.5 max-[1500px]:rounded-lg"
                                      onClick={openCreateDialog}
                                    >
                                      <Plus
                                        size={16}
                                        className="stroke-[2px]"
                                      />
                                      New user
                                    </Button>
                                  ) : undefined
                                }
                              />
                            </TableCell>
                          </TableRow>
                        ) : (
                          users.map((user) => (
                            <TableRow
                              key={user.id}
                              className={cn(
                                "group border-b border-[#eaecf0] hover:bg-[#f9fafb] transition-colors",
                                user.isDeleted && "opacity-75 bg-amber-50/40",
                              )}
                            >
                              <TableCell className="py-4">
                                <UserRolePermissionPopover
                                  user={user}
                                  getFullImageUrl={getFullImageUrl}
                                >
                                  <div className="relative size-10 rounded-xl flex items-center justify-center text-[12px] font-bold text-white shrink-0 bg-accent shadow-sm ring-2 ring-white overflow-hidden">
                                    {user.avatar?.url ? (
                                      <Image
                                        src={getFullImageUrl(user.avatar.url)}
                                        alt={user.name}
                                        fill
                                        sizes="40px"
                                        className="object-cover"
                                      />
                                    ) : (
                                      user.name
                                        .split(/\s+/)
                                        .map((s) => s[0])
                                        .join("")
                                        .slice(0, 2)
                                        .toUpperCase()
                                    )}
                                  </div>
                                  <div className="flex flex-col min-w-0 ml-1">
                                    <span className="text-[14px] font-bold text-[#101828] truncate font-['Lexend'] mb-0.5">
                                      {user.name}
                                    </span>
                                    <span className="text-[11px] text-[#475467] truncate font-medium">
                                      {user.email}
                                    </span>
                                    <div className="md:hidden mt-1 inline-flex">
                                      <span className="inline-flex items-center px-1.5 py-0.5 rounded-md text-[10px] font-bold bg-[#f2f4f7] text-[#344054] border border-[#d0d5dd]">
                                        {getRoleName(user.role)}
                                      </span>
                                    </div>
                                  </div>
                                </UserRolePermissionPopover>
                              </TableCell>
                              <TableCell className="py-4 hidden md:table-cell">
                                <div className="inline-flex items-center px-2.5 py-0.5 rounded-full text-[12px] font-bold bg-[#f2f4f7] text-[#344054] border border-[#d0d5dd]">
                                  {getRoleName(user.role)}
                                </div>
                              </TableCell>
                              <TableCell className="py-3">
                                {user.isDeleted ? (
                                  <span className="inline-flex items-center rounded-md border border-amber-200 bg-amber-50 px-2 py-0.5 text-[11px] font-semibold text-amber-800">
                                    Deleted
                                  </span>
                                ) : (
                                  <div className="flex items-center gap-2">
                                    {canMutateUserRows ? (
                                      <Switch
                                        checked={
                                          getUserStatus(user) === "Active"
                                        }
                                        onCheckedChange={async (checked) => {
                                          const status = checked
                                            ? "Active"
                                            : "Inactive";
                                          if (
                                            user.id === currentUserId &&
                                            status === "Inactive"
                                          ) {
                                            toast.error(
                                              "You cannot deactivate your own account",
                                            );
                                            return;
                                          }
                                          try {
                                            await updateUserStatus({
                                              id: user.id,
                                              status,
                                            }).unwrap();
                                            toast.success(
                                              `User ${status === "Active" ? "activated" : "deactivated"}`,
                                            );
                                          } catch (e) {
                                            toast.error(
                                              e &&
                                                typeof e === "object" &&
                                                "data" in e
                                                ? (
                                                    e as {
                                                      data?: {
                                                        message?: string;
                                                      };
                                                    }
                                                  ).data?.message
                                                : "Failed to update status",
                                            );
                                          }
                                        }}
                                        disabled={user.id === currentUserId}
                                      />
                                    ) : null}
                                    <span
                                      className={cn(
                                        "text-[11px] font-medium",
                                        getUserStatus(user) === "Active"
                                          ? "text-green-600"
                                          : "text-gray-500",
                                      )}
                                    >
                                      {getUserStatus(user)}
                                    </span>
                                  </div>
                                )}
                              </TableCell>
                              <TableCell className="text-right py-4">
                                <div className="flex items-center justify-end gap-1.5 opacity-100">
                                  <Tooltip>
                                    <TooltipTrigger asChild>
                                      <Button
                                        type="button"
                                        variant="toolbar"
                                        tone="info"
                                        onClick={(e) => {
                                          e.stopPropagation();
                                          handleViewLogs(user);
                                        }}
                                      >
                                        <Activity size={16} />
                                      </Button>
                                    </TooltipTrigger>
                                    <TooltipContent side="top">
                                      View activity logs
                                    </TooltipContent>
                                  </Tooltip>
                                  <Can action="read" subject="user">
                                    <Tooltip>
                                      <TooltipTrigger asChild>
                                        <Button
                                          type="button"
                                          variant="toolbar"
                                          tone="violet"
                                          asChild
                                        >
                                          <Link
                                            href={`/users/${user.id}/permissions`}
                                            onClick={(e) => e.stopPropagation()}
                                            prefetch={false}
                                          >
                                            <KeyRound size={16} />
                                          </Link>
                                        </Button>
                                      </TooltipTrigger>
                                      <TooltipContent side="top">
                                        View permissions
                                      </TooltipContent>
                                    </Tooltip>
                                  </Can>
                                  {canMutateUserRows ? (
                                    user.isDeleted ? (
                                      <Tooltip>
                                        <TooltipTrigger asChild>
                                          <Button
                                            type="button"
                                            variant="toolbar"
                                            tone="success"
                                            onClick={(e) => {
                                              e.stopPropagation();
                                              void handleRestoreUser(user);
                                            }}
                                            disabled={restoring}
                                          >
                                            <RotateCcw size={16} />
                                          </Button>
                                        </TooltipTrigger>
                                        <TooltipContent side="top">
                                          Restore user
                                        </TooltipContent>
                                      </Tooltip>
                                    ) : (
                                      <>
                                        <Tooltip>
                                          <TooltipTrigger asChild>
                                            <Button
                                              type="button"
                                              variant="toolbar"
                                              tone="accent"
                                              onClick={(e) => {
                                                e.stopPropagation();
                                                openEditDialog(user);
                                              }}
                                            >
                                              <Pencil size={16} />
                                            </Button>
                                          </TooltipTrigger>
                                          <TooltipContent side="top">
                                            Edit user
                                          </TooltipContent>
                                        </Tooltip>
                                        <Tooltip>
                                          <TooltipTrigger asChild>
                                            <Button
                                              type="button"
                                              variant="toolbar"
                                              tone="danger"
                                              onClick={(e) => {
                                                e.stopPropagation();
                                                confirmDelete(user);
                                              }}
                                            >
                                              <Trash2 size={16} />
                                            </Button>
                                          </TooltipTrigger>
                                          <TooltipContent side="top">
                                            Delete user
                                          </TooltipContent>
                                        </Tooltip>
                                      </>
                                    )
                                  ) : null}
                                </div>
                              </TableCell>
                            </TableRow>
                          ))
                        )}
                      </TableBody>
                    </Table>
                  </TooltipProvider>
                </div>
              </div>

              {total > 0 && (
                <div className="flex flex-wrap items-center justify-between gap-3 py-4 px-1 border-t border-border/60 mt-4 shrink-0">
                  <div className="flex items-center gap-3">
                    <span className="text-[12px] text-muted-foreground font-medium">
                      Showing {(page - 1) * limit + 1}–
                      {Math.min(page * limit, total)} of {total}
                    </span>
                    <ReactSelect
                      value={String(limit)}
                      onValueChange={(v) => {
                        setLimit(parseInt(v, 10));
                        setPage(1);
                      }}
                      options={pageLimitOptions}
                      triggerClassName="h-8 w-[100px] text-[12px]"
                    />
                  </div>
                  {totalPages > 1 && (
                    <div className="flex items-center gap-2">
                      <Button
                        variant="outline"
                        size="pagination"
                        onClick={() => setPage((p) => Math.max(1, p - 1))}
                        disabled={page <= 1 || usersFetching}
                      >
                        <ChevronLeft size={14} />
                        Previous
                      </Button>
                      <div className="flex items-center gap-1">
                        {Array.from({ length: totalPages }, (_, i) => i + 1)
                          .filter(
                            (p) =>
                              p === 1 ||
                              p === totalPages ||
                              Math.abs(p - page) <= 1,
                          )
                          .reduce<(number | "ellipsis")[]>(
                            (acc, p, idx, arr) => {
                              if (idx > 0 && p - (arr[idx - 1] as number) > 1)
                                acc.push("ellipsis");
                              acc.push(p);
                              return acc;
                            },
                            [],
                          )
                          .map((item, idx) =>
                            item === "ellipsis" ? (
                              <span
                                key={`e-${idx}`}
                                className="px-1 text-[12px] text-muted-foreground"
                              >
                                …
                              </span>
                            ) : (
                              <Button
                                key={item}
                                variant={item === page ? "paginationPageCurrent" : "ghost"}
                                size={item === page ? "page" : "page"}
                                onClick={() => setPage(item)}
                                disabled={usersFetching}
                              >
                                {item}
                              </Button>
                            ),
                          )}
                      </div>
                      <Button
                        variant="outline"
                        size="pagination"
                        onClick={() =>
                          setPage((p) => Math.min(totalPages, p + 1))
                        }
                        disabled={page >= totalPages || usersFetching}
                      >
                        Next
                        <ChevronRight size={14} />
                      </Button>
                    </div>
                  )}
                </div>
              )}
            </div>
          </div>
        )}
      </div>

      <Dialog open={userDialogOpen} onOpenChange={setUserDialogOpen}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>
              {userDialogMode === "create" ? "New User" : "Edit User"}
            </DialogTitle>
          </DialogHeader>
          <div className="grid gap-4 py-4 max-h-[60vh] overflow-y-auto scrollbar-themed px-1">
            <div className="flex flex-col items-center gap-4 mb-2">
              <div className="relative group">
                <div className="relative size-20 rounded-full bg-accent/10 border-2 border-dashed border-accent/40 flex items-center justify-center overflow-hidden">
                  {filePreview ? (
                    <Image
                      src={filePreview}
                      alt="Preview"
                      fill
                      sizes="80px"
                      className="object-cover"
                      unoptimized={
                        filePreview.startsWith("blob:") ||
                        filePreview.startsWith("data:")
                      }
                    />
                  ) : editingUser?.avatar?.url ? (
                    <Image
                      src={getFullImageUrl(editingUser.avatar.url)}
                      alt="User Avatar"
                      fill
                      sizes="80px"
                      className="object-cover"
                    />
                  ) : (
                    <Camera className="text-accent/40" size={32} />
                  )}
                </div>
                <Label
                  htmlFor="user-image"
                  className="absolute inset-0 flex items-center justify-center bg-black/40 text-white rounded-full opacity-0 group-hover:opacity-100 cursor-pointer transition-opacity"
                >
                  <Camera size={20} />
                </Label>
                <input
                  id="user-image"
                  type="file"
                  accept="image/*"
                  className="hidden"
                  onChange={(e) => {
                    const file = e.target.files?.[0];
                    if (file) setValue("file", file);
                  }}
                />
              </div>
              <p className="text-[11px] text-gray-500 font-medium">
                Click to upload avatar (optional)
              </p>
            </div>

            <div className="grid gap-2">
              <Label htmlFor="user-name">Name</Label>
              <Controller
                name="name"
                control={control}
                render={({ field }) => (
                  <Input {...field} id="user-name" placeholder="Full name" />
                )}
              />
              {errors.name && (
                <p className="text-[11px] text-destructive">
                  {errors.name.message}
                </p>
              )}
            </div>
            <div className="grid gap-2">
              <Label htmlFor="user-email">Email</Label>
              <Controller
                name="email"
                control={control}
                render={({ field }) => (
                  <Input
                    {...field}
                    id="user-email"
                    type="email"
                    placeholder="user@example.com"
                  />
                )}
              />
              {errors.email && (
                <p className="text-[11px] text-destructive">
                  {errors.email.message}
                </p>
              )}
            </div>
            <div className="grid gap-2">
              <Label htmlFor="user-password">
                Password{" "}
                {userDialogMode === "edit" && "(leave blank to keep current)"}
              </Label>
              <Controller
                name="password"
                control={control}
                render={({ field }) => (
                  <div className="relative">
                    <Input
                      {...field}
                      id="user-password"
                      type={showPassword ? "text" : "password"}
                      placeholder={
                        userDialogMode === "edit"
                          ? "Leave blank to keep"
                          : "Min 6 characters"
                      }
                      className="pr-10"
                    />
                    <Button
                      type="button"
                      variant="inputTrailingIcon"
                      onClick={() => setShowPassword((prev) => !prev)}
                      aria-label={
                        showPassword ? "Hide password" : "Show password"
                      }
                    >
                      {showPassword ? <EyeOff size={18} /> : <Eye size={18} />}
                    </Button>
                  </div>
                )}
              />
              {errors.password && (
                <p className="text-[11px] text-destructive">
                  {errors.password.message}
                </p>
              )}
            </div>
            <div className="grid gap-2">
              <Label htmlFor="user-role">Role</Label>
              <Controller
                name="role"
                control={control}
                render={({ field }) => (
                  <ReactSelect
                    id="user-role"
                    value={field.value ? field.value : "none"}
                    onValueChange={(v) => field.onChange(v === "none" ? "" : v)}
                    disabled={rolesLoading}
                    options={roleSelectOptions}
                    placeholder="Select role"
                    triggerClassName={cn(usersRoleComboboxInputClassName, "w-full")}
                    contentClassName={usersRoleComboboxContentClassName}
                  />
                )}
              />
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setUserDialogOpen(false)}>
              Cancel
            </Button>
            <Button
              onClick={handleUserDialogSubmit}
              disabled={creating || (userDialogMode === "edit" && updating)}
            >
              {userDialogMode === "create"
                ? creating
                  ? "Creating..."
                  : "Create"
                : updating
                  ? "Saving..."
                  : "Save"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <AlertDialog
        open={deleteDialogOpen}
        onOpenChange={(open) => {
          if (!open && deleting) return;
          setDeleteDialogOpen(open);
          if (!open && !deleting) {
            setUserToDelete(null);
          }
        }}
      >
        <AlertDialogContent size="sm">
          <AlertDialogHeader>
            <AlertDialogMedia className="bg-destructive/10 text-destructive">
              <TriangleAlert />
            </AlertDialogMedia>
            <AlertDialogTitle>Delete user</AlertDialogTitle>
            <AlertDialogDescription>
              Delete access for &quot;{userToDelete?.name}&quot; and remove the
              saved avatar image. This action cannot be undone.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel onClick={cancelDelete} disabled={deleting}>
              Keep user
            </AlertDialogCancel>
            <Button
              type="button"
              variant="destructive"
              onClick={() => void handleDeleteConfirm()}
              disabled={deleting}
            >
              {deleting ? "Deleting..." : "Yes, delete"}
            </Button>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}
