// src/pages/Upload.jsx
// ✅ Max file size 5GB
// ✅ Folder tree built from nested `folders` in API response (your JSON shape)
// ✅ Folder destination uses your Dropdown component
// ✅ Prevent upload if a file with same name exists in destination folder (case-insensitive)
// ✅ Auto-suggest available names like "file (1).zip" and allow one-click apply
// ✅ Encrypt radio added (default: false) -> ALWAYS sends encrypt=true/false

import React, { useEffect, useMemo, useRef, useState, useCallback } from "react";
import { Axiosinstance } from "../services/auth/Axiosinstance";
import { TbCloudUpload, TbFolderPlus } from "react-icons/tb";
import { TbFolder } from "react-icons/tb";
import Dropdown from "../components/filters/Dropdown";
import { useToast } from "../components/ToastProvider";

/* ---------------- helpers ---------------- */
function cn(...a) {
  return a.filter(Boolean).join(" ");
}

const bytesToHuman = (bytes) => {
  if (!Number.isFinite(bytes)) return "-";
  const units = ["B", "KB", "MB", "GB", "TB"];
  let b = bytes;
  let i = 0;
  while (b >= 1024 && i < units.length - 1) {
    b /= 1024;
    i++;
  }
  return `${b.toFixed(i === 0 ? 0 : 2)} ${units[i]}`;
};

const clamp = (v, min, max) => Math.max(min, Math.min(max, v));

const normalizeName = (s) => String(s || "").trim().toLowerCase();

/**
 * خروجی شما:
 * {
 *   current_folder,
 *   folders: [ { id,name, folders:[...], files:[...] }, ... ],
 *   files: [ ... ]
 * }
 */
const extractFolders = (data) => (Array.isArray(data?.folders) ? data.folders : []);
const extractFiles = (data) => (Array.isArray(data?.files) ? data.files : []);

/**
 * فولدرهای nested (folders داخل folders) را flatten می‌کند
 * و label مثل: /A/B/C می‌سازد
 */
const flattenFoldersWithPathFromNested = (foldersTopLevel) => {
  const out = [];
  const walk = (nodes, prefix) => {
    (nodes || []).forEach((n) => {
      const name = n?.name || "بدون نام";
      const path = `${prefix}/${name}`.replaceAll("//", "/");
      out.push({ id: String(n.id), label: path, path, raw: n });

      const kids = Array.isArray(n?.folders) ? n.folders : [];
      if (kids.length) walk(kids, path);
    });
  };
  walk(foldersTopLevel || [], "");
  return out.sort((a, b) => a.label.localeCompare(b.label, "fa"));
};

// پیام خطا از DRF/Backend
const getErrMsg = (err, fallback = "خطا. لطفاً دوباره تلاش کنید.") => {
  const d = err?.response?.data;
  if (!d) return err?.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;
  }
};

const MAX_FILE_BYTES = 5 * 1024 * 1024 * 1024; // 5GB

/** split filename to base + ext (ext includes dot, may be "") */
const splitName = (name) => {
  const n = String(name || "").trim();
  if (!n) return { base: "", ext: "" };

  // اگر فایل مثل ".env" بود، ext رو خالی می‌گیریم
  if (n.startsWith(".") && n.indexOf(".", 1) === -1) return { base: n, ext: "" };

  const idx = n.lastIndexOf(".");
  if (idx <= 0 || idx === n.length - 1) return { base: n, ext: "" };
  return { base: n.slice(0, idx), ext: n.slice(idx) };
};

/** generate suggestions: base (1).ext, base (2).ext ... that are NOT in existing set */
const suggestAvailableNames = (name, existingSet, max = 5) => {
  const out = [];
  const { base, ext } = splitName(name);

  if (!base) return out;

  const original = `${base}${ext}`;
  if (!existingSet.has(normalizeName(original))) out.push(original);

  let i = 1;
  while (out.length < max && i <= 200) {
    const candidate = `${base} (${i})${ext}`;
    if (!existingSet.has(normalizeName(candidate))) out.push(candidate);
    i++;
  }
  return out;
};

