// src/components/storage/FilesGrid.jsx
import React, { useEffect, useMemo, useRef, useState } from "react";
import { IoEllipsisVertical } from "react-icons/io5";
import { FaStar } from "react-icons/fa";
import {
  FileTypeIcon,
  formatDate,
  formatSize,
  getEffectiveHex,
  getFileExtension,
  getFileId,
  getItemColorStyle,
  hexToRgba,
  isImageFile,
  joinUrl,
  getPreviewUrl,
  getPublicBaseUrl,
} from "../../utils/storage";
import ActionMenuPortal from "./ActionMenuPortal";

export default function FilesGrid({
  files = [],
  fileMenu,
  onToggleFileMenu,
  onCloseFileMenu,
  renderFileMenu,
  baseURL,
  Axiosinstance, // ✅ باید از Dashboard پاس داده بشه
}) {
  if (!files.length) return null;

  const [thumbs, setThumbs] = useState({}); // fileId -> abs thumb url

  // ✅ برای جلوگیری از stale closure
  const thumbsRef = useRef(thumbs);
  useEffect(() => {
    thumbsRef.current = thumbs;
  }, [thumbs]);

  // جلوگیری از درخواست‌های تکراری
  const inFlightRef = useRef(new Set());

  // ✅ محدودیت retry برای preview های هنوز آماده نشده
  const triesRef = useRef({}); // id -> tries count
  const MAX_TRIES = 4;
  const RETRY_MS = 1200;
  const CONCURRENCY = 6;

  const publicBase = useMemo(() => getPublicBaseUrl(baseURL), [baseURL]);

  useEffect(() => {
    if (!Axiosinstance) return;

    // فقط فایل‌های تصویر که:
    // - preview مستقیم تو آبجکتشون نیست (getPreviewUrl null)
    // - و هنوز تو cache نداریم
    const needIds = (files || [])
      .filter((f) => isImageFile(f))
      .map((f) => ({ id: String(getFileId(f)), f }))
      .filter((x) => x.id && !getPreviewUrl(baseURL, x.f))
      .map((x) => x.id)
      .filter((id) => !thumbsRef.current[id] && !inFlightRef.current.has(id))
      .filter((id) => (triesRef.current[id] || 0) < MAX_TRIES);

    if (needIds.length === 0) return;

    let cancelled = false;

    const worker = async (ids) => {
      for (const id of ids) {
        if (cancelled) return;

        if (thumbsRef.current[id]) continue;
        if (inFlightRef.current.has(id)) continue;
        if ((triesRef.current[id] || 0) >= MAX_TRIES) continue;

        inFlightRef.current.add(id);
        triesRef.current[id] = (triesRef.current[id] || 0) + 1;

        try {
          const res = await Axiosinstance.get(`storage/files/${id}/preview/`);
          const p = res?.data?.preview;

          const readyThumb = p?.status === "ready" ? p?.thumb_url : null;

          if (readyThumb && !cancelled) {
            const abs = joinUrl(publicBase, readyThumb);
            setThumbs((prev) => (prev[id] ? prev : { ...prev, [id]: abs }));
          } else {
            // ✅ اگر هنوز آماده نیست، یک retry زمان‌دار
            if (!cancelled) {
              setTimeout(() => {
                // فقط باعث rerun effect میشه چون files تغییر نکرده؟ نه.
                // پس با یک setThumbs بی‌اثر، ری‌اکت رو تکون میدیم:
                setThumbs((prev) => ({ ...prev }));
              }, RETRY_MS);
            }
          }
        } catch {
          // ignore
        } finally {
          inFlightRef.current.delete(id);
        }
      }
    };

    const chunks = Array.from({ length: CONCURRENCY }, () => []);
    needIds.forEach((id, i) => chunks[i % CONCURRENCY].push(id));
    chunks.forEach((c) => worker(c));

    return () => {
      cancelled = true;
    };
  }, [files, Axiosinstance, publicBase, baseURL]); // ✅ thumbs رو نیاز نیست

  return (
    <div className="mt-3 max-h-[650px] overflow-y-auto grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
      {files.map((file) => {
        const img = isImageFile(file);
        const id = getFileId(file);
        const sid = String(id);
        const location = file.folderPath || "ریشه";
        const ext = getFileExtension(file.name);
        const fhex = getEffectiveHex(file);
        const size = formatSize(file.current_version?.size);

        const direct = getPreviewUrl(baseURL, file); // اگر تو لیست آیتم‌ها preview اومده باشه
        const cached = thumbs[sid] || null;

        const fallbackDownload = joinUrl(baseURL, `storage/files/${id}/download/`);
        const previewUrl = direct || cached || fallbackDownload;

        return (
          <div
            key={sid}
            className="relative min-w-0 rounded-2xl p-4
              dark:bg-white/5 bg-[#A1E3F980]
              hover:bg-[#f2f2f2] dark:hover:bg-white/10
              border border-black/5 dark:border-white/10
              shadow-[0_10px_30px_rgba(0,0,0,0.06)]
              transition-colors"
          >
            <div className="absolute left-2 top-2">
              <button
                type="button"
                className="p-2 rounded-xl hover:bg-black/5 dark:hover:bg-white/10"
                onPointerDown={(e) => {
                  e.preventDefault();
                  e.stopPropagation();
                }}
                onClick={(e) => onToggleFileMenu?.(id, e)}
              >
                <IoEllipsisVertical className="h-5 w-5 dark:text-white text-black" />
              </button>

              <ActionMenuPortal
                open={String(fileMenu?.id) === sid}
                rect={fileMenu?.rect}
                onClose={onCloseFileMenu}
                width={310}
              >
                {renderFileMenu?.({ ...file, folderPath: location })}
              </ActionMenuPortal>
            </div>

            <p className="dark:text-white text-black mb-3 text-sm font-bold truncate flex items-center gap-2">
              <span
                className="inline-flex items-center justify-center w-9 h-9 rounded-xl border"
                style={{
                  background: hexToRgba(fhex, 0.14),
                  borderColor: hexToRgba(fhex, 0.35),
                }}
              >
                <FileTypeIcon ext={ext} className="h-5 w-5" style={getItemColorStyle(file)} />
              </span>

              {file.is_starred && <FaStar className="text-yellow-500 h-4 w-4" />}
              <span className="truncate">{file.name}</span>
            </p>

            <div className="w-full h-32 rounded-2xl dark:bg-[#16325B] bg-white/70 border border-black/10 dark:border-white/10 flex items-center justify-center overflow-hidden">
              {img ? (
                <img
                  src={previewUrl}
                  alt={file.name}
                  className="w-full h-full object-cover"
                  loading="lazy"
                  onError={(e) => {
                    // اگر thumb شکست خورد → دانلود مستقیم
                    if (e.currentTarget.src !== fallbackDownload) {
                      e.currentTarget.src = fallbackDownload;
                    }
                  }}
                />
              ) : (
                <FileTypeIcon ext={ext} className="h-10 w-10" style={getItemColorStyle(file)} />
              )}
            </div>

            <div className="mt-3 space-y-1 text-xs font-medium">
              <p className="dark:text-white/70 text-black/60 truncate">مالک: {file.owner_email || "-"}</p>
              <p className="dark:text-white/70 text-black/60 truncate">محل: {location}</p>
              <p className="dark:text-white/70 text-black/60 truncate">آپدیت: {formatDate(file.updated_at)}</p>
              <p className="dark:text-white/50 text-black/50 truncate">حجم: {size}</p>
            </div>
          </div>
        );
      })}
    </div>
  );
}
