// src/hooks/useStorageDashboardItems.js
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { flattenFilesFromFolders, getFileId, getFolderId } from "../utils/storage.jsx";

export function useStorageDashboardItems({ Axiosinstance, toast }) {
  const [folders, setFolders] = useState([]);
  const [foldersTreeRaw, setFoldersTreeRaw] = useState([]);
  const [files, setFiles] = useState([]);

  const [loading, setLoading] = useState(false);
  const [loadError, setLoadError] = useState(null);

  const isMountedRef = useRef(false);
  const inFlightRef = useRef(false);
  const refreshTimerRef = useRef(null);

  const applyStarToFolderTree = useCallback((folderList, starredFolderIdsSet) => {
    const walk = (list) =>
      (list || []).map((f) => {
        const id = getFolderId(f);
        const is_starred = starredFolderIdsSet.has(String(id)) || !!f.is_starred;
        return {
          ...f,
          is_starred,
          folders: f?.folders?.length ? walk(f.folders) : f.folders,
        };
      });
    return walk(folderList || []);
  }, []);

  const buildStateFromResponses = useCallback(
    (itemsRes, starredFilesRes, starredFoldersRes) => {
      const data = itemsRes?.data || {};

      // starred files
      const starredFilesData = starredFilesRes?.data || {};
      let starredFilesArray = [];
      if (Array.isArray(starredFilesData?.files)) starredFilesArray = starredFilesData.files;
      else if (Array.isArray(starredFilesData)) starredFilesArray = starredFilesData;

      const starredFileIds = new Set(starredFilesArray.map((f) => String(getFileId(f))));

      // starred folders
      const starredFoldersArray = Array.isArray(starredFoldersRes?.data) ? starredFoldersRes.data : [];
      const starredFolderIds = new Set(starredFoldersArray.map((f) => String(getFolderId(f))));

      // folders tree
      const foldersRaw = data.folders || [];
      const foldersTreeWithStar = applyStarToFolderTree(foldersRaw, starredFolderIds);

      setFoldersTreeRaw(foldersTreeWithStar);
      setFolders(foldersTreeWithStar);

      // files: root + nested
      const rootFiles = (data.files || []).map((file) => ({ ...file, folderPath: "ریشه" }));
      const nestedFiles = flattenFilesFromFolders(foldersTreeWithStar || [], "ریشه");
      const allFilesRaw = [...rootFiles, ...nestedFiles];

      const allFilesWithStar = allFilesRaw.map((file) => ({
        ...file,
        is_starred: starredFileIds.has(String(getFileId(file))) || !!file.is_starred,
      }));

      setFiles(allFilesWithStar);
    },
    [applyStarToFolderTree]
  );

  const fetchItems = useCallback(
    async ({ silent = false } = {}) => {
      if (inFlightRef.current) return;
      inFlightRef.current = true;

      try {
        if (!silent) setLoading(true);
        setLoadError(null);

        const [itemsRes, starredFilesRes, starredFoldersRes] = await Promise.all([
          Axiosinstance.get("storage/items/"),
          Axiosinstance.get("storage/starred/"),
          Axiosinstance.get("storage/folders/starred/"),
        ]);

        buildStateFromResponses(itemsRes, starredFilesRes, starredFoldersRes);
      } catch (err) {
        setLoadError("خطا در دریافت فایل‌ها. لطفاً بعداً دوباره امتحان کنید.");
        toast?.error?.("خطا در دریافت آیتم‌ها. لطفاً دوباره تلاش کنید.");
      } finally {
        if (!silent) setLoading(false);
        inFlightRef.current = false;
      }
    },
    [Axiosinstance, toast, buildStateFromResponses]
  );

  const requestRefresh = useCallback(
    (opts = { silent: true }) => {
      if (refreshTimerRef.current) window.clearTimeout(refreshTimerRef.current);
      refreshTimerRef.current = window.setTimeout(() => {
        fetchItems(opts);
      }, 200);
    },
    [fetchItems]
  );

  useEffect(() => {
    if (isMountedRef.current) return;
    isMountedRef.current = true;

    fetchItems({ silent: false });

    return () => {
      if (refreshTimerRef.current) window.clearTimeout(refreshTimerRef.current);
    };
  }, [fetchItems]);

  const ownerEmails = useMemo(() => Array.from(new Set(files.map((f) => f.owner_email).filter(Boolean))), [files]);

  return {
    folders,
    foldersTreeRaw,
    files,
    loading,
    loadError,
    ownerEmails,
    setFiles,
    setFolders,
    setFoldersTreeRaw,
    fetchItems,
    requestRefresh,
  };
}