export default function Upload() {
  const { success, error: toastError, info } = useToast();

  const [file, setFile] = useState(null);
  const [fileName, setFileName] = useState("");
  const [description, setDescription] = useState("");
  const [tags, setTags] = useState("");

  // ✅ NEW: encryption flag (default false)
  const [encrypt, setEncrypt] = useState(false);

  const [isDragging, setIsDragging] = useState(false);

  // folders tree from API (top-level folders)
  const [foldersTop, setFoldersTop] = useState([]);

  // flat list for dropdown
  const flatFolders = useMemo(() => flattenFoldersWithPathFromNested(foldersTop), [foldersTop]);

  const [selectedFolderId, setSelectedFolderId] = useState(""); // "" = root
  const [newFolderName, setNewFolderName] = useState("");
  const [isCreatingFolder, setIsCreatingFolder] = useState(false);

  const [isUploading, setIsUploading] = useState(false);
  const [uploadProgress, setUploadProgress] = useState(0);

  // stats
  const [uploadLoaded, setUploadLoaded] = useState(0);
  const [uploadTotal, setUploadTotal] = useState(0);
  const [uploadSpeed, setUploadSpeed] = useState(0);
  const [uploadEtaSec, setUploadEtaSec] = useState(null);

  // duplicate check state
  const [isCheckingDup, setIsCheckingDup] = useState(false);
  const [hasDupName, setHasDupName] = useState(false);

  // destination existing file names (normalized)
  const [destFileNamesSet, setDestFileNamesSet] = useState(() => new Set());

  const lastProgressRef = useRef({ t: 0, loaded: 0 });

  const resetUploadStats = useCallback((size = 0) => {
    setUploadProgress(0);
    setUploadLoaded(0);
    setUploadTotal(size || 0);
    setUploadSpeed(0);
    setUploadEtaSec(null);
    lastProgressRef.current = { t: 0, loaded: 0 };
  }, []);

  /**
   * ✅ یک درخواست: items/ برای روت یا فولدر انتخاب‌شده
   * - folders: درخت nested می‌آید
   * - files: فایل‌های همان مسیر می‌آید (برای duplicate check)
   */
  const fetchItems = useCallback(async (folderId) => {
    const params = {};
    if (folderId) params.folder = folderId;
    const res = await Axiosinstance.get("storage/items/", { params });
    return res?.data;
  }, []);

  // init: load root items -> folders tree
  useEffect(() => {
    const run = async () => {
      try {
        const data = await fetchItems("");
        setFoldersTop(extractFolders(data));
      } catch (err) {
        console.error("items fetch failed:", err);
        toastError("دریافت پوشه‌ها ناموفق بود.", { title: "خطا" });
      }
    };
    run();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  /** ✅ انتخاب فایل با محدودیت 5GB */
  const pickFile = useCallback(
    (picked) => {
      if (!picked) return;

      const size = picked?.size || 0;
      if (size > MAX_FILE_BYTES) {
        toastError(`حداکثر حجم مجاز فایل 5GB است. (حجم فایل شما: ${bytesToHuman(size)})`, { title: "محدودیت آپلود" });
        return;
      }

      setFile(picked);
      setFileName(picked.name);

      // ✅ default encryption false for each new file
      setEncrypt(false);

      resetUploadStats(size);
      info("فایل انتخاب شد.", { title: "آپلود" });
    },
    [info, resetUploadStats, toastError]
  );

  // input change
  const handleFileChange = (e) => {
    const selected = e.target.files?.[0];
    pickFile(selected);
  };

  // drag drop
  const handleDragOver = (e) => {
    e.preventDefault();
    setIsDragging(true);
  };
  const handleDragLeave = (e) => {
    e.preventDefault();
    setIsDragging(false);
  };
  const handleDrop = (e) => {
    e.preventDefault();
    setIsDragging(false);
    const dropped = e.dataTransfer.files?.[0];
    pickFile(dropped);
  };

  /**
   * ✅ Auto-check duplicate whenever:
   * - destination changes
   * - fileName changes
   * - file selected
   *
   * Also stores destination file names set for suggestions
   */
  useEffect(() => {
    let cancelled = false;

    const run = async () => {
      if (!file) {
        setHasDupName(false);
        setDestFileNamesSet(new Set());
        return;
      }

      try {
        setIsCheckingDup(true);

        const data = await fetchItems(selectedFolderId || "");
        const files = extractFiles(data);

        const namesSet = new Set(files.map((f) => normalizeName(f?.name)));
        if (!cancelled) setDestFileNamesSet(namesSet);

        const n = normalizeName(fileName);
        const dup = n ? namesSet.has(n) : false;
        if (!cancelled) setHasDupName(dup);
      } catch (err) {
        console.error("dup check failed:", err);
        if (!cancelled) {
          setHasDupName(false);
          setDestFileNamesSet(new Set());
        }
      } finally {
        if (!cancelled) setIsCheckingDup(false);
      }
    };

    run();
    return () => {
      cancelled = true;
    };
  }, [file, fileName, selectedFolderId, fetchItems]);

  const suggestions = useMemo(() => {
    if (!file || !fileName.trim()) return [];
    if (!hasDupName) return [];
    return suggestAvailableNames(fileName.trim(), destFileNamesSet, 5);
  }, [file, fileName, hasDupName, destFileNamesSet]);

  const applySuggestion = (s) => {
    if (!s) return;
    setFileName(s);
    info("نام پیشنهادی اعمال شد.", { title: "نام فایل" });
  };

  // ساخت پوشه جدید
  const handleCreateFolder = async () => {
    if (isCreatingFolder) return;

    if (!newFolderName.trim()) {
      toastError("نام پوشه را وارد کنید.", { title: "خطا" });
      return;
    }

    try {
      setIsCreatingFolder(true);

      const payload = { name: newFolderName.trim() };
      if (selectedFolderId) payload.parent = selectedFolderId;

      const res = await Axiosinstance.post("storage/folders/", payload);
      const created = res.data;

      // refresh root folders tree again (safe)
      const rootData = await fetchItems("");
      setFoldersTop(extractFolders(rootData));

      if (created?.id) setSelectedFolderId(String(created.id));
      setNewFolderName("");
      success("پوشه با موفقیت ایجاد شد.", { title: "موفق" });
    } catch (err) {
      console.error("Folder Create Error:", err);
      toastError(getErrMsg(err, "خطا در ایجاد پوشه. لطفاً دوباره تلاش کنید."), { title: "خطا" });
    } finally {
      setIsCreatingFolder(false);
    }
  };

  // آپلود
  const handleUpload = async () => {
    if (isUploading) return;

    if (!file) {
      toastError("لطفاً ابتدا یک فایل انتخاب کنید.", { title: "خطا" });
      return;
    }
    if (!fileName.trim()) {
      toastError("نام فایل را وارد کنید.", { title: "خطا" });
      return;
    }

    // ✅ size guard
    if ((file?.size || 0) > MAX_FILE_BYTES) {
      toastError(`حداکثر حجم مجاز فایل 5GB است. (حجم فایل شما: ${bytesToHuman(file.size || 0)})`, { title: "محدودیت آپلود" });
      return;
    }

    // ✅ Block upload if duplicate exists
    if (hasDupName) {
      toastError("فایلی با همین نام در این پوشه وجود دارد. لطفاً نام فایل را تغییر دهید یا از پیشنهاد استفاده کنید.", {
        title: "نام تکراری",
      });
      return;
    }

    setIsUploading(true);
    resetUploadStats(file.size || 0);

    try {
      const formData = new FormData();

      // rename before upload
      const renamedFile = new File([file], fileName.trim(), { type: file.type });

      formData.append("file", renamedFile);
      formData.append("name", fileName.trim());
      if (description.trim()) formData.append("description", description.trim());
      if (tags.trim()) formData.append("tags", tags.trim());
      if (selectedFolderId) formData.append("folder", selectedFolderId);

      // ✅ ALWAYS send encrypt boolean
      formData.append("encrypt", encrypt ? "true" : "false");

      await Axiosinstance.post("storage/upload/", formData, {
        headers: { "Content-Type": "multipart/form-data" },
        onUploadProgress: (event) => {
          const total = event.total || file.size || 0;
          const loaded = event.loaded || 0;

          const percent = total ? Math.round((loaded * 100) / total) : 0;
          setUploadProgress(clamp(percent, 0, 100));
          setUploadLoaded(loaded);
          setUploadTotal(total);

          const now = performance.now();
          const last = lastProgressRef.current;

          if (last.t) {
            const dt = (now - last.t) / 1000;
            const dLoaded = loaded - last.loaded;
            if (dt > 0.15 && dLoaded >= 0) {
              const speed = dLoaded / dt;
              setUploadSpeed(speed);

              const remain = Math.max(0, total - loaded);
              const eta = speed > 0 ? Math.round(remain / speed) : null;
              setUploadEtaSec(eta);
            }
          }
          lastProgressRef.current = { t: now, loaded };
        },
      });

      success("فایل با موفقیت آپلود شد 🎉", { title: "موفق" });

      // reset
      setFile(null);
      setFileName("");
      setDescription("");
      setTags("");
      setEncrypt(false);
      setHasDupName(false);
      setDestFileNamesSet(new Set());
      resetUploadStats(0);

      // optional: refresh tree
      const rootData = await fetchItems("");
      setFoldersTop(extractFolders(rootData));
    } catch (err) {
      console.error("Upload Error:", err);
      toastError(getErrMsg(err, "خطا در آپلود فایل. لطفاً دوباره تلاش کنید."), { title: "خطا" });
    } finally {
      setIsUploading(false);
    }
  };

  // cancel
  const handleCancel = () => {
    if (isUploading) info("آپلود لغو شد.", { title: "لغو" });

    setFile(null);
    setFileName("");
    setDescription("");
    setTags("");
    setEncrypt(false);
    setHasDupName(false);
    setDestFileNamesSet(new Set());
    resetUploadStats(0);
    setIsUploading(false);
  };

  // folder dropdown items
  const folderDropdownItems = useMemo(() => {
    const base = [{ value: "", label: "/ (ریشه)", icon: <TbFolder className="w-4 h-4" /> }];
    const folderItems = flatFolders.map((f) => ({
      value: String(f.id),
      label: f.label,
      icon: <TbFolder className="w-4 h-4" />,
    }));
    return base.concat(folderItems);
  }, [flatFolders]);

  const currentDestLabel = useMemo(() => {
    if (!selectedFolderId) return "/ (ریشه)";
    return flatFolders.find((x) => String(x.id) === String(selectedFolderId))?.label || "(نامشخص)";
  }, [flatFolders, selectedFolderId]);

  const uploadedHuman = bytesToHuman(uploadLoaded);
  const totalHuman = bytesToHuman(uploadTotal);
  const remainHuman = bytesToHuman(Math.max(0, uploadTotal - uploadLoaded));
  const speedHuman = uploadSpeed ? `${bytesToHuman(uploadSpeed)}/s` : "-";
  const etaHuman = uploadEtaSec === null ? "-" : uploadEtaSec < 60 ? `${uploadEtaSec}s` : `${Math.ceil(uploadEtaSec / 60)}m`;

  return (
    <div className=" w-full items-start sm:p-10 justify-center gap-6">
      <div className=" items-center justify-center w-full">
        <div
          className={cn(
            "grid gap-4 justify-center text-center sm:p-10 p-4 min-h-72 w-full max-w-4xl sm:border-2 border-dashed rounded-4xl cursor-pointer transition-all duration-200",
            isDragging ? "border-[#A1E3F9] bg-white/5" : "dark:border-white/50 bg-transparent"
          )}
          onDragOver={handleDragOver}
          onDragLeave={handleDragLeave}
          onDrop={handleDrop}
        >
          <TbCloudUpload className="h-60 w-60 mx-auto dark:text-white text-[#43BEFF]" />
          <p className="dark:text-white text-black text-3xl font-bold">آپلود فایل جدید</p>
          <p className="dark:text-white text-black text-xl font-semibold">فایل خود را انتخاب کنید تا جزئیات آن را تکمیل نمایید.</p>

          {/* انتخاب فایل */}
          <div className="flex flex-col items-center gap-2">
            <label className="dark:bg-[#001F3F] bg-[#f2f2f2] rounded-xl py-1.5 px-8 dark:text-white text-black text-sm font-semibold w-fit mx-auto cursor-pointer dark:hover:bg-[#022a63] transition-colors">
              انتخاب فایل
              <input type="file" className="hidden" onChange={handleFileChange} />
            </label>

            <p className="dark:text-white text-black text-lg font-semibold">یا فایل خود را اینجا بکشید و رها کنید</p>
            <p className="text-xs dark:text-white/60 text-black/60">حداکثر حجم مجاز: 5GB</p>

            {file && (
              <p className="dark:text-white text-black text-sm mt-1">
                فایل انتخاب شده: <span className="font-semibold">{file.name}</span>
              </p>
            )}

            {/* فرم جزئیات */}
            {file && (
              <div className="w-full max-w-4xl rounded-2xl px-6 py-5 flex flex-col gap-4">
                {/* نام فایل */}
                <div className="flex flex-col gap-1 text-right">
                  <label className="dark:text-white text-black text-sm font-semibold">نام فایل</label>

                  <input
                    type="text"
                    className={cn(
                      "bg-[#A1E3F980] dark:bg-[#a1E3f919] dark:text-white text-black text-sm rounded-xl px-3 py-2 outline-none border",
                      hasDupName ? "border-red-500/60" : "border-white/10"
                    )}
                    value={fileName}
                    onChange={(e) => setFileName(e.target.value)}
                  />

                  <div className="mt-1 flex items-center justify-between text-xs">
                    <span className="text-black/60 dark:text-white/60">
                      حجم فایل: <b className="dark:text-white text-black">{bytesToHuman(file.size || 0)}</b>
                      <span className="mx-1">•</span>
                      سقف: <b className="dark:text-white text-black">{bytesToHuman(MAX_FILE_BYTES)}</b>
                    </span>

                    <span className={cn("font-semibold", hasDupName ? "text-red-500" : "text-black/50 dark:text-white/50")}>
                      {isCheckingDup ? "در حال بررسی نام..." : hasDupName ? "نام تکراری در مقصد" : "نام آزاد"}
                    </span>
                  </div>

                  {/* ✅ پیشنهاد نام آزاد */}
                  {hasDupName && (
                    <div className="mt-2 rounded-xl border border-red-500/20 bg-red-500/5 p-3 text-right">
                      <div className="text-xs text-red-500">
                        فایلی با همین نام در <b>{currentDestLabel}</b> وجود دارد. یکی از نام‌های آزاد زیر را انتخاب کن:
                      </div>

                      <div className="mt-2 flex flex-wrap gap-2">
                        {suggestions.length ? (
                          suggestions.map((s) => (
                            <button
                              key={s}
                              type="button"
                              onClick={() => applySuggestion(s)}
                              className="text-xs rounded-xl px-3 py-1.5 border border-black/10 dark:border-white/10 bg-white/60 dark:bg-white/5 hover:bg-white/80 dark:hover:bg-white/10 transition"
                            >
                              استفاده از: <b className="dark:text-white text-black">{s}</b>
                            </button>
                          ))
                        ) : (
                          <div className="text-xs text-red-500/90">پیشنهاد خودکار پیدا نشد (اسم خیلی خاصه). دستی تغییر بده.</div>
                        )}
                      </div>
                    </div>
                  )}
                </div>

                {/* توضیحات */}
                <div className="flex flex-col gap-1 text-right">
                  <label className="dark:text-white text-black text-sm font-semibold">توضیحات فایل</label>
                  <textarea
                    rows={3}
                    className="bg-[#A1E3F980] dark:bg-[#a1E3f919] dark:text-white text-black text-sm rounded-xl px-3 py-2 outline-none border border-white/10 resize-none"
                    placeholder='مثلاً: "پروپوزال پروژه 7RP"'
                    value={description}
                    onChange={(e) => setDescription(e.target.value)}
                  />
                </div>

                {/* پوشه مقصد + ساخت پوشه */}
                <div className="flex flex-col gap-1 text-right">
                  <label className="dark:text-white text-black text-sm font-semibold">پوشه مقصد</label>

                  <div className="flex flex-wrap gap-2 items-center">
                    <Dropdown
                      id="upload-folder"
                      label="انتخاب پوشه"
                      icon={<TbFolder className="w-5 h-5" />}
                      items={folderDropdownItems}
                      selectedValue={selectedFolderId ? String(selectedFolderId) : ""}
                      onSelect={(val) => setSelectedFolderId(String(val || ""))}
                      width={420}
                    />

                    <div className="flex items-center gap-2">
                      <input
                        type="text"
                        value={newFolderName}
                        onChange={(e) => setNewFolderName(e.target.value)}
                        placeholder={selectedFolderId ? "ساخت پوشه داخل همین مسیر..." : "ساخت پوشه در ریشه..."}
                        className="bg-[#A1E3F980] dark:bg-[#a1E3f919] dark:text-white text-black text-sm rounded-xl px-3 py-2 outline-none border border-white/10 min-w-[220px]"
                      />
                      <button
                        type="button"
                        onClick={handleCreateFolder}
                        disabled={isCreatingFolder || !newFolderName.trim()}
                        className="inline-flex items-center gap-2 dark:bg-[#001f3f] bg-[#f2f2f2] dark:hover:bg-[#022a63] dark:text-white text-black text-sm font-semibold rounded-xl px-4 py-2 disabled:grayscale-100 disabled:pointer-events-none"
                      >
                        <TbFolderPlus className="w-5 h-5" />
                        {isCreatingFolder ? "در حال ایجاد..." : "ایجاد پوشه"}
                      </button>
                    </div>
                  </div>

                  <div className="mt-1 text-xs text-black/60 dark:text-white/60">
                    مقصد فعلی: <b className="dark:text-white text-black">{currentDestLabel}</b>
                  </div>
                </div>

                {/* ✅ Encrypt radio (default false) */}
                <div className="flex flex-col gap-2 text-right">
                  <label className="dark:text-white text-black text-sm font-semibold">رمزنگاری فایل</label>

                  <div className="grid sm:grid-cols-2 gap-2">
                    <label
                      className={cn(
                        "cursor-pointer rounded-2xl border px-3 py-2 flex items-center gap-2 text-sm",
                        encrypt === false
                          ? "border-[#43BEFF]/40 bg-[#43BEFF]/10"
                          : "border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10"
                      )}
                    >
                      <input
                        type="radio"
                        name="encrypt"
                        checked={encrypt === false}
                        onChange={() => setEncrypt(false)}
                      />
                      <span className="font-semibold">رمزنگاری نشود (پیش‌فرض)</span>
                    </label>

                    <label
                      className={cn(
                        "cursor-pointer rounded-2xl border px-3 py-2 flex items-center gap-2 text-sm",
                        encrypt === true
                          ? "border-emerald-500/40 bg-emerald-500/10"
                          : "border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10"
                      )}
                    >
                      <input
                        type="radio"
                        name="encrypt"
                        checked={encrypt === true}
                        onChange={() => setEncrypt(true)}
                      />
                      <span className="font-semibold">رمزنگاری شود</span>
                    </label>
                  </div>

                  <div className="text-xs text-black/60 dark:text-white/60 leading-5">
                    این مقدار همیشه به سرور ارسال می‌شود: <b>encrypt={encrypt ? "true" : "false"}</b>
                  </div>
                </div>

                {/* تگ‌ها */}
                <div className="flex flex-col gap-1 text-right">
                  <label className="dark:text-white text-black text-sm font-semibold">تگ‌ها</label>
                  <input
                    type="text"
                    className="bg-[#A1E3F980] dark:bg-[#a1E3f919] dark:text-white text-black text-sm rounded-xl px-3 py-2 outline-none border border-white/10"
                    placeholder="مثلاً: قرارداد, مالی, پروژه-7RP"
                    value={tags}
                    onChange={(e) => setTags(e.target.value)}
                  />
                  <span className="text-xs text-black/50 dark:text-white/50 mt-1">تگ‌ها را با کاما (،) از هم جدا کنید.</span>
                </div>

                {/* ✅ پروگرس حرفه‌ای */}
                {isUploading && (
                  <div className="mt-2 rounded-2xl p-3 border border-black/10 dark:border-white/10 bg-[#A1E3F919]">
                    <div className="flex items-center justify-between gap-2 text-xs dark:text-white/80 text-black/70">
                      <span className="font-bold">در حال آپلود</span>
                      <span className="font-extrabold">{uploadProgress}%</span>
                    </div>

                    <div className="mt-2 w-full h-3 rounded-full bg-black/10 dark:bg-white/10 overflow-hidden">
                      <div className="h-3 rounded-full bg-[#43BEFF] transition-all duration-150" style={{ width: `${uploadProgress}%` }} />
                    </div>

                    <div className="mt-2 grid grid-cols-2 sm:grid-cols-4 gap-2 text-[11px] dark:text-white/70 text-black/60">
                      <div className="rounded-xl px-2 py-1 bg-white/40 dark:bg-white/5 border border-black/5 dark:border-white/10">
                        آپلود شده: <b className="dark:text-white text-black">{uploadedHuman}</b>
                      </div>
                      <div className="rounded-xl px-2 py-1 bg-white/40 dark:bg-white/5 border border-black/5 dark:border-white/10">
                        کل: <b className="dark:text-white text-black">{totalHuman}</b>
                      </div>
                      <div className="rounded-xl px-2 py-1 bg-white/40 dark:bg-white/5 border border-black/5 dark:border-white/10">
                        باقی‌مانده: <b className="dark:text-white text-black">{remainHuman}</b>
                      </div>
                      <div className="rounded-xl px-2 py-1 bg-white/40 dark:bg-white/5 border border-black/5 dark:border-white/10">
                        زمان باقی: <b className="dark:text-white text-black">{etaHuman}</b>
                        <span className="mx-1">•</span>
                        سرعت: <b className="dark:text-white text-black">{speedHuman}</b>
                      </div>
                    </div>
                  </div>
                )}

                {/* دکمه‌ها */}
                <div className="flex justify-end gap-3 mt-4">
                  <button
                    type="button"
                    onClick={handleCancel}
                    className="dark:bg-[#001f3f] bg-[#f2f2f2] dark:text-white text-black rounded-xl py-2 px-6 text-sm font-semibold dark:hover:bg-[#022a63] transition-colors"
                  >
                    لغو
                  </button>

                  <button
                    type="button"
                    onClick={handleUpload}
                    disabled={isUploading || isCheckingDup || hasDupName}
                    className="dark:bg-[#001f3f] bg-[#f2f2f2] dark:hover:bg-[#022a63] dark:text-white text-black rounded-xl py-2 px-8 text-sm font-semibold disabled:opacity-60 disabled:cursor-not-allowed"
                    title={hasDupName ? "نام فایل تکراری است" : ""}
                  >
                    {isUploading ? "در حال آپلود..." : isCheckingDup ? "در حال بررسی..." : "آپلود"}
                  </button>
                </div>

                {hasDupName && (
                  <div className="mt-2 text-xs text-red-500 text-right">
                    آپلود غیرفعال شد چون فایل همنام در مقصد وجود دارد. یکی از پیشنهادها را بزن یا دستی نام را تغییر بده.
                  </div>
                )}
              </div>
            )}
          </div>

          {/* message/error UI حذف شد چون Toast جایگزین شد */}
        </div>
      </div>
    </div>
  );
}
