import React, { useCallback, useEffect, useMemo, useState } from "react";
import { Axiosinstance } from "../services/auth/Axiosinstance";
import { useToast } from "../components/ToastProvider";

import { IoGrid, IoList, IoFolderOpen, IoEllipsisVertical } from "react-icons/io5";
import { TbPlus } from "react-icons/tb";

import ActionMenuPortal from "../components/storage/ActionMenuPortal";
import FilesList from "../components/storage/FilesList";
import FilesGrid from "../components/storage/FilesGrid";

import RenameModal from "../components/storage/RenameModal";
import MoveModal from "../components/storage/MoveModal";
import DetailsModal from "../components/storage/DetailsModal";
import ShareModal from "../components/storage/ShareModal";
import ColorPickerModal from "../components/storage/ColorPickerModal";
import ZipModal from "../components/storage/ZipModal";

import BreadcrumbBar from "../components/storage/BreadcrumbBar";
import { FileMenu, FolderMenu } from "../components/storage/ItemMenus";

import { useStorageColors } from "../hooks/useStorageColors";
import { useStorageItemsTree } from "../hooks/useStorageItemsTree";

import { flattenFolderTree, getFolderId, getFileId } from "../utils/storage";
import PaginationControls from "../components/storage/PaginationControls";

/* ---------------- session helpers ---------------- */
const SESSION_PAGE_SIZE_KEY = "storage.pageSize";
const readSessionInt = (key, fallback) => {
  try {
    const raw = sessionStorage.getItem(key);
    const n = Number.parseInt(raw, 10);
    return Number.isFinite(n) ? n : fallback;
  } catch {
    return fallback;
  }
};
const clampInt = (v, min, max) => {
  const n = Number.parseInt(String(v || ""), 10);
  if (!Number.isFinite(n)) return min;
  return Math.max(min, Math.min(max, n));
};

const getFriendlyError = (err, fallback = "عملیات ناموفق بود.") => {
  const d = err?.response?.data;
  if (!d) return fallback;
  if (typeof d === "string") return d;
  if (typeof d?.detail === "string") return d.detail;
  if (typeof d?.message === "string") return d.message;
  const firstKey = d && typeof d === "object" ? Object.keys(d)[0] : null;
  if (firstKey) {
    const v = d[firstKey];
    if (Array.isArray(v) && v[0]) return String(v[0]);
    if (typeof v === "string") return v;
  }
  return fallback;
};

/* ---------------- tree helpers ---------------- */
const findFolderByPath = (folders, path) => {
  if (!path || path.length === 0) return null;
  let currentList = folders;
  let current = null;

  for (const id of path) {
    current = currentList.find((f) => String(getFolderId(f)) === String(id)) || null;
    if (!current) return null;
    currentList = current.folders || [];
  }
  return current;
};

const buildBreadcrumb = (folders, path) => {
  const crumbs = [];
  let currentList = folders;

  for (let i = 0; i < (path?.length || 0); i++) {
    const id = path[i];
    const current = currentList.find((f) => String(getFolderId(f)) === String(id));
    if (!current) break;
    crumbs.push({ id: getFolderId(current), name: current.name || "بدون نام" });
    currentList = current.folders || [];
  }

  return crumbs;
};

const paginate = (arr, page, size) => {
  const total = Array.isArray(arr) ? arr.length : 0;
  const totalPages = Math.max(1, Math.ceil(total / size));
  const p = clampInt(page, 1, totalPages);
  const start = (p - 1) * size;
  const end = start + size;
  return { total, totalPages, page: p, items: (arr || []).slice(start, end) };
};

