// src/pages/AdminUserStorage.jsx
import React, {
  useEffect,
  useMemo,
  useState,
  useCallback,
  useRef,
  useLayoutEffect,
} from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { createPortal } from "react-dom";
import PageShell from "./_pageShell";
import { api } from "../services/api";
import { useToast } from "../components/ToastProvider";
import DropdownPortal from "../components/DropdownPortal";
import {
  TbRefresh,
  TbSearch,
  TbPencil,
  TbTrash,
  TbCheck,
  TbX,
  TbAlertTriangle,
  TbUser,
  TbUsers,
  TbFolder,
  TbFile,
  TbChevronLeft,
  TbHome,
  TbDotsVertical,
} from "react-icons/tb";

/* ---------------- helpers ---------------- */
function cn(...a) {
  return a.filter(Boolean).join(" ");
}
function toFa(v) {
  try {
    return String(v).toLocaleString("fa-IR");
  } catch {
    return String(v ?? "");
  }
}
function fmtDate(iso) {
  if (!iso) return "-";
  try {
    return new Date(iso).toLocaleString("fa-IR", {
      year: "numeric",
      month: "2-digit",
      day: "2-digit",
      hour: "2-digit",
      minute: "2-digit",
    });
  } catch {
    return iso;
  }
}
const getErrMsg = (e, fallback = "خطای ناشناخته") => {
  const d = e?.response?.data;
  if (!d) return e?.message || fallback;
  if (typeof d === "string") return d;
  if (d.detail) return d.detail;
  if (d.message) return d.message;
  try {
    return JSON.stringify(d);
  } catch {
    return fallback;
  }
};
function bytesToHuman(bytes) {
  const n = Number(bytes ?? 0);
  if (!Number.isFinite(n)) return "-";
  const units = ["B", "KB", "MB", "GB", "TB", "PB"];
  let x = n;
  let i = 0;
  while (x >= 1024 && i < units.length - 1) {
    x /= 1024;
    i++;
  }
  const fixed = i === 0 ? 0 : 2;
  return `${toFa(x.toFixed(fixed))} ${units[i]}`;
}
function extFromName(name) {
  const s = String(name || "");
  const i = s.lastIndexOf(".");
  if (i === -1) return "";
  return s.slice(i + 1).toUpperCase();
}
function guessTypeBadge(name) {
  const ext = extFromName(name);
  if (!ext) return { tone: "default", label: "FILE" };
  const img = ["JPG", "JPEG", "PNG", "WEBP", "GIF", "SVG", "AVIF"];
  const doc = ["PDF", "DOC", "DOCX", "PPT", "PPTX", "XLS", "XLSX", "TXT"];
  const zip = ["ZIP", "RAR", "7Z", "TAR", "GZ"];
  if (img.includes(ext)) return { tone: "info", label: ext };
  if (doc.includes(ext)) return { tone: "success", label: ext };
  if (zip.includes(ext)) return { tone: "warn", label: ext };
  return { tone: "default", label: ext };
}
function clamp(n, min, max) {
  return Math.max(min, Math.min(max, n));
}

/* ---------------- UI atoms (same vibe) ---------------- */
const CARD =
  "rounded-2xl shadow border border-black/10 dark:border-white/10 bg-white/70 dark:bg-white/5 backdrop-blur-sm";
const SOFT =
  "rounded-2xl shadow border border-black/10 dark:border-white/10 bg-[#A1E3F910] dark:bg-[#A1E3F919]";
const INPUT_BASE =
  "w-full dark:bg-[#A1E3F919] bg-[#A1E3F980] text-sm rounded-xl shadow grid relative items-center border border-black/10 dark:border-white/10";
const INPUT =
  "h-11 px-4 w-full outline-0 focus:outline-0 rounded-xl bg-transparent text-black dark:text-white placeholder:text-black/50 dark:placeholder:text-white/50";

function Badge({ tone = "default", children }) {
  const m = {
    default:
      "bg-black/5 border-black/10 text-black/70 dark:text-white/70 dark:bg-white/10 dark:border-white/10",
    success:
      "bg-emerald-500/10 border-emerald-500/25 text-emerald-700 dark:text-emerald-200",
    danger:
      "bg-red-500/10 border-red-500/25 text-red-700 dark:text-red-200",
    warn:
      "bg-amber-500/10 border-amber-500/25 text-amber-700 dark:text-amber-200",
    info:
      "bg-[#43BEFF14] border-[#43BEFF40] text-[#146E85] dark:text-[#A1E3F9]",
  };
  return (
    <span
      className={cn(
        "inline-flex items-center gap-2 px-3 py-1 rounded-full text-xs border",
        m[tone] || m.default
      )}
    >
      {children}
    </span>
  );
}

/* ---------------- Modal ---------------- */
function useBodyScrollLock(locked) {
  useEffect(() => {
    if (!locked) return;
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => (document.body.style.overflow = prev);
  }, [locked]);
}

