import React, { useEffect, useMemo, useState } from "react";
import ModalShell from "./ModalShell";
import { getFolderId } from "../../utils/storage";
import { Axiosinstance } from "../../services/auth/Axiosinstance";
import { useToast } from "../ToastProvider";

/* ---------------- helpers ---------------- */
const normalizeName = (s) => String(s || "").trim().toLowerCase();
const extractFiles = (data) => (Array.isArray(data?.files) ? data.files : []);

const splitName = (name) => {
  const n = String(name || "").trim();
  if (!n) return { base: "", 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) };
};

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;
};

async function renameFile(entryId, name) {
  const newName = String(name || "").trim();
  if (!entryId) throw new Error("Missing entry_id");
  if (!newName) throw new Error("Name is required");

  const res = await Axiosinstance.patch(`storage/files/${entryId}/rename/`, { name: newName });
  return res?.data;
}

export default function MoveModal({
  state,
  setState,
  foldersFlat = [],
  onMove, // async (file, destination_folder_id|null) => void
  onCreateFolder, // async (name, parentId|"root") => void
}) {
  const { info, error: toastError } = useToast();

  const open = !!state?.open;
  const file = state?.item;

  const options = useMemo(() => {
    const rows = Array.isArray(foldersFlat) ? foldersFlat : [];
    return rows
      .map((f) => ({
        id: String(f?.id ?? getFolderId(f)),
        label: `${"— ".repeat(f?.depth || 0)}${f?.name || "بدون نام"}`,
      }))
      .filter((x) => x.id && x.id !== "undefined");
  }, [foldersFlat]);

  const targetValue = state?.target ?? "root";
  const destFolderId = targetValue === "root" ? null : targetValue;

  // ✅ rename name state
  const [moveName, setMoveName] = useState("");
  // ✅ duplicate check states
  const [isChecking, setIsChecking] = useState(false);
  const [destNamesSet, setDestNamesSet] = useState(() => new Set());
  const [hasDup, setHasDup] = useState(false);

  // وقتی مودال باز شد یا فایل عوض شد: اسم پیش‌فرض رو بگذار
  useEffect(() => {
    if (!open) return;
    setMoveName(file?.name || "");
    setIsChecking(false);
    setHasDup(false);
    setDestNamesSet(new Set());
  }, [open, file?.id]); // eslint-disable-line react-hooks/exhaustive-deps

  // ✅ fetch dest files for duplicate check
  useEffect(() => {
    let cancelled = false;

    const run = async () => {
      if (!open || !file) return;

      try {
        setIsChecking(true);

        const params = {};
        if (destFolderId) params.folder = destFolderId;

        const res = await Axiosinstance.get("storage/items/", { params });
        const files = extractFiles(res?.data);

        // حذف خودش (اگر لیست مقصد شامل خودش بود)
        const names = files
          .filter((f) => String(f?.id) !== String(file?.id))
          .map((f) => normalizeName(f?.name));

        const set = new Set(names);
        const n = normalizeName(moveName);

        if (!cancelled) {
          setDestNamesSet(set);
          setHasDup(n ? set.has(n) : false);
        }
      } catch (e) {
        console.error("move dup check failed:", e);
        if (!cancelled) {
          setDestNamesSet(new Set());
          setHasDup(false);
        }
      } finally {
        if (!cancelled) setIsChecking(false);
      }
    };

    run();
    return () => {
      cancelled = true;
    };
  }, [open, file?.id, destFolderId, moveName]);

  const suggestions = useMemo(() => {
    if (!file) return [];
    if (!moveName.trim()) return [];
    if (!hasDup) return [];
    return suggestAvailableNames(moveName.trim(), destNamesSet, 5);
  }, [file, moveName, hasDup, destNamesSet]);

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

  const close = () =>
    setState({ open: false, item: null, target: "root", createName: "", creating: false, moving: false });

  return (
    <ModalShell open={open} title="انتقال به پوشه" onClose={close} maxWidth="max-w-lg">
      <div className="space-y-4 text-sm">
        <div className="rounded-xl border border-black/10 dark:border-white/10 bg-white/60 dark:bg-[#16325B]/50 p-3">
          <div className="text-black/70 dark:text-white/80 text-xs mb-1">فایل</div>
          <div className="font-extrabold truncate">{file?.name || "-"}</div>
        </div>

        {/* ✅ نام فایل در مقصد (rename-before-move) */}
        <div className="space-y-2">
          <div className="text-xs text-black/60 dark:text-white/70">نام فایل در مقصد</div>

          <input
            value={moveName}
            onChange={(e) => setMoveName(e.target.value)}
            className={`w-full rounded-xl border bg-white dark:bg-[#001F3F] px-3 py-2 outline-none dark:text-white ${
              hasDup ? "border-red-500/60" : "border-black/10 dark:border-white/10"
            }`}
            placeholder="نام فایل"
          />

          <div className="flex items-center justify-between text-xs">
            <span className={`font-semibold ${hasDup ? "text-red-500" : "text-black/50 dark:text-white/50"}`}>
              {isChecking ? "در حال بررسی نام..." : hasDup ? "نام تکراری در مقصد" : "نام آزاد"}
            </span>
          </div>

          {/* ✅ پیشنهاد نام آزاد */}
          {hasDup && (
            <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">
                فایلی با همین نام در پوشه مقصد وجود دارد. یکی از نام‌های آزاد زیر را انتخاب کن:
              </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="space-y-2">
          <div className="text-xs text-black/60 dark:text-white/70">انتقال به</div>

          <select
            value={targetValue}
            onChange={(e) => setState((p) => ({ ...p, target: e.target.value }))}
            className="w-full rounded-xl border border-black/10 dark:border-white/10 bg-white dark:bg-[#001F3F] px-3 py-2 outline-none dark:text-white"
          >
            <option value="root">📌 ریشه</option>
            {options.map((o) => (
              <option key={o.id} value={o.id}>
                {o.label}
              </option>
            ))}
          </select>
        </div>

        {/* ساخت پوشه */}
        <div className="rounded-xl border border-black/10 dark:border-white/10 bg-white/60 dark:bg-[#16325B]/50 p-3 space-y-2">
          <div className="text-xs text-black/60 dark:text-white/70">ساخت پوشه جدید (اختیاری)</div>

          <div className="flex gap-2">
            <input
              value={state?.createName ?? ""}
              onChange={(e) => setState((p) => ({ ...p, createName: e.target.value }))}
              className="flex-1 rounded-xl border border-black/10 dark:border-white/10 bg-white dark:bg-[#001F3F] px-3 py-2 outline-none dark:text-white"
              placeholder="نام پوشه جدید"
            />
            <button
              type="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={state?.creating || !String(state?.createName || "").trim()}
              onClick={async () => {
                const name = String(state?.createName || "").trim();
                if (!name) return;

                setState((p) => ({ ...p, creating: true }));
                try {
                  await onCreateFolder?.(name, state?.target ?? "root");
                  setState((p) => ({ ...p, createName: "" }));
                } finally {
                  setState((p) => ({ ...p, creating: false }));
                }
              }}
            >
              {state?.creating ? "درحال ساخت..." : "ساخت"}
            </button>
          </div>
        </div>

        <div className="flex gap-2 justify-end">
          <button
            type="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={close}
            disabled={state?.moving}
          >
            لغو
          </button>

          <button
            type="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={state?.moving || !file || isChecking || hasDup || !String(moveName || "").trim()}
            onClick={async () => {
              if (!file) return;

              const newName = String(moveName || "").trim();
              if (!newName) {
                toastError("نام فایل را وارد کنید.", { title: "انتقال" });
                return;
              }
              if (hasDup) {
                toastError("نام فایل در مقصد تکراری است. یکی از پیشنهادها را انتخاب کنید یا نام را تغییر دهید.", {
                  title: "نام تکراری",
                });
                return;
              }

              setState((p) => ({ ...p, moving: true }));
              try {
                // ✅ اگر اسم عوض شده → اول rename
                if (newName !== (file?.name || "")) {
                  await renameFile(file.id, newName);
                }

                // ✅ سپس move
                const dest = state?.target === "root" ? null : state?.target;
                await onMove?.(file, dest);

                close();
              } finally {
                setState((p) => ({ ...p, moving: false }));
              }
            }}
          >
            {state?.moving ? "درحال انتقال..." : isChecking ? "درحال بررسی..." : hasDup ? "نام تکراری" : "انتقال"}
          </button>
        </div>

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