export default function Folder() {
  const toastApi = useToast();

  const toast = useMemo(() => {
    if (toastApi?.success && toastApi?.error) return toastApi;
    if (toastApi?.show) {
      return {
        success: (m) => toastApi.show({ type: "success", message: m }),
        error: (m) => toastApi.show({ type: "error", message: m }),
        info: (m) => toastApi.show({ type: "info", message: m }),
      };
    }
    if (toastApi?.addToast) {
      return {
        success: (m) => toastApi.addToast("success", m),
        error: (m) => toastApi.addToast("error", m),
        info: (m) => toastApi.addToast("info", m),
      };
    }
    return { success: () => {}, error: () => {}, info: () => {} };
  }, [toastApi]);

  /* ===================== Data ===================== */
  const { tree, loading, loadError, requestRefresh } = useStorageItemsTree({
    Axiosinstance,
    toast,
  });

  const { colorsCfg, colorOptions, colorsLoading } = useStorageColors({
    Axiosinstance,
    toast,
  });

  /* ===================== Navigation ===================== */
  const [selectedFolderPath, setSelectedFolderPath] = useState(["root"]);
  const root = tree?.[0] || null;

  const selectedFolder = useMemo(() => (root ? findFolderByPath([root], selectedFolderPath) : null), [root, selectedFolderPath]);

  const visibleFolders = selectedFolder?.folders || [];
  const visibleFiles = selectedFolder?.files || [];

  const breadcrumb = useMemo(() => (root ? buildBreadcrumb([root], selectedFolderPath) : []), [root, selectedFolderPath]);

  const allFoldersFlat = useMemo(() => {
    if (!root) return [];
    return flattenFolderTree(root?.folders || []);
  }, [root]);

  /* ===================== View ===================== */
  const [viewMode, setViewMode] = useState("grid");

  /* ===================== Pagination (folders + files) ===================== */
  const [pageSize, setPageSize] = useState(() => clampInt(readSessionInt(SESSION_PAGE_SIZE_KEY, 8), 1, 200));
  const [foldersPage, setFoldersPage] = useState(1);
  const [filesPage, setFilesPage] = useState(1);

  useEffect(() => {
    // هر بار مسیر پوشه/نمایش/سایز عوض شد برگرد صفحه 1
    setFoldersPage(1);
    setFilesPage(1);
  }, [selectedFolderPath, viewMode, pageSize]);

  const pagedFolders = useMemo(() => paginate(visibleFolders, foldersPage, pageSize), [visibleFolders, foldersPage, pageSize]);

  const pagedFiles = useMemo(() => paginate(visibleFiles, filesPage, pageSize), [visibleFiles, filesPage, pageSize]);

  /* ===================== Portal menus ===================== */
  const [fileMenu, setFileMenu] = useState({ id: null, rect: null });
  const [folderMenu, setFolderMenu] = useState({ id: null, rect: null });
  const closeFileMenu = () => setFileMenu({ id: null, rect: null });
  const closeFolderMenu = () => setFolderMenu({ id: null, rect: null });

  const toggleFileMenu = (id, e) => {
    e.preventDefault();
    e.stopPropagation();
    const rect = e.currentTarget.getBoundingClientRect();
    setFileMenu((prev) => (String(prev.id) === String(id) ? { id: null, rect: null } : { id, rect }));
    setFolderMenu({ id: null, rect: null });
  };

  const toggleFolderMenu = (id, e) => {
    e.preventDefault();
    e.stopPropagation();
    const rect = e.currentTarget.getBoundingClientRect();
    setFolderMenu((prev) => (String(prev.id) === String(id) ? { id: null, rect: null } : { id, rect }));
    setFileMenu({ id: null, rect: null });
  };

  /* ===================== Modals ===================== */
  const [detailsModal, setDetailsModal] = useState({ open: false, type: null, item: null });
  const [renameModal, setRenameModal] = useState({ open: false, type: null, item: null, value: "" });
  const [moveModal, setMoveModal] = useState({ open: false, item: null, target: "root" });

  const [shareModal, setShareModal] = useState({
    open: false,
    file: null,
    data: null,
    downloadLink: "",
    copying: false,
    revoking: false,
    creating: false,
  });

  const [createFolderModal, setCreateFolderModal] = useState({
    open: false,
    parent: "root",
    name: "",
    creating: false,
  });

  const [colorModal, setColorModal] = useState({ open: false, type: null, item: null });

  // ✅ Zip modal
  const [zipModal, setZipModal] = useState({
    open: false,
    items: [],
    name: "",
    folder_id: "root",
    picking: false,
    pickValue: "",
    zipping: false,
  });

  const openDetails = (type, item) => {
    closeFileMenu();
    closeFolderMenu();
    setDetailsModal({ open: true, type, item });
  };

  const openRename = (type, item) => {
    closeFileMenu();
    closeFolderMenu();
    setRenameModal({ open: true, type, item, value: item?.name || "" });
  };

  const openMove = (file) => {
    closeFileMenu();
    closeFolderMenu();
    setMoveModal({ open: true, item: file, target: "root" });
  };

  /* ===================== Zip / Unzip ===================== */
  const openZipModalWith = (seed) => {
    closeFileMenu();
    closeFolderMenu();
    setZipModal((p) => {
      const exists = (p.items || []).some((it) => it.type === seed.type && String(it.id) === String(seed.id));
      const items = exists ? p.items : [seed];
      const suggestedName = seed?.type === "folder" ? `${String(seed?.name || "archive").replaceAll("/", "-")}.zip` : `${String(seed?.name || "archive").replaceAll("/", "-")}.zip`;

      return {
        open: true,
        items,
        name: p.open ? p.name : suggestedName,
        folder_id: p.folder_id || "root",
        picking: false,
        pickValue: "",
        zipping: false,
      };
    });
  };

  const handleCreateArchive = async () => {
    const name = String(zipModal.name || "").trim();
    if (!name) return toast.error("نام فایل زیپ را وارد کنید.");

    const items = Array.isArray(zipModal.items) ? zipModal.items : [];
    const file_ids = items
      .filter((x) => x.type === "file")
      .map((x) => x.id)
      .filter(Boolean);
    const folder_ids = items
      .filter((x) => x.type === "folder")
      .map((x) => x.id)
      .filter(Boolean);

    if (file_ids.length === 0 && folder_ids.length === 0) return toast.error("حداقل یک فایل یا پوشه انتخاب کنید.");

    const folder_id = zipModal.folder_id && zipModal.folder_id !== "root" ? zipModal.folder_id : null;

    try {
      setZipModal((p) => ({ ...p, zipping: true }));
      toast.info("در حال ساخت آرشیو...");

      await Axiosinstance.post("storage/archive/create/", {
        name,
        folder_id,
        file_ids,
        folder_ids,
      });

      toast.success("زیپ ساخته شد ✅");
      setZipModal({
        open: false,
        items: [],
        name: "",
        folder_id: "root",
        picking: false,
        pickValue: "",
        zipping: false,
      });
      await requestRefresh({ silent: true });
    } catch (err) {
      toast.error(getFriendlyError(err, "زیپ کردن ناموفق بود."));
      setZipModal((p) => ({ ...p, zipping: false }));
    }
  };

  const handleExtractZip = async (file, opts = {}) => {
    const id = getFileId(file);
    if (!id) return toast.error("شناسه فایل پیدا نشد.");

    const payload = {
      zip_file_id: id,
      target_folder_id: opts?.target_folder_id ?? null,
      create_subfolder: opts?.create_subfolder ?? true,
      overwrite: opts?.overwrite ?? false,
    };

    try {
      toast.info("در حال Extract ...");
      await Axiosinstance.post("storage/archive/extract/", payload);
      toast.success("انزیپ انجام شد ✅");
      await requestRefresh({ silent: true });
    } catch (err) {
      toast.error(getFriendlyError(err, "انزیپ ناموفق بود."));
    }
  };

  /* ===================== API actions ===================== */
  const handleCreateFolder = async (name, parent) => {
    try {
      const clean = String(name || "").trim();
      if (!clean) return toast.error("نام پوشه را وارد کنید.");

      const payload = parent === "root" ? { name: clean } : { name: clean, parent };
      await Axiosinstance.post("storage/folders/", payload);

      toast.success("پوشه ساخته شد ✅");
      await requestRefresh({ silent: true });
      return true;
    } catch (err) {
      toast.error(getFriendlyError(err, "ساخت پوشه ناموفق بود."));
      return false;
    }
  };

  const handleRenameFile = async (file, name) => {
    try {
      const id = getFileId(file);
      await Axiosinstance.patch(`storage/files/${id}/rename/`, { name });
      toast.success("نام فایل تغییر کرد ✅");
      await requestRefresh({ silent: true });
    } catch (err) {
      toast.error(getFriendlyError(err, "تغییر نام فایل ناموفق بود."));
    }
  };

  const handleRenameFolder = async (folder, name) => {
    try {
      const id = getFolderId(folder);
      await Axiosinstance.patch(`storage/folders/${id}/`, { name });
      toast.success("نام پوشه تغییر کرد ✅");
      await requestRefresh({ silent: true });
    } catch (err) {
      toast.error(getFriendlyError(err, "تغییر نام پوشه ناموفق بود."));
    }
  };

  const handleMoveFile = async (file, destination_folder_id) => {
    try {
      const id = getFileId(file);
      await Axiosinstance.post(`storage/files/${id}/move/`, { destination_folder_id });
      toast.success("فایل منتقل شد ✅");
      await requestRefresh({ silent: true });
    } catch (err) {
      toast.error(getFriendlyError(err, "انتقال فایل ناموفق بود."));
    }
  };

  const handleDownloadFile = async (file) => {
    try {
      const id = getFileId(file);
      const response = await Axiosinstance.get(`storage/files/${id}/download/`, { responseType: "blob" });
      const blobUrl = window.URL.createObjectURL(new Blob([response.data]));
      const link = document.createElement("a");
      link.href = blobUrl;
      link.download = file.name || "file";
      document.body.appendChild(link);
      link.click();
      link.remove();
      window.URL.revokeObjectURL(blobUrl);
      toast.success("دانلود شروع شد ✅");
    } catch (err) {
      toast.error(getFriendlyError(err, "دانلود فایل ناموفق بود."));
    }
  };

  const handleTrashFile = async (file) => {
    try {
      const id = getFileId(file);
      await Axiosinstance.post(`storage/files/${id}/trash/`);
      toast.info("فایل به سطل زباله منتقل شد.");
      await requestRefresh({ silent: true });
    } catch (err) {
      toast.error(getFriendlyError(err, "انتقال به سطل زباله ناموفق بود."));
    }
  };

  const handleRestoreFile = async (file) => {
    try {
      const id = getFileId(file);
      await Axiosinstance.post(`storage/files/${id}/restore/`);
      toast.success("فایل بازیابی شد ✅");
      await requestRefresh({ silent: true });
    } catch (err) {
      toast.error(getFriendlyError(err, "بازگردانی ناموفق بود."));
    }
  };

  const handleHardDeleteFile = async (file) => {
    try {
      const id = getFileId(file);
      await Axiosinstance.delete(`storage/files/${id}/hard-delete/`);
      toast.success("حذف دائمی فایل انجام شد ✅");
      await requestRefresh({ silent: true });
    } catch (err) {
      toast.error(getFriendlyError(err, "حذف دائمی ناموفق بود."));
    }
  };

  const handleStarFile = async (file) => {
    try {
      const id = getFileId(file);
      const res = await Axiosinstance.post(`storage/files/${id}/star/`);
      const is_starred = typeof res.data?.is_starred === "boolean" ? res.data.is_starred : !file.is_starred;
      toast.success(is_starred ? "به ستاره‌دارها اضافه شد ⭐" : "از ستاره‌دارها حذف شد ✅");
      await requestRefresh({ silent: true });
    } catch (err) {
      toast.error(getFriendlyError(err, "ستاره‌دار کردن ناموفق بود."));
    }
  };

  const handleTrashFolder = async (folder) => {
    try {
      const id = getFolderId(folder);
      await Axiosinstance.post(`storage/folders/${id}/trash/`);
      toast.info("پوشه به سطل زباله منتقل شد.");
      await requestRefresh({ silent: true });
    } catch (err) {
      toast.error(getFriendlyError(err, "انتقال پوشه ناموفق بود."));
    }
  };

  const handleRestoreFolder = async (folder) => {
    try {
      const id = getFolderId(folder);
      await Axiosinstance.post(`storage/folders/${id}/restore/`);
      toast.success("پوشه بازیابی شد ✅");
      await requestRefresh({ silent: true });
    } catch (err) {
      toast.error(getFriendlyError(err, "بازگردانی پوشه ناموفق بود."));
    }
  };

  const handleHardDeleteFolder = async (folder) => {
    try {
      const id = getFolderId(folder);
      await Axiosinstance.delete(`storage/folders/${id}/hard-delete/`);
      toast.success("حذف دائمی پوشه انجام شد ✅");
      // اگر داخل همین پوشه بودی، یک پله برگرد
      setSelectedFolderPath((p) => (p.includes(String(id)) ? p.slice(0, -1) : p));
      await requestRefresh({ silent: true });
    } catch (err) {
      toast.error(getFriendlyError(err, "حذف دائمی پوشه ناموفق بود."));
    }
  };

  const handleStarFolder = async (folder) => {
    try {
      const id = getFolderId(folder);
      const res = await Axiosinstance.post(`storage/folders/${id}/star/`);
      const is_starred = typeof res.data?.is_starred === "boolean" ? res.data.is_starred : !folder.is_starred;
      toast.success(is_starred ? "پوشه ستاره‌دار شد ⭐" : "پوشه از ستاره‌دارها حذف شد ✅");
      await requestRefresh({ silent: true });
    } catch (err) {
      toast.error(getFriendlyError(err, "ستاره‌دار کردن پوشه ناموفق بود."));
    }
  };

  const handleOpenShare = (file) => {
    closeFileMenu();
    setShareModal({
      open: true,
      file,
      data: null,
      downloadLink: "",
      copying: false,
      revoking: false,
      creating: false,
    });
  };

  const handleCreateShare = async ({ permission, duration, file }) => {
    if (!file) return toast.error("فایل انتخاب نشده.");
    try {
      setShareModal((p) => ({ ...p, creating: true }));
      const id = getFileId(file);
      const res = await Axiosinstance.post(`storage/files/${id}/share/`, { permission, duration });
      setShareModal((p) => ({
        ...p,
        data: res.data,
        downloadLink: res.data?.download_url || res.data?.share_url || "",
        creating: false,
      }));
      toast.success("لینک اشتراک ساخته شد ✅");
    } catch (err) {
      toast.error(getFriendlyError(err, "ساخت لینک اشتراک ناموفق بود."));
      setShareModal((p) => ({ ...p, creating: false }));
    }
  };

  const handleRevokeShare = async () => {
    const token = shareModal?.data?.token;
    const file = shareModal?.file;
    if (!token || !file) return toast.error("توکن اشتراک پیدا نشد.");

    try {
      setShareModal((p) => ({ ...p, revoking: true }));
      const id = getFileId(file);
      await Axiosinstance.post(`storage/files/${id}/share/revoke/`, { token });
      toast.success("اشتراک لغو شد ✅");
      setShareModal({
        open: false,
        file: null,
        data: null,
        downloadLink: "",
        copying: false,
        revoking: false,
        creating: false,
      });
    } catch (err) {
      toast.error(getFriendlyError(err, "لغو اشتراک ناموفق بود."));
      setShareModal((p) => ({ ...p, revoking: false }));
    }
  };

  const handleSetColor = async (type, item, color_id) => {
    try {
      if (type === "file") {
        const id = getFileId(item);
        await Axiosinstance.patch(`storage/files/${id}/color/`, { color_id: color_id ?? null });
      } else {
        const id = getFolderId(item);
        await Axiosinstance.patch(`storage/folders/${id}/color/`, { color_id: color_id ?? null });
      }
      toast.success("رنگ تغییر کرد ✅");
      await requestRefresh({ silent: true });
    } catch (err) {
      toast.error(getFriendlyError(err, "تغییر رنگ ناموفق بود."));
    }
  };

  /* ===================== Menus render (ItemMenus) ===================== */
  const renderFileMenu = useCallback(
    (file) => (
      <FileMenu
        file={file}
        colorsCfg={colorsCfg}
        colorOptions={colorOptions}
        colorsLoading={colorsLoading}
        onDetails={(t, it) => {
          openDetails(t, it);
          closeFileMenu();
        }}
        onRename={(f) => openRename("file", f)}
        onShare={(f) => handleOpenShare(f)}
        onDownload={(f) => handleDownloadFile(f)}
        onMove={(f) => openMove(f)}
        onZip={(seed) => {
          openZipModalWith(seed);
          closeFileMenu();
        }}
        onUnzip={async (f) => {
          await handleExtractZip(f);
          closeFileMenu();
        }}
        onToggleStar={(f) => handleStarFile(f)}
        onTrashOrRestore={(f, mode) => (mode === "trash" ? handleTrashFile(f) : handleRestoreFile(f))}
        onHardDelete={(f) => handleHardDeleteFile(f)}
        onOpenColorModal={(f) => {
          closeFileMenu();
          setColorModal({ open: true, type: "file", item: f });
        }}
      />
    ),
    [colorsCfg, colorOptions, colorsLoading, visibleFiles, pageSize]
  );

  const renderFolderMenu = useCallback(
    (folder) => (
      <FolderMenu
        folder={folder}
        colorsCfg={colorsCfg}
        colorOptions={colorOptions}
        colorsLoading={colorsLoading}
        onDetails={(t, it) => {
          openDetails(t, it);
          closeFolderMenu();
        }}
        onRename={(fo) => openRename("folder", fo)}
        onZip={(seed) => {
          openZipModalWith(seed);
          closeFolderMenu();
        }}
        onToggleStar={(fo) => handleStarFolder(fo)}
        onTrashOrRestore={(fo, mode) => (mode === "trash" ? handleTrashFolder(fo) : handleRestoreFolder(fo))}
        onHardDelete={(fo) => handleHardDeleteFolder(fo)}
        onOpenColorModal={(fo) => {
          closeFolderMenu();
          setColorModal({ open: true, type: "folder", item: fo });
        }}
      />
    ),
    [colorsCfg, colorOptions, colorsLoading]
  );

  const canBack = selectedFolderPath.length > 1;

  return (
    <div
      className="w-full min-w-0 dark:text-white text-black"
      onClick={() => {
        closeFileMenu();
        closeFolderMenu();
      }}
    >
      {/* Zip */}
      <ZipModal
        state={zipModal}
        setState={setZipModal}
        files={(visibleFiles || []).map((f) => ({ ...f, id: String(getFileId(f)) }))}
        allFoldersFlat={allFoldersFlat}
        onCreateArchive={handleCreateArchive}
      />

      {/* Details */}
      <DetailsModal state={detailsModal} onClose={() => setDetailsModal({ open: false, type: null, item: null })} />

      {/* Rename */}
      <RenameModal
        state={renameModal}
        setState={setRenameModal}
        onSave={async () => {
          const item = renameModal.item;
          const name = String(renameModal.value || "").trim();
          if (!item || !name) return toast.error("نام جدید را وارد کنید.");

          if (renameModal.type === "file") await handleRenameFile(item, name);
          if (renameModal.type === "folder") await handleRenameFolder(item, name);

          setRenameModal({ open: false, type: null, item: null, value: "" });
        }}
      />

      {/* Move */}
      <MoveModal
        state={moveModal}
        setState={setMoveModal}
        foldersFlat={allFoldersFlat}
        onCreateFolder={async (name, parentId) => handleCreateFolder(name, parentId)}
        onMove={async (file, dest) => {
          const finalDest = dest === "root" ? null : dest;
          await handleMoveFile(file, finalDest);
          setMoveModal({ open: false, item: null, target: "root" });
        }}
      />

      {/* Share */}
      <ShareModal
        state={shareModal}
        onClose={() =>
          setShareModal({
            open: false,
            file: null,
            data: null,
            downloadLink: "",
            copying: false,
            revoking: false,
            creating: false,
          })
        }
        onCreate={handleCreateShare}
        onRevoke={handleRevokeShare}
      />

      {/* Color */}
      <ColorPickerModal
        open={colorModal.open}
        onClose={() => setColorModal({ open: false, type: null, item: null })}
        title="تغییر رنگ"
        itemName={colorModal?.item?.name || ""}
        colorsCfg={colorsCfg}
        colorOptions={colorOptions}
        colorsLoading={colorsLoading}
        onPick={async (colorIdOrNull) => {
          const t = colorModal.type;
          const it = colorModal.item;
          if (!t || !it) return;
          await handleSetColor(t, it, colorIdOrNull);
          setColorModal({ open: false, type: null, item: null });
        }}
      />

      {/* Create Folder (simple modal) */}
      {createFolderModal.open && (
        <div
          className="fixed inset-0 z-[999998] flex items-center justify-center p-4"
          onPointerDown={(e) => {
            if (e.target === e.currentTarget) setCreateFolderModal({ open: false, parent: "root", name: "", creating: false });
          }}
        >
          <div className="absolute inset-0 bg-black/40 backdrop-blur-[2px]" />
          <div className="relative w-full max-w-lg rounded-2xl bg-white dark:bg-[#001F3F] border border-black/10 dark:border-white/10 shadow-2xl p-4" onPointerDown={(e) => e.stopPropagation()}>
            <div className="flex items-center justify-between mb-3 gap-3">
              <h3 className="font-extrabold text-black dark:text-white truncate">ایجاد پوشه</h3>
              <button
                className="px-3 py-1.5 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10"
                onClick={() => setCreateFolderModal({ open: false, parent: "root", name: "", creating: false })}
              >
                بستن
              </button>
            </div>

            <div className="space-y-3">
              <input
                value={createFolderModal.name}
                onChange={(e) => setCreateFolderModal((p) => ({ ...p, name: e.target.value }))}
                className="w-full rounded-xl border border-black/10 dark:border-white/10 bg-white dark:bg-[#16325B] px-3 py-2 outline-none dark:text-white"
                placeholder="نام پوشه جدید"
              />

              <div className="flex gap-2 justify-end">
                <button
                  className="px-4 py-2 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10"
                  onClick={() => setCreateFolderModal({ open: false, parent: "root", name: "", creating: false })}
                >
                  لغو
                </button>
                <button
                  className="px-4 py-2 rounded-xl bg-[#A1E3F980] dark:bg-[#A1E3F919] border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 disabled:opacity-60"
                  disabled={createFolderModal.creating}
                  onClick={async () => {
                    const parentId = createFolderModal.parent;
                    const ok = await handleCreateFolder(createFolderModal.name, parentId);
                    if (ok) setCreateFolderModal({ open: false, parent: "root", name: "", creating: false });
                  }}
                >
                  {createFolderModal.creating ? "در حال ساخت..." : "ساخت پوشه"}
                </button>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* Top bar */}
      <div className="mb-5 rounded-2xl border border-black/10 dark:border-white/10 bg-[#A1E3F910] shadow p-3 sm:p-4">
        <div className="flex flex-col lg:flex-row gap-3 lg:items-center lg:justify-between min-w-0">
          <div className="min-w-0">
            <h1 className="text-lg sm:text-xl font-extrabold">پوشه‌ها</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
              onClick={() => setViewMode("grid")}
              className={`flex-1 lg:flex-none border rounded-xl px-3 py-2 inline-flex items-center justify-center gap-2 transition
                ${
                  viewMode === "grid"
                    ? "dark:bg-[#A1E3F919] bg-[#A1E3F980] dark:text-[#43BEFF] shadow text-black border-[#A1E3F919]"
                    : "border-[#A1E3F919] hover:bg-black/5 dark:text-white text-[#43BEFF] dark:hover:bg-white/10"
                }`}
            >
              <IoGrid className="h-5 w-5" />
              <span className="text-sm">گرید</span>
            </button>

            <button
              onClick={() => setViewMode("list")}
              className={`flex-1 lg:flex-none border rounded-xl px-3 py-2 inline-flex items-center justify-center gap-2 transition
                ${
                  viewMode === "list"
                    ? "dark:bg-[#A1E3F919] bg-[#A1E3F980] dark:text-[#43BEFF] shadow text-black border-[#A1E3F919]"
                    : "border-[#A1E3F919] hover:bg-black/5 dark:text-white text-[#43BEFF] dark:hover:bg-white/10"
                }`}
            >
              <IoList className="h-5 w-5" />
              <span className="text-sm">لیست</span>
            </button>
          </div>
        </div>
      </div>

      {/* Breadcrumb */}
      <BreadcrumbBar
        breadcrumb={breadcrumb}
        canBack={canBack}
        onRoot={() => {
          setSelectedFolderPath(["root"]);
          closeFileMenu();
          closeFolderMenu();
        }}
        onCrumb={(i) => {
          setSelectedFolderPath((p) => p.slice(0, i + 1));
          closeFileMenu();
          closeFolderMenu();
        }}
        onBack={() => {
          setSelectedFolderPath((p) => p.slice(0, -1));
          closeFileMenu();
          closeFolderMenu();
        }}
      />

      {/* States */}
      {loading && <div className="p-4 rounded-2xl border border-black/10 dark:border-white/10 bg-white/60 dark:bg-[#16325b] text-sm">در حال دریافت...</div>}
      {loadError && <div className="p-4 rounded-2xl border border-red-500/30 bg-red-500/10 text-sm text-red-600 dark:text-red-200">{loadError}</div>}

      {/* Folders header */}
      <div className="flex justify-between flex-wrap items-center mb-3">
        <h2 className="font-extrabold text-base sm:text-lg">{selectedFolder?.name ? `پوشه‌های داخل ${selectedFolder.name}` : "پوشه‌ها"}</h2>

        <button
          onClick={() => {
            const parentId = selectedFolder ? String(getFolderId(selectedFolder)) : "root";
            setCreateFolderModal({ open: true, parent: parentId || "root", name: "", creating: false });
          }}
          type="button"
          className="flex gap-2 items-center justify-center px-4 py-2 text-sm font-medium border border-black/10 bg-[#A1E3F980] dark:bg-[#A1E3F919] dark:border-white/10 rounded-xl shadow hover:bg-[#43BEFF40] transition"
        >
          <TbPlus className="h-5 w-5" />
          <span>ایجاد پوشه</span>
        </button>
      </div>

      {/* Folders */}
      {pagedFolders.total === 0 ? (
        <div className="p-4 rounded-2xl border border-black/10 dark:border-white/10 bg-white/60 dark:bg-[#16325b] text-sm text-black/60 dark:text-white/70">پوشه‌ای برای نمایش وجود ندارد.</div>
      ) : (
        <>
          <ul className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3 sm:gap-4 py-3 sm:py-4">
            {pagedFolders.items.map((folder) => {
              const fid = getFolderId(folder);
              return (
                <li
                  key={String(fid)}
                  onClick={() => {
                    setSelectedFolderPath((prev) => [...prev, fid]);
                    closeFileMenu();
                    closeFolderMenu();
                  }}
                  className="relative min-w-0 rounded-2xl p-4 bg-[#A1E3F980] shadow dark:bg-[#A1E3F919]
                    hover:bg-[#f2f2f2] dark:hover:bg-[#001F3F]
                    border border-black/5 dark:border-white/10
                    transition-colors cursor-pointer"
                >
                  <div className="flex items-start justify-between gap-3 min-w-0">
                    <div className="flex gap-3 items-center min-w-0">
                      <div className="w-11 h-11 rounded-2xl bg-white/70 dark:bg-white/10 border border-black/10 dark:border-white/10 flex items-center justify-center shrink-0">
                        <IoFolderOpen className="h-6 w-6 text-[#43BEFF]" />
                      </div>

                      <div className="min-w-0">
                        <p className="truncate font-bold text-sm sm:text-base">{folder.name || "بدون نام"}</p>
                        <p className="text-xs mt-2 dark:text-white/60 text-black/50 truncate">
                          {folder.folders?.length || 0} فولدر • {folder.files?.length || 0} فایل
                        </p>
                      </div>
                    </div>

                    <button
                      type="button"
                      className="p-2 rounded-xl hover:bg-black/5 dark:hover:bg-white/10 shrink-0"
                      onPointerDown={(e) => {
                        e.preventDefault();
                        e.stopPropagation();
                      }}
                      onClick={(e) => toggleFolderMenu(fid, e)}
                    >
                      <IoEllipsisVertical className="h-5 w-5 dark:text-white text-black" />
                    </button>

                    <ActionMenuPortal open={String(folderMenu.id) === String(fid)} rect={folderMenu.rect} onClose={closeFolderMenu} width={280}>
                      {renderFolderMenu(folder)}
                    </ActionMenuPortal>
                  </div>
                </li>
              );
            })}
          </ul>

          <PaginationControls
            total={pagedFolders.total}
            page={pagedFolders.page}
            onPageChange={setFoldersPage}
            pageSize={pageSize}
            onPageSizeChange={setPageSize}
            sessionKey={SESSION_PAGE_SIZE_KEY}
            defaultPageSize={8}
            label="پوشه‌ها"
          />
        </>
      )}

      {/* Files section */}
      <div className="mt-4">
        <div className="flex items-center justify-between mb-3">
          <h2 className="font-extrabold text-base sm:text-lg">فایل‌های {selectedFolder?.name || ""}</h2>
        </div>

        {pagedFiles.total === 0 ? (
          <div className="p-4 rounded-2xl border border-black/10 dark:border-white/10 bg-white/60 dark:bg-[#16325b] text-sm text-black/60 dark:text-white/70">فایلی در این پوشه وجود ندارد.</div>
        ) : (
          <>
            {viewMode === "list" ? (
              <FilesList files={pagedFiles.items} fileMenu={fileMenu} onToggleFileMenu={toggleFileMenu} onCloseFileMenu={closeFileMenu} renderFileMenu={renderFileMenu} />
            ) : (
              <FilesGrid
                files={pagedFiles.items}
                baseURL={Axiosinstance.defaults.baseURL}
                Axiosinstance={Axiosinstance}
                fileMenu={fileMenu}
                onToggleFileMenu={toggleFileMenu}
                onCloseFileMenu={closeFileMenu}
                renderFileMenu={renderFileMenu}
              />
            )}

            <div className="mt-3">
              <PaginationControls
                total={pagedFiles.total}
                page={pagedFiles.page}
                onPageChange={setFilesPage}
                pageSize={pageSize}
                onPageSizeChange={setPageSize}
                sessionKey={SESSION_PAGE_SIZE_KEY}
                defaultPageSize={8}
                label="فایل‌ها"
              />
            </div>
          </>
        )}
      </div>
    </div>
  );
}