function Modal({ open, title, onClose, children, widthClass = "max-w-2xl" }) {
  useBodyScrollLock(open);

  useEffect(() => {
    if (!open) return;
    const onKey = (e) => e.key === "Escape" && onClose?.();
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [open, onClose]);

  if (!open) return null;

  return createPortal(
    <div className="fixed inset-0 z-[9998]">
      <div className="absolute inset-0 bg-black/45" onClick={onClose} />
      <div className={cn("absolute inset-x-0 top-10 mx-auto px-3", widthClass)}>
        <div className="rounded-2xl shadow-xl border border-black/10 dark:border-white/10 bg-white dark:bg-[#0b1d39] overflow-hidden">
          <div className="px-4 py-3 border-b border-black/10 dark:border-white/10 flex items-center justify-between">
            <div className="font-extrabold text-black dark:text-white text-sm truncate">
              {title}
            </div>
            <button
              type="button"
              onClick={onClose}
              className="rounded-xl px-3 py-2 hover:bg-black/5 dark:hover:bg-white/10 transition"
            >
              <TbX className="w-5 h-5" />
            </button>
          </div>
          <div className="p-4">{children}</div>
        </div>
      </div>
    </div>,
    document.body
  );
}

function Field({ label, children, hint }) {
  return (
    <div>
      <div className="mb-1 text-xs text-black/60 dark:text-white/70 font-bold">
        {label}
      </div>
      {children}
      {hint ? (
        <div className="mt-1 text-[11px] text-black/50 dark:text-white/60">
          {hint}
        </div>
      ) : null}
    </div>
  );
}

/* ---------------- Outside pointerdown (NO CAPTURE) ---------------- */
function useOutsidePointerDown(ref, handler, when = true) {
  useEffect(() => {
    if (!when) return;

    const onDown = (e) => {
      if (!ref.current) return;
      if (ref.current.contains(e.target)) return;
      handler?.(e);
    };

    document.addEventListener("pointerdown", onDown); // bubble phase ✅
    return () => document.removeEventListener("pointerdown", onDown);
  }, [ref, handler, when]);
}

/* ---------------- Action Menu (3 dots) - FIXED LIKE COUPONS ---------------- */
function ActionMenuDots({ id, menu, setMenu, items = [] }) {
  const open = menu?.id === id && !!menu?.rect;
  const close = useCallback(() => setMenu({ id: null, rect: null }), [setMenu]);

  const menuRef = useRef(null);
  useOutsidePointerDown(menuRef, () => close(), open);

  useEffect(() => {
    if (!open) return;
    const onKey = (e) => e.key === "Escape" && close();
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [open, close]);

  const onToggle = (e) => {
    e.preventDefault();
    e.stopPropagation();
    const r = e.currentTarget.getBoundingClientRect();
    setMenu((prev) => (prev?.id === id ? { id: null, rect: null } : { id, rect: r }));
  };

  const rect = menu?.rect;
  const [pos, setPos] = useState({ top: 0, left: 0 });

  useLayoutEffect(() => {
    if (!open || !rect) return;

    const calc = () => {
      const vw = window.innerWidth;
      const vh = window.innerHeight;

      const menuW = 224; // w-56
      const menuH = menuRef.current?.offsetHeight || 220;

      let top = rect.bottom + 8;
      let left = rect.right - menuW;

      if (top + menuH > vh - 8) top = rect.top - menuH - 8;

      top = clamp(top, 8, vh - menuH - 8);
      left = clamp(left, 8, vw - menuW - 8);

      setPos({ top, left });
    };

    calc();
    window.addEventListener("resize", calc);
    window.addEventListener("scroll", calc, true);
    return () => {
      window.removeEventListener("resize", calc);
      window.removeEventListener("scroll", calc, true);
    };
  }, [open, rect]);

  return (
    <span className="relative">
      <button
        type="button"
        onPointerDown={(e) => {
          // ✅ خیلی مهم: جلوگیری از بیرونی‌ها (خصوصاً pointerdownهای parent)
          e.preventDefault();
          e.stopPropagation();
        }}
        onClick={onToggle}
        className={cn(
          "h-9 w-9 grid place-items-center rounded-xl border border-black/10 dark:border-white/10",
          "bg-white/70 dark:bg-white/5 hover:bg-black/5 dark:hover:bg-white/10 transition"
        )}
        aria-label="actions"
      >
        <TbDotsVertical className="w-5 h-5 text-black/70 dark:text-white" />
      </button>

      {open && rect
        ? createPortal(
            <div
              ref={menuRef}
              className="fixed z-[9999]"
              style={{ top: pos.top, left: pos.left, width: 224 }}
              onPointerDown={(e) => e.stopPropagation()}
              onClick={(e) => e.stopPropagation()}
            >
              <div className="w-56 rounded-2xl shadow-xl border border-black/10 dark:border-white/10 bg-white dark:bg-[#0b1d39] overflow-hidden">
                <div className="p-1">
                  {items.map((it, idx) => (
                    <button
                      key={idx}
                      type="button"
                      onPointerDown={(e) => {
                        // ✅ اجازه نده بیرون منو رو ببنده / کلیک رو بخوره
                        e.preventDefault();
                        e.stopPropagation();
                      }}
                      onClick={(e) => {
                        e.preventDefault();
                        e.stopPropagation();
                        close();
                        it?.onClick?.();
                      }}
                      className={cn(
                        "w-full text-right px-3 py-2 rounded-xl",
                        "hover:bg-black/5 dark:hover:bg-white/10 transition",
                        it?.danger
                          ? "text-red-700 dark:text-red-200"
                          : "text-black dark:text-white"
                      )}
                    >
                      <div className="flex items-center justify-between gap-2">
                        <span className="text-sm font-semibold">{it?.label}</span>
                        {it?.icon ? <span className="opacity-80">{it.icon}</span> : null}
                      </div>
                    </button>
                  ))}
                </div>
              </div>
            </div>,
            document.body
          )
        : null}
    </span>
  );
}

/* ---------------- API ---------------- */
async function listUsers(params) {
  const res = await api.get("/api/admin/users/", { params });
  return res.data;
}

// edit/delete user
async function patchUser({ user_id, payload }) {
  const res = await api.patch(`/api/admin/users/${user_id}/`, payload);
  return res.data;
}
async function deleteUser(user_id) {
  const res = await api.delete(`/api/admin/users/${user_id}/`);
  return res.data;
}

async function listFolders(params) {
  const res = await api.get("/api/admin/storage/folders/", { params });
  return res.data;
}
async function patchFolder({ folder_id, payload }) {
  const res = await api.patch(`/api/admin/storage/folders/${folder_id}/`, payload);
  return res.data;
}
async function deleteFolder(folder_id) {
  const res = await api.delete(`/api/admin/storage/folders/${folder_id}/`);
  return res.data;
}
async function listFiles(params) {
  const res = await api.get("/api/admin/storage/files/", { params });
  return res.data;
}
async function patchFile({ entry_id, payload }) {
  const res = await api.patch(`/api/admin/storage/files/${entry_id}/`, payload);
  return res.data;
}
async function deleteFile(entry_id) {
  const res = await api.delete(`/api/admin/storage/files/${entry_id}/`);
  return res.data;
}
async function listSubscriptions(params) {
  const res = await api.get("/api/admin/billing/subscriptions/", { params });
  return res.data;
}

/* ---------------- Page ---------------- */
export default function AdminUserStorage() {
  const qc = useQueryClient();
  const { success, error: toastError, info } = useToast();

  // ✅ جدا کردن state منوها (مثل AdminCoupons)
  const [actionMenu, setActionMenu] = useState({ id: null, rect: null }); // 3-dots
  const [ddMenu, setDdMenu] = useState({ id: null, rect: null }); // DropdownPortal

  const closeAllMenus = useCallback(() => {
    setActionMenu({ id: null, rect: null });
    setDdMenu({ id: null, rect: null });
  }, []);

  // users filters
  const [uq, setUq] = useState("");
  const [uActive, setUActive] = useState("all");

  // selected
  const [selectedUser, setSelectedUser] = useState(null);
  const [selectedFolderId, setSelectedFolderId] = useState(null);

  // filters
  const [fq, setFq] = useState("");
  const [fileQ, setFileQ] = useState("");

  // user edit/delete modals
  const [userEditOpen, setUserEditOpen] = useState(false);
  const [userDeleteOpen, setUserDeleteOpen] = useState(false);
  const [userCurrent, setUserCurrent] = useState(null);
  const [userDraft, setUserDraft] = useState({
    username: "",
    email: "",
    phone: "",
    full_name: "",
    is_active: true,
    storage_limit: "",
  });

  // folder modals
  const [folderRenameOpen, setFolderRenameOpen] = useState(false);
  const [folderDeleteOpen, setFolderDeleteOpen] = useState(false);
  const [folderDraftName, setFolderDraftName] = useState("");
  const [folderCurrent, setFolderCurrent] = useState(null);

  // file modals
  const [fileRenameOpen, setFileRenameOpen] = useState(false);
  const [fileDeleteOpen, setFileDeleteOpen] = useState(false);
  const [fileCurrent, setFileCurrent] = useState(null);
  const [fileDraft, setFileDraft] = useState({ name: "", folder: null });

  const activeOptions = useMemo(
    () => [
      { value: "all", label: "همه وضعیت‌ها" },
      { value: "true", label: "فقط فعال" },
      { value: "false", label: "فقط غیرفعال" },
    ],
    []
  );

  // users
  const qUsers = useQuery({
    queryKey: ["admin-users", { uq, uActive }],
    queryFn: () =>
      listUsers({
        q: uq || undefined,
        is_active: uActive === "all" ? undefined : uActive,
        page: 1,
        page_size: 2000,
      }),
    staleTime: 10_000,
    refetchOnWindowFocus: false,
  });

  const users = useMemo(() => {
    const d = qUsers.data;
    return Array.isArray(d) ? d : d?.results || [];
  }, [qUsers.data]);

  useEffect(() => {
    if (selectedUser?.id) return;
    if (users.length > 0) {
      setSelectedUser(users[0]);
      setSelectedFolderId(null);
      setFq("");
      setFileQ("");
    }
  }, [users, selectedUser?.id]);

  const ownerId = selectedUser?.id || null;

  // subscriptions for selected user
  const qSub = useQuery({
    enabled: !!ownerId,
    queryKey: ["admin-subs", { user: ownerId }],
    queryFn: () =>
      listSubscriptions({
        user: ownerId,
        status: "active",
        page: 1,
        page_size: 50,
      }),
    staleTime: 10_000,
    refetchOnWindowFocus: false,
  });

  const selectedUserActiveSub = useMemo(() => {
    const d = qSub.data;
    const arr = Array.isArray(d) ? d : d?.results || [];
    return (
      arr.find(
        (s) =>
          String(s?.status || "").toLowerCase() === "active" &&
          Number(s?.user) === Number(ownerId)
      ) || null
    );
  }, [qSub.data, ownerId]);

  // folders
  const qFolders = useQuery({
    enabled: !!ownerId,
    queryKey: ["admin-folders", { ownerId, fq }],
    queryFn: () =>
      listFolders({
        owner_id: ownerId,
        q: fq || undefined,
        page: 1,
        page_size: 2000,
      }),
    staleTime: 5_000,
    refetchOnWindowFocus: false,
  });

  const allFolders = useMemo(() => {
    const d = qFolders.data;
    return Array.isArray(d) ? d : d?.results || [];
  }, [qFolders.data]);

  const folderById = useMemo(() => {
    const m = new Map();
    allFolders.forEach((f) => f?.id && m.set(String(f.id), f));
    return m;
  }, [allFolders]);

  const childrenMap = useMemo(() => {
    const m = new Map();
    const push = (k, v) => {
      const key = k == null ? "__ROOT__" : String(k);
      const arr = m.get(key) || [];
      arr.push(v);
      m.set(key, arr);
    };
    allFolders.forEach((f) => push(f?.parent ?? null, f));
    for (const [k, arr] of m.entries()) {
      arr.sort((a, b) =>
        String(a?.name || "").localeCompare(String(b?.name || ""), "fa")
      );
      m.set(k, arr);
    }
    return m;
  }, [allFolders]);

  const currentChildrenFolders = useMemo(() => {
    const key = selectedFolderId == null ? "__ROOT__" : String(selectedFolderId);
    return childrenMap.get(key) || [];
  }, [childrenMap, selectedFolderId]);

  const breadcrumb = useMemo(() => {
    const chain = [];
    if (selectedFolderId == null) return chain;
    let curId = String(selectedFolderId);
    const seen = new Set();
    while (curId && !seen.has(curId)) {
      seen.add(curId);
      const f = folderById.get(curId);
      if (!f) break;
      chain.push(f);
      curId = f?.parent ? String(f.parent) : null;
    }
    return chain.reverse();
  }, [selectedFolderId, folderById]);

  useEffect(() => {
    if (selectedFolderId == null) return;
    if (!folderById.has(String(selectedFolderId))) setSelectedFolderId(null);
  }, [selectedFolderId, folderById]);

  // files
  const qFiles = useQuery({
    enabled: !!ownerId,
    queryKey: ["admin-files", { ownerId, folder_id: selectedFolderId, fileQ }],
    queryFn: () => {
      const params = {
        owner_id: ownerId,
        q: fileQ || undefined,
        page: 1,
        page_size: 2000,
      };
      if (selectedFolderId) params.folder_id = selectedFolderId;
      return listFiles(params);
    },
    staleTime: 5_000,
    refetchOnWindowFocus: false,
  });

  const files = useMemo(() => {
    const d = qFiles.data;
    return Array.isArray(d) ? d : d?.results || [];
  }, [qFiles.data]);

  // user mutations
  const mutPatchUser = useMutation({
    mutationFn: patchUser,
    onSuccess: async (updated) => {
      await qc.invalidateQueries({ queryKey: ["admin-users"] });
      success("کاربر بروزرسانی شد ✅", { title: "Users" });

      if (
        updated?.id &&
        selectedUser?.id &&
        Number(updated.id) === Number(selectedUser.id)
      ) {
        setSelectedUser((p) => ({ ...p, ...updated }));
      }

      setUserEditOpen(false);
      setUserCurrent(null);
    },
    onError: (e) => toastError(getErrMsg(e, "خطا در ویرایش کاربر"), { title: "Users" }),
  });

  const mutDeleteUser = useMutation({
    mutationFn: deleteUser,
    onSuccess: async () => {
      await qc.invalidateQueries({ queryKey: ["admin-users"] });
      success("کاربر حذف شد ✅", { title: "Users" });

      const deletedId = userCurrent?.id;

      setUserDeleteOpen(false);
      setUserCurrent(null);

      if (deletedId && selectedUser?.id && Number(deletedId) === Number(selectedUser.id)) {
        const res = await qUsers.refetch();
        const fresh = Array.isArray(res?.data) ? res.data : res?.data?.results || [];
        const nextUser = fresh?.[0] || null;
        setSelectedUser(nextUser);
        setSelectedFolderId(null);
        setFq("");
        setFileQ("");
      }
    },
    onError: (e) => toastError(getErrMsg(e, "خطا در حذف کاربر"), { title: "Users" }),
  });

  // folder mutations
  const mutRenameFolder = useMutation({
    mutationFn: patchFolder,
    onSuccess: async () => {
      await qc.invalidateQueries({ queryKey: ["admin-folders"] });
      success("فولدر بروزرسانی شد ✅", { title: "Storage" });
      setFolderRenameOpen(false);
      setFolderCurrent(null);
      setFolderDraftName("");
    },
    onError: (e) => toastError(getErrMsg(e, "خطا در تغییر نام فولدر"), { title: "Storage" }),
  });

  const mutDeleteFolder = useMutation({
    mutationFn: deleteFolder,
    onSuccess: async () => {
      await qc.invalidateQueries({ queryKey: ["admin-folders"] });
      success("فولدر حذف شد ✅", { title: "Storage" });
      setFolderDeleteOpen(false);
      setFolderCurrent(null);

      if (folderCurrent?.id && String(folderCurrent.id) === String(selectedFolderId || "")) {
        const parentId2 = folderCurrent?.parent ? String(folderCurrent.parent) : null;
        setSelectedFolderId(parentId2 || null);
      }
    },
    onError: (e) => toastError(getErrMsg(e, "خطا در حذف فولدر"), { title: "Storage" }),
  });

  // file mutations
  const mutRenameFile = useMutation({
    mutationFn: patchFile,
    onSuccess: async () => {
      await qc.invalidateQueries({ queryKey: ["admin-files"] });
      success("فایل بروزرسانی شد ✅", { title: "Storage" });
      setFileRenameOpen(false);
      setFileCurrent(null);
    },
    onError: (e) => toastError(getErrMsg(e, "خطا در تغییر فایل"), { title: "Storage" }),
  });

  const mutDeleteFile = useMutation({
    mutationFn: deleteFile,
    onSuccess: async () => {
      await qc.invalidateQueries({ queryKey: ["admin-files"] });
      success("فایل حذف شد ✅", { title: "Storage" });
      setFileDeleteOpen(false);
      setFileCurrent(null);
    },
    onError: (e) => toastError(getErrMsg(e, "خطا در حذف فایل"), { title: "Storage" }),
  });

  // actions
  const refreshAll = async () => {
    closeAllMenus();
    info("در حال بروزرسانی...", { title: "Admin" });
    await Promise.allSettled([
      qUsers.refetch(),
      qFolders.refetch(),
      qFiles.refetch(),
      qSub.refetch(),
    ]);
    success("بروزرسانی شد ✅", { title: "Admin" });
  };

  const currentFolder = selectedFolderId ? folderById.get(String(selectedFolderId)) : null;
  const parentId = currentFolder?.parent ? String(currentFolder.parent) : null;

  const openEditUser = (u) => {
    closeAllMenus();
    setUserCurrent(u);
    setUserDraft({
      username: u?.username || "",
      email: u?.email || "",
      phone: u?.phone || "",
      full_name: u?.full_name || "",
      is_active: !!u?.is_active,
      storage_limit:
        u?.storage_limit == null || u?.storage_limit === "" ? "" : String(u.storage_limit),
    });
    setUserEditOpen(true);
  };

  const openDeleteUser = (u) => {
    closeAllMenus();
    setUserCurrent(u);
    setUserDeleteOpen(true);
  };

  const submitUserPatch = () => {
    if (!userCurrent?.id) return;

    const payload = {};
    const username = String(userDraft.username || "").trim();
    const email = String(userDraft.email || "").trim();
    const phone = String(userDraft.phone || "").trim();
    const full_name = String(userDraft.full_name || "").trim();

    if (username) payload.username = username;
    if (email) payload.email = email;
    payload.phone = phone || null;
    payload.full_name = full_name || "";
    payload.is_active = !!userDraft.is_active;

    if (String(userDraft.storage_limit || "").trim() !== "") {
      const n = Number(String(userDraft.storage_limit).trim());
      if (!Number.isFinite(n) || n < 0) {
        return toastError("storage_limit باید عدد معتبر باشد.", { title: "Users" });
      }
      payload.storage_limit = n;
    }

    info("در حال ذخیره...", { title: "Users" });
    mutPatchUser.mutate({ user_id: userCurrent.id, payload });
  };

  return (
    <PageShell title="مدیریت کاربران و فایل‌ها">
      <div className="w-full dark:text-white">
        {/* header */}
        <div className={cn(CARD, "p-3 sm:p-4 mb-4 !bg-[#A1E3F910] dark:!bg-[#A1E3F910]")}>
          <div className="flex flex-col lg:flex-row gap-3 lg:items-center lg:justify-between">
            <div className="min-w-0">
              <h1 className="text-lg sm:text-xl font-extrabold inline-flex items-center gap-2">
                <TbUsers className="w-5 h-5 opacity-80" />
                مدیریت کاربران
              </h1>
              <p className="text-xs sm:text-sm text-black/60 dark:text-white/70 truncate">
                مدیریت کاربران و استوریج
              </p>
            </div>

            <div className="flex items-center gap-2 w-full lg:w-auto">
              <button
                type="button"
                onPointerDown={(e) => {
                  e.preventDefault();
                  e.stopPropagation();
                }}
                onClick={(e) => {
                  e.preventDefault();
                  e.stopPropagation();
                  refreshAll();
                }}
                disabled={
                  qUsers.isFetching || qFolders.isFetching || qFiles.isFetching || qSub.isFetching
                }
                className="flex-1 sm:flex-none px-4 py-2 rounded-xl shadow bg-white dark:bg-[#16325b]
                          border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10
                          text-sm inline-flex items-center justify-center gap-2 transition disabled:opacity-60"
              >
                <TbRefresh
                  className={cn(
                    "w-4 h-4 text-[#43BEFF] dark:text-white",
                    qUsers.isFetching || qFolders.isFetching || qFiles.isFetching || qSub.isFetching
                      ? "animate-spin"
                      : ""
                  )}
                />
                بروزرسانی
              </button>
            </div>
          </div>

          {qUsers.error || qFolders.error || qFiles.error || qSub.error ? (
            <div className={cn("mt-3 rounded-2xl border border-amber-500/25 bg-amber-500/10 p-3")}>
              <div className="flex items-start gap-2">
                <TbAlertTriangle className="w-5 h-5 mt-0.5" />
                <div className="text-sm">
                  <div className="font-extrabold">یک خطا در دریافت داده‌ها رخ داد</div>
                  <div className="text-xs opacity-80 mt-1">
                    {getErrMsg(qUsers.error || qFolders.error || qFiles.error || qSub.error)}
                  </div>
                </div>
              </div>
            </div>
          ) : null}
        </div>

        {/* layout */}
        <div className="grid lg:grid-cols-[380px_1fr] grid-cols-1 gap-4">
          {/* USERS */}
          <div className={cn(CARD, "p-3 sm:p-4 h-fit")} onPointerDown={(e) => e.stopPropagation()}>
            <div className="flex items-center justify-between">
              <div className="text-sm font-extrabold inline-flex items-center gap-2">
                <TbUser className="w-5 h-5 opacity-80" />
                کاربران
              </div>
              <Badge tone="info">
                تعداد: <b className="font-extrabold">{toFa(users.length)}</b>
              </Badge>
            </div>

            <div className="mt-3 flex flex-col gap-2">
              <div className={cn(INPUT_BASE)}>
                <div className="absolute right-3 top-1/2 -translate-y-1/2 opacity-70">
                  <TbSearch className="w-5 h-5" />
                </div>
                <input
                  className={cn(INPUT, "pr-11")}
                  placeholder="جستجوی کاربر (email/phone/username...)"
                  value={uq}
                  onChange={(e) => setUq(e.target.value)}
                />
              </div>

              <DropdownPortal
                id="user-active-filter"
                menu={ddMenu}
                setMenu={setDdMenu}
                label="وضعیت"
                value={uActive}
                options={activeOptions}
                onChange={(v) => setUActive(v)}
                width={220}
              />
            </div>

            <div className="mt-4 space-y-2 h-[70vh] overflow-auto pr-1">
              {qUsers.isLoading ? (
                [...Array(6)].map((_, i) => (
                  <div key={i} className={cn(SOFT, "p-3 animate-pulse")}>
                    <div className="h-5 w-40 rounded bg-black/5 dark:bg-white/10" />
                    <div className="mt-2 h-4 w-56 rounded bg-black/5 dark:bg-white/10" />
                  </div>
                ))
              ) : users.length === 0 ? (
                <div className="py-10 text-center text-black/50 dark:text-white/60">
                  کاربری یافت نشد.
                </div>
              ) : (
                users.map((u) => {
                  const active = !!u?.is_active;
                  const isSel = selectedUser?.id === u.id;

                  return (
                    <div
                      key={u.id}
                      className={cn(
                        "w-full rounded-2xl p-3 border transition",
                        "max-w-full overflow-hidden",
                        isSel
                          ? "border-[#43BEFF60] bg-[#43BEFF10]"
                          : "border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10"
                      )}
                    >
                      <div className="flex items-start justify-between gap-2">
                        <button
                          type="button"
                          className="min-w-0 text-right flex-1"
                          onClick={() => {
                            closeAllMenus();
                            setSelectedUser(u);
                            setSelectedFolderId(null);
                            setFq("");
                            setFileQ("");
                          }}
                        >
                          <div className="font-extrabold truncate">
                            {u.username || `User #${u.id}`}
                          </div>
                          <div className="mt-1 text-[11px] text-black/55 dark:text-white/60 truncate">
                            {u.email || "—"} • {u.phone || "—"}
                          </div>
                          <div className="mt-1 text-[11px] text-black/50 dark:text-white/60">
                            joined: <span className="font-mono">{fmtDate(u.date_joined)}</span>
                          </div>
                        </button>

                        <div className="flex flex-col items-end gap-2 shrink-0">
                          <div className="flex items-center gap-2">
                            <Badge tone={active ? "success" : "danger"}>
                              {active ? <TbCheck className="w-4 h-4" /> : <TbX className="w-4 h-4" />}
                              {active ? "فعال" : "غیرفعال"}
                            </Badge>

                            <ActionMenuDots
                              id={`user-actions-${String(u.id)}`}
                              menu={actionMenu}
                              setMenu={setActionMenu}
                              items={[
                                {
                                  label: "ویرایش",
                                  icon: <TbPencil className="w-4 h-4" />,
                                  onClick: () => openEditUser(u),
                                },
                                {
                                  label: "حذف",
                                  icon: <TbTrash className="w-4 h-4" />,
                                  danger: true,
                                  onClick: () => openDeleteUser(u),
                                },
                              ]}
                            />
                          </div>
                        </div>
                      </div>

                      <div className="mt-2 flex items-center justify-between text-[11px] text-black/55 dark:text-white/60">
                        <span className="truncate">
                          used: <b>{bytesToHuman(u.storage_used)}</b>
                        </span>
                        <span className="truncate">
                          limit: <b>{bytesToHuman(u.storage_limit)}</b>
                        </span>
                      </div>
                    </div>
                  );
                })
              )}
            </div>
          </div>

          {/* STORAGE */}
          <div className={cn(CARD, "p-3 sm:p-4 min-w-0")}>
            <div className="flex flex-col md:flex-row md:items-center md:justify-between gap-2">
              <div className="min-w-0">
                <div className="text-sm font-extrabold inline-flex items-center gap-2">
                  <TbFolder className="w-5 h-5 opacity-80" />
                  استوریج کاربر
                </div>
                <div className="text-xs text-black/55 dark:text-white/60 truncate mt-1">
                  کاربر انتخاب‌شده:{" "}
                  <b className="text-black dark:text-white">
                    {selectedUser ? `${selectedUser.username} (id:${selectedUser.id})` : "—"}
                  </b>
                </div>

                <div className="mt-2 flex flex-wrap items-center gap-2">
                  {ownerId ? (
                    selectedUserActiveSub ? (
                      <>
                        <Badge tone="info">
                          اشتراک:{" "}
                          <b className="font-extrabold">
                            {selectedUserActiveSub.plan_name || "PLAN"}
                          </b>{" "}
                          • Active
                        </Badge>
                        <span className="text-[11px] text-black/50 dark:text-white/60">
                          شروع:{" "}
                          <span className="font-mono">{fmtDate(selectedUserActiveSub.started_at)}</span>
                          {selectedUserActiveSub.ends_at ? (
                            <>
                              {" "}
                              • پایان:{" "}
                              <span className="font-mono">{fmtDate(selectedUserActiveSub.ends_at)}</span>
                            </>
                          ) : (
                            <>
                              {" "}
                              • پایان: <span className="font-mono">—</span>
                            </>
                          )}
                        </span>
                      </>
                    ) : qSub.isFetching ? (
                      <Badge tone="default">
                        <TbRefresh className="w-4 h-4 animate-spin" />
                        در حال بررسی اشتراک...
                      </Badge>
                    ) : (
                      <Badge tone="warn">اشتراک فعال ندارد</Badge>
                    )
                  ) : null}
                </div>
              </div>

              <div className="flex items-center gap-2 flex-wrap">
                <Badge tone="info">
                  پوشه‌ها: <b className="font-extrabold">{toFa(currentChildrenFolders.length)}</b>
                </Badge>
                <Badge tone="info">
                  فایل‌ها: <b className="font-extrabold">{toFa(files.length)}</b>
                </Badge>
              </div>
            </div>

            {/* breadcrumb */}
            <div className={cn(SOFT, "mt-4 p-3 overflow-x-auto")}>
              <div className="min-w-max flex items-center gap-2 text-sm">
                <button
                  type="button"
                  onClick={() => {
                    closeAllMenus();
                    setSelectedFolderId(null);
                  }}
                  className={cn(
                    "inline-flex items-center gap-2 px-3 py-2 rounded-xl border",
                    "border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 transition"
                  )}
                >
                  <TbHome className="w-5 h-5 text-[#43BEFF] dark:text-white" />
                  ریشه
                </button>

                {breadcrumb.map((f, idx) => (
                  <div key={String(f.id)} className="inline-flex items-center gap-2">
                    <TbChevronLeft className="w-4 h-4 opacity-60" />
                    <button
                      type="button"
                      onClick={() => {
                        closeAllMenus();
                        setSelectedFolderId(f.id);
                      }}
                      className={cn(
                        "px-3 py-2 rounded-xl border border-black/10 dark:border-white/10",
                        "hover:bg-black/5 dark:hover:bg-white/10 transition",
                        idx === breadcrumb.length - 1 ? "bg-[#43BEFF10] border-[#43BEFF60]" : ""
                      )}
                    >
                      <span className="font-extrabold">{f.name || "-"}</span>
                    </button>
                  </div>
                ))}
              </div>

              {selectedFolderId ? (
                <div className="mt-2 text-[11px] text-black/50 dark:text-white/60">
                  folder_id: <span className="font-mono">{String(selectedFolderId)}</span>
                </div>
              ) : (
                <div className="mt-2 text-[11px] text-black/50 dark:text-white/60">
                  در حال نمایش فولدرهای سطح اول
                </div>
              )}
            </div>

            <div className="mt-4 grid gap-4 min-w-0">
              {/* folders */}
              <div className={cn(SOFT, "p-3 min-w-0")}>
                <div className="flex items-center justify-between gap-2">
                  <div className="font-extrabold text-sm inline-flex items-center gap-2 min-w-0">
                    <TbFolder className="w-5 h-5 opacity-80" />
                    <span className="truncate">پوشه‌های داخل فولدر انتخاب‌شده</span>
                  </div>

                  {selectedFolderId ? (
                    <button
                      type="button"
                      onClick={() => {
                        closeAllMenus();
                        setSelectedFolderId(parentId || null);
                      }}
                      className={cn(
                        "px-3 py-2 rounded-xl border border-black/10 dark:border-white/10",
                        "hover:bg-black/5 dark:hover:bg-white/10 transition text-sm inline-flex items-center gap-2"
                      )}
                    >
                      <TbChevronLeft className="w-4 h-4" />
                      بازگشت
                    </button>
                  ) : null}
                </div>

                <div className="mt-3">
                  <div className={cn(INPUT_BASE)}>
                    <div className="absolute right-3 top-1/2 -translate-y-1/2 opacity-70">
                      <TbSearch className="w-5 h-5" />
                    </div>
                    <input
                      className={cn(INPUT, "pr-11")}
                      placeholder="جستجوی فولدرها (کل فولدرهای کاربر)"
                      value={fq}
                      onChange={(e) => setFq(e.target.value)}
                    />
                  </div>
                </div>

                <div className="mt-3 space-y-2 max-h-[520px] overflow-auto pr-1">
                  {qFolders.isLoading ? (
                    [...Array(6)].map((_, i) => (
                      <div
                        key={i}
                        className={cn(
                          "rounded-2xl border border-black/10 dark:border-white/10 p-3 animate-pulse"
                        )}
                      >
                        <div className="h-5 w-44 rounded bg-black/5 dark:bg-white/10" />
                        <div className="mt-2 h-4 w-56 rounded bg-black/5 dark:bg-white/10" />
                      </div>
                    ))
                  ) : currentChildrenFolders.length === 0 ? (
                    <div className="py-10 text-center text-black/50 dark:text-white/60">
                      پوشه‌ای داخل این مسیر وجود ندارد.
                    </div>
                  ) : (
                    currentChildrenFolders.map((f) => (
                      <div
                        key={String(f.id)}
                        className={cn(
                          "rounded-2xl border p-3 transition",
                          "border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10"
                        )}
                      >
                        <div className="flex items-start justify-between gap-2">
                          <button
                            type="button"
                            className="min-w-0 text-right flex-1"
                            onClick={() => {
                              closeAllMenus();
                              setSelectedFolderId(f.id);
                            }}
                          >
                            <div className="font-extrabold truncate">{f.name || "-"}</div>
                            <div className="mt-1 text-[11px] text-black/50 dark:text-white/60 truncate">
                              id: <span className="font-mono">{String(f.id)}</span>
                            </div>
                            <div className="mt-1 text-[11px] text-black/50 dark:text-white/60">
                              created: <span className="font-mono">{fmtDate(f.created_at)}</span>
                            </div>
                          </button>

                          <div className="shrink-0">
                            <ActionMenuDots
                              id={`folder-actions-${String(f.id)}`}
                              menu={actionMenu}
                              setMenu={setActionMenu}
                              items={[
                                {
                                  label: "تغییر نام",
                                  icon: <TbPencil className="w-4 h-4" />,
                                  onClick: () => {
                                    closeAllMenus();
                                    setFolderCurrent(f);
                                    setFolderDraftName(f?.name || "");
                                    setFolderRenameOpen(true);
                                  },
                                },
                                {
                                  label: "حذف",
                                  icon: <TbTrash className="w-4 h-4" />,
                                  danger: true,
                                  onClick: () => {
                                    closeAllMenus();
                                    setFolderCurrent(f);
                                    setFolderDeleteOpen(true);
                                  },
                                },
                              ]}
                            />
                          </div>
                        </div>
                      </div>
                    ))
                  )}
                </div>
              </div>

              {/* files */}
              <div className={cn(SOFT, "p-3 min-w-0")}>
                <div className="flex flex-col md:flex-row md:items-center md:justify-between gap-2">
                  <div className="font-extrabold flex flex-wrap justify-between text-sm items-center gap-2 min-w-0">
                    <div className="w-fit flex items-center gap-2">
                      <TbFile className="w-5 h-5 opacity-80" />
                      <span className="truncate">فایل‌ها</span>
                    </div>
                    {selectedFolderId ? (
                      <span className="text-[11px] font-bold opacity-70 inline-flex items-center gap-1 truncate">
                        folder: <span className="font-mono">{String(selectedFolderId)}</span>
                      </span>
                    ) : null}
                  </div>
                </div>

                <div className="mt-3">
                  <div className={cn(INPUT_BASE)}>
                    <div className="absolute right-3 top-1/2 -translate-y-1/2 opacity-70">
                      <TbSearch className="w-5 h-5" />
                    </div>
                    <input
                      className={cn(INPUT, "pr-11")}
                      placeholder="جستجوی فایل‌ها (name...)"
                      value={fileQ}
                      onChange={(e) => setFileQ(e.target.value)}
                    />
                  </div>
                </div>

                <div className="mt-3">
                  {qFiles.isLoading ? (
                    <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-2 2xl:grid-cols-3 gap-3">
                      {[...Array(8)].map((_, i) => (
                        <div
                          key={i}
                          className={cn(
                            "rounded-2xl border border-black/10 dark:border-white/10 p-3 animate-pulse",
                            "bg-white/60 dark:bg-white/5"
                          )}
                        >
                          <div className="flex items-start justify-between gap-2">
                            <div className="h-10 w-10 rounded-2xl bg-black/5 dark:bg-white/10" />
                            <div className="h-9 w-9 rounded-xl bg-black/5 dark:bg-white/10" />
                          </div>
                          <div className="mt-3 h-5 w-44 rounded bg-black/5 dark:bg-white/10" />
                          <div className="mt-2 h-4 w-56 rounded bg-black/5 dark:bg-white/10" />
                          <div className="mt-2 h-4 w-40 rounded bg-black/5 dark:bg-white/10" />
                        </div>
                      ))}
                    </div>
                  ) : files.length === 0 ? (
                    <div className="py-10 text-center text-black/50 dark:text-white/60">
                      فایلی برای نمایش وجود ندارد.
                    </div>
                  ) : (
                    <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-2 2xl:grid-cols-3 gap-3 h-[500px] overflow-y-scroll">
                      {files.map((f) => {
                        const type = guessTypeBadge(f?.name);
                        const status = f.in_trash
                          ? { tone: "warn", label: "Trash" }
                          : f.is_deleted
                          ? { tone: "danger", label: "Deleted" }
                          : { tone: "success", label: "OK" };

                        return (
                          <div
                            key={String(f.id)}
                            className={cn(
                              "rounded-2xl border border-black/10 dark:border-white/10 p-3",
                              "bg-white/70 dark:bg-white/5 hover:bg-black/5 dark:hover:bg-white/10 transition",
                              "min-w-0"
                            )}
                          >
                            <div className="flex items-start justify-between gap-2">
                              <div className="h-10 w-10 rounded-2xl grid place-items-center border border-black/10 dark:border-white/10 bg-[#43BEFF14]">
                                <TbFile className="w-5 h-5 text-[#146E85] dark:text-[#A1E3F9]" />
                              </div>

                              <ActionMenuDots
                                id={`file-actions-${String(f.id)}`}
                                menu={actionMenu}
                                setMenu={setActionMenu}
                                items={[
                                  {
                                    label: "تغییر نام / جابجایی",
                                    icon: <TbPencil className="w-4 h-4" />,
                                    onClick: () => {
                                      closeAllMenus();
                                      setFileCurrent(f);
                                      setFileDraft({
                                        name: f?.name || "",
                                        folder: f?.folder ?? null,
                                      });
                                      setFileRenameOpen(true);
                                    },
                                  },
                                  {
                                    label: "حذف",
                                    icon: <TbTrash className="w-4 h-4" />,
                                    danger: true,
                                    onClick: () => {
                                      closeAllMenus();
                                      setFileCurrent(f);
                                      setFileDeleteOpen(true);
                                    },
                                  },
                                ]}
                              />
                            </div>

                            <div className="mt-3 min-w-0">
                              <div className="font-extrabold text-black dark:text-white truncate">
                                {f.name || "-"}
                              </div>

                              <div className="mt-2 flex items-center gap-2 flex-wrap">
                                <Badge tone={type.tone}>{type.label}</Badge>
                                <Badge tone={status.tone}>{status.label}</Badge>
                              </div>

                              <div className="mt-2 text-[11px] text-black/55 dark:text-white/60 truncate">
                                id: <span className="font-mono">{String(f.id)}</span>
                              </div>
                              <div className="mt-1 text-[11px] text-black/50 dark:text-white/60 truncate">
                                folder:{" "}
                                <span className="font-mono">{f.folder ? String(f.folder) : "—"}</span>
                              </div>

                              <div className="mt-2 text-[11px] text-black/50 dark:text-white/60">
                                created: <span className="font-mono">{fmtDate(f.created_at)}</span>
                              </div>
                              <div className="mt-1 text-[11px] text-black/50 dark:text-white/60">
                                updated: <span className="font-mono">{fmtDate(f.updated_at)}</span>
                              </div>
                            </div>
                          </div>
                        );
                      })}
                    </div>
                  )}
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* ---------------- USER EDIT MODAL ---------------- */}
        <Modal
          open={userEditOpen}
          title={`ویرایش کاربر: ${userCurrent?.username || "-"}`}
          onClose={() => !mutPatchUser.isPending && setUserEditOpen(false)}
          widthClass="max-w-2xl"
        >
          <div className="space-y-4">
            <div className="grid md:grid-cols-2 gap-3">
              <Field label="username">
                <div className={INPUT_BASE}>
                  <input
                    className={INPUT}
                    value={userDraft.username}
                    onChange={(e) => setUserDraft((p) => ({ ...p, username: e.target.value }))}
                  />
                </div>
              </Field>

              <Field label="email">
                <div className={INPUT_BASE}>
                  <input
                    className={INPUT}
                    value={userDraft.email}
                    onChange={(e) => setUserDraft((p) => ({ ...p, email: e.target.value }))}
                  />
                </div>
              </Field>

              <Field label="phone">
                <div className={INPUT_BASE}>
                  <input
                    className={INPUT}
                    value={userDraft.phone}
                    onChange={(e) => setUserDraft((p) => ({ ...p, phone: e.target.value }))}
                  />
                </div>
              </Field>

              <Field label="full_name">
                <div className={INPUT_BASE}>
                  <input
                    className={INPUT}
                    value={userDraft.full_name}
                    onChange={(e) => setUserDraft((p) => ({ ...p, full_name: e.target.value }))}
                  />
                </div>
              </Field>

              <Field label="is_active">
                <div className={cn(SOFT, "p-2 flex items-center justify-between")}>
                  <span className="text-xs text-black/60 dark:text-white/70">وضعیت کاربر</span>
                  <button
                    type="button"
                    onClick={() => setUserDraft((p) => ({ ...p, is_active: !p.is_active }))}
                    className={cn(
                      "px-3 py-2 rounded-xl border border-black/10 dark:border-white/10 transition text-xs",
                      userDraft.is_active
                        ? "bg-emerald-500/10 border-emerald-500/25 text-emerald-700 dark:text-emerald-200"
                        : "bg-red-500/10 border-red-500/25 text-red-700 dark:text-red-200"
                    )}
                  >
                    {userDraft.is_active ? "فعال" : "غیرفعال"}
                  </button>
                </div>
              </Field>

              <Field label="storage_limit" hint="به بایت. اگر خالی باشد ارسال نمی‌شود (بدون تغییر).">
                <div className={INPUT_BASE}>
                  <input
                    className={INPUT}
                    value={userDraft.storage_limit}
                    onChange={(e) => setUserDraft((p) => ({ ...p, storage_limit: e.target.value }))}
                    placeholder="مثال: 10737418240"
                  />
                </div>
              </Field>
            </div>

            <div className="flex flex-col sm:flex-row gap-2 sm:justify-end">
              <button
                type="button"
                onClick={() => {
                  setUserEditOpen(false);
                  setUserCurrent(null);
                }}
                disabled={mutPatchUser.isPending}
                className="px-4 py-2 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 transition disabled:opacity-60"
              >
                انصراف
              </button>

              <button
                type="button"
                onClick={submitUserPatch}
                disabled={mutPatchUser.isPending || !userCurrent?.id}
                className="px-4 py-2 rounded-xl shadow border border-black/10 dark:border-white/10 bg-white dark:bg-[#16325b]
                           hover:bg-black/5 dark:hover:bg-white/10 transition inline-flex items-center justify-center gap-2 disabled:opacity-60"
              >
                {mutPatchUser.isPending ? (
                  <>
                    <TbRefresh className="w-4 h-4 animate-spin text-[#43BEFF] dark:text-white" />
                    درحال ذخیره...
                  </>
                ) : (
                  <>
                    <TbCheck className="w-4 h-4 text-[#43BEFF] dark:text-white" />
                    ذخیره تغییرات
                  </>
                )}
              </button>
            </div>
          </div>
        </Modal>

        {/* ---------------- USER DELETE MODAL ---------------- */}
        <Modal
          open={userDeleteOpen}
          title="حذف کاربر"
          onClose={() => !mutDeleteUser.isPending && setUserDeleteOpen(false)}
          widthClass="max-w-xl"
        >
          <div className="space-y-3">
            <div className={cn(SOFT, "p-4")}>
              <div className="text-sm font-extrabold text-black dark:text-white">
                مطمئنی می‌خوای این کاربر حذف بشه؟
              </div>
              <div className="mt-2 text-xs text-black/55 dark:text-white/60">
                <div>
                  username: <b>{userCurrent?.username || "—"}</b>
                </div>
                <div>
                  email: <b>{userCurrent?.email || "—"}</b>
                </div>
                <div>
                  id: <span className="font-mono">{String(userCurrent?.id || "-")}</span>
                </div>
                <div className="mt-1">این کار برگشت‌پذیر نیست.</div>
              </div>
            </div>

            <div className="flex flex-col sm:flex-row gap-2 sm:justify-end">
              <button
                type="button"
                onClick={() => {
                  setUserDeleteOpen(false);
                  setUserCurrent(null);
                }}
                disabled={mutDeleteUser.isPending}
                className="px-4 py-2 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 transition disabled:opacity-60"
              >
                انصراف
              </button>

              <button
                type="button"
                disabled={mutDeleteUser.isPending || !userCurrent?.id}
                onClick={() => {
                  if (!userCurrent?.id) return;
                  info("در حال حذف...", { title: "Users" });
                  mutDeleteUser.mutate(userCurrent.id);
                }}
                className="px-4 py-2 rounded-xl shadow border border-red-500/25 bg-red-500/10 hover:bg-red-500/15 transition text-red-700 dark:text-red-200 inline-flex items-center justify-center gap-2 disabled:opacity-60"
              >
                <TbTrash className="w-4 h-4" />
                {mutDeleteUser.isPending ? "درحال حذف..." : "حذف کاربر"}
              </button>
            </div>
          </div>
        </Modal>

        {/* -------- Folder Modals -------- */}
        <Modal
          open={folderRenameOpen}
          title={`تغییر نام فولدر: ${folderCurrent?.name || "-"}`}
          onClose={() => {
            setFolderRenameOpen(false);
            setFolderCurrent(null);
          }}
          widthClass="max-w-xl"
        >
          <div className="space-y-3">
            <Field label="نام جدید">
              <div className={INPUT_BASE}>
                <input
                  className={INPUT}
                  value={folderDraftName}
                  onChange={(e) => setFolderDraftName(e.target.value)}
                />
              </div>
            </Field>

            <div className="flex flex-col sm:flex-row gap-2 sm:justify-end">
              <button
                type="button"
                onClick={() => {
                  setFolderRenameOpen(false);
                  setFolderCurrent(null);
                }}
                className="px-4 py-2 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 transition"
              >
                انصراف
              </button>

              <button
                type="button"
                disabled={mutRenameFolder.isPending}
                onClick={() => {
                  if (!folderCurrent?.id) return;
                  const name = folderDraftName.trim();
                  if (!name) return toastError("نام فولدر الزامی است.", { title: "Storage" });
                  mutRenameFolder.mutate({ folder_id: folderCurrent.id, payload: { name } });
                }}
                className="px-4 py-2 rounded-xl shadow border border-black/10 dark:border-white/10 bg-white dark:bg-[#16325b]
                           hover:bg-black/5 dark:hover:bg-white/10 transition inline-flex items-center justify-center gap-2 disabled:opacity-60"
              >
                {mutRenameFolder.isPending ? (
                  <>
                    <TbRefresh className="w-4 h-4 animate-spin text-[#43BEFF] dark:text-white" />
                    درحال ذخیره...
                  </>
                ) : (
                  <>
                    <TbCheck className="w-4 h-4 text-[#43BEFF] dark:text-white" />
                    ذخیره
                  </>
                )}
              </button>
            </div>
          </div>
        </Modal>

        <Modal
          open={folderDeleteOpen}
          title="حذف فولدر"
          onClose={() => {
            setFolderDeleteOpen(false);
            setFolderCurrent(null);
          }}
          widthClass="max-w-xl"
        >
          <div className="space-y-3">
            <div className={cn(SOFT, "p-4")}>
              <div className="text-sm font-extrabold text-black dark:text-white">
                مطمئنی می‌خوای این فولدر حذف بشه؟
              </div>
              <div className="mt-2 text-xs text-black/55 dark:text-white/60">
                <div>
                  نام: <b>{folderCurrent?.name}</b>
                </div>
                <div>
                  id: <span className="font-mono">{String(folderCurrent?.id || "-")}</span>
                </div>
                <div className="mt-1">این کار برگشت‌پذیر نیست.</div>
              </div>
            </div>

            <div className="flex flex-col sm:flex-row gap-2 sm:justify-end">
              <button
                type="button"
                onClick={() => {
                  setFolderDeleteOpen(false);
                  setFolderCurrent(null);
                }}
                className="px-4 py-2 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 transition"
              >
                انصراف
              </button>

              <button
                type="button"
                disabled={mutDeleteFolder.isPending}
                onClick={() => {
                  if (!folderCurrent?.id) return;
                  mutDeleteFolder.mutate(folderCurrent.id);
                }}
                className="px-4 py-2 rounded-xl shadow border border-red-500/25 bg-red-500/10 hover:bg-red-500/15 transition text-red-700 dark:text-red-200 inline-flex items-center justify-center gap-2 disabled:opacity-60"
              >
                <TbTrash className="w-4 h-4" />
                {mutDeleteFolder.isPending ? "درحال حذف..." : "حذف"}
              </button>
            </div>
          </div>
        </Modal>

        {/* -------- File Modals -------- */}
        <Modal
          open={fileRenameOpen}
          title={`تغییر فایل: ${fileCurrent?.name || "-"}`}
          onClose={() => {
            setFileRenameOpen(false);
            setFileCurrent(null);
          }}
          widthClass="max-w-2xl"
        >
          <div className="space-y-4">
            <div className="grid md:grid-cols-2 gap-3">
              <Field label="Name جدید">
                <div className={INPUT_BASE}>
                  <input
                    className={INPUT}
                    value={fileDraft.name}
                    onChange={(e) => setFileDraft((p) => ({ ...p, name: e.target.value }))}
                  />
                </div>
              </Field>

              <Field label="Folder جدید (اختیاری)" hint="برای Move کردن فایل">
                <div className={INPUT_BASE}>
                  <input
                    className={INPUT}
                    value={fileDraft.folder ?? ""}
                    onChange={(e) => setFileDraft((p) => ({ ...p, folder: e.target.value || null }))}
                    placeholder="folder uuid یا خالی برای null"
                  />
                </div>
              </Field>
            </div>

            <div className="flex flex-col sm:flex-row gap-2 sm:justify-end">
              <button
                type="button"
                onClick={() => {
                  setFileRenameOpen(false);
                  setFileCurrent(null);
                }}
                className="px-4 py-2 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 transition"
              >
                انصراف
              </button>

              <button
                type="button"
                disabled={mutRenameFile.isPending}
                onClick={() => {
                  if (!fileCurrent?.id) return;
                  const name = String(fileDraft.name || "").trim();
                  if (!name) return toastError("نام فایل الزامی است.", { title: "Storage" });

                  mutRenameFile.mutate({
                    entry_id: fileCurrent.id,
                    payload: { name, folder: fileDraft.folder || null },
                  });
                }}
                className="px-4 py-2 rounded-xl shadow border border-black/10 dark:border-white/10 bg-white dark:bg-[#16325b]
                           hover:bg-black/5 dark:hover:bg-white/10 transition inline-flex items-center justify-center gap-2 disabled:opacity-60"
              >
                {mutRenameFile.isPending ? (
                  <>
                    <TbRefresh className="w-4 h-4 animate-spin text-[#43BEFF] dark:text-white" />
                    درحال ذخیره...
                  </>
                ) : (
                  <>
                    <TbCheck className="w-4 h-4 text-[#43BEFF] dark:text-white" />
                    ذخیره
                  </>
                )}
              </button>
            </div>
          </div>
        </Modal>

        <Modal
          open={fileDeleteOpen}
          title="حذف فایل"
          onClose={() => {
            setFileDeleteOpen(false);
            setFileCurrent(null);
          }}
          widthClass="max-w-xl"
        >
          <div className="space-y-3">
            <div className={cn(SOFT, "p-4")}>
              <div className="text-sm font-extrabold text-black dark:text-white">
                مطمئنی می‌خوای این فایل حذف بشه؟
              </div>
              <div className="mt-2 text-xs text-black/55 dark:text-white/60">
                <div>
                  نام: <b>{fileCurrent?.name}</b>
                </div>
                <div>
                  id: <span className="font-mono">{String(fileCurrent?.id || "-")}</span>
                </div>
                <div className="mt-1">این کار برگشت‌پذیر نیست.</div>
              </div>
            </div>

            <div className="flex flex-col sm:flex-row gap-2 sm:justify-end">
              <button
                type="button"
                onClick={() => {
                  setFileDeleteOpen(false);
                  setFileCurrent(null);
                }}
                className="px-4 py-2 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 transition"
              >
                انصراف
              </button>

              <button
                type="button"
                disabled={mutDeleteFile.isPending}
                onClick={() => {
                  if (!fileCurrent?.id) return;
                  mutDeleteFile.mutate(fileCurrent.id);
                }}
                className="px-4 py-2 rounded-xl shadow border border-red-500/25 bg-red-500/10 hover:bg-red-500/15 transition text-red-700 dark:text-red-200 inline-flex items-center justify-center gap-2 disabled:opacity-60"
              >
                <TbTrash className="w-4 h-4" />
                {mutDeleteFile.isPending ? "درحال حذف..." : "حذف"}
              </button>
            </div>
          </div>
        </Modal>
      </div>
    </PageShell>
  );
}
