import { t } from "../../../app/i18n.js";
import { createPanelStateBridge } from "../../../stores/panelStateBridge.js";

export function createBrowserNavigationController({
    state,
    gridContainer,
    folderBreadcrumb,
    folderBreadcrumbController = null,
    customSelect,
    reloadGrid,
    clearSelection = null,
    onContextChanged = null,
    lifecycleSignal = null,
}: Record<string, any> = {}): Record<string, any> {
    const { read, write } = createPanelStateBridge(state, [
        "scope",
        "customRootId",
        "currentFolderRelativePath",
    ]);
    const folderBackStack: any[] = [];

    const normPath = (value: any) =>
        String(value || "")
            .trim()
            .replaceAll("\\", "/");
    const isWindowsDrive = (part: any) => /^[a-zA-Z]:$/.test(String(part || "").trim());
    const currentFolderPath = () => normPath(read("currentFolderRelativePath", "") || "");

    const pushUniqueHistory = (stack: any, value: any) => {
        const v = normPath(value);
        if (!Array.isArray(stack)) return;
        if (!v && v !== "") return;
        const top = stack.length ? normPath(stack[stack.length - 1]) : null;
        if (top === v) return;
        stack.push(v);
    };

    const popDistinctHistory = (stack: any, current: any) => {
        const cur = normPath(current);
        if (!Array.isArray(stack)) return null;
        while (stack.length) {
            const candidate = normPath(stack.pop());
            if (candidate !== cur) return candidate;
        }
        return null;
    };

    const setFolderPath = (next: any) => {
        const v = normPath(next);
        write("currentFolderRelativePath", v);
        try {
            if (gridContainer?.dataset) gridContainer.dataset.mjrSubfolder = v;
        } catch (e) {
            console.debug?.(e);
        }
    };

    const resolveFolderTargetPath = (asset: any) => {
        const rawSubfolder = normPath(asset?.subfolder || "");
        if (rawSubfolder) return rawSubfolder;

        const rawFilepath = normPath(asset?.filepath || asset?.path || "");
        if (rawFilepath) {
            const kind = String(asset?.kind || "").toLowerCase();
            if (kind === "folder") return rawFilepath;
            // Defensive fallback: if a file path is emitted, browse its parent folder.
            const parent = parentFolderPath(rawFilepath);
            return parent || rawFilepath;
        }

        const name = normPath(asset?.filename || "");
        if (!name) return currentFolderPath();
        const base = currentFolderPath();
        if (!base) return name;
        return `${base}/${name}`.replace(/\/{2,}/g, "/");
    };

    const parentFolderPath = (pathValue: any) => {
        const cur = normPath(pathValue);
        if (!cur) return "";
        const parts = cur.split("/").filter(Boolean);
        if (!parts.length) return "";
        if (parts.length === 1) return isWindowsDrive(parts[0]) ? `${parts[0]}/` : "";
        parts.pop();
        if (parts.length === 1 && isWindowsDrive(parts[0])) return `${parts[0]}/`;
        return parts.join("/");
    };

    const notifyContext = () => {
        try {
            onContextChanged?.();
        } catch (e) {
            console.debug?.(e);
        }
        try {
            renderBreadcrumb();
        } catch (e) {
            console.debug?.(e);
        }
    };

    const resetGridScrollToTop = () => {
        try {
            if (gridContainer && typeof gridContainer.scrollTop === "number") {
                gridContainer.scrollTop = 0;
            }
        } catch (e) {
            console.debug?.(e);
        }
        try {
            const parent = gridContainer?.parentElement || null;
            if (parent && typeof parent.scrollTop === "number") {
                parent.scrollTop = 0;
            }
        } catch (e) {
            console.debug?.(e);
        }
    };

    const navigateFolder = async (target: any, { pushHistory = true } = {}) => {
        const prev = currentFolderPath();
        const next = normPath(target);
        if (prev === next) return;
        if (pushHistory) pushUniqueHistory(folderBackStack, prev);
        setFolderPath(next);
        resetGridScrollToTop();
        notifyContext();
        try {
            clearSelection?.();
        } catch (e) {
            console.debug?.(e);
        }
        await reloadGrid?.();
    };

    const resetToBrowserRoot = async () => {
        write("customRootId", "");
        setFolderPath("");
        resetGridScrollToTop();
        notifyContext();
        try {
            clearSelection?.();
        } catch (e) {
            console.debug?.(e);
        }
        await reloadGrid?.();
    };

    const setVueBreadcrumb = (payload: any) => {
        if (typeof folderBreadcrumbController?.setFolderBreadcrumb !== "function") return false;
        try {
            folderBreadcrumbController.setFolderBreadcrumb(payload);
            return true;
        } catch (e) {
            console.debug?.(e);
            return false;
        }
    };

    const renderBreadcrumb = () => {
        const isCustom = String(read("scope", "") || "") === "custom";
        const rel = String(read("currentFolderRelativePath", "") || "")
            .trim()
            .replaceAll("\\", "/");
        const folderBrowsingActive = isCustom || !!rel;
        const selectedRootId = String(read("customRootId", "") || "").trim();
        const selectedRootLabel = (() => {
            if (!selectedRootId) return "";
            try {
                const opt = customSelect?.selectedOptions?.[0] || null;
                return String(opt?.textContent || "").trim();
            } catch {
                return "";
            }
        })();

        if (!folderBrowsingActive) {
            folderBackStack.length = 0;
            if (setVueBreadcrumb({ visible: false })) return;
            folderBreadcrumb.style.display = "none";
            folderBreadcrumb.replaceChildren();
            return;
        }

        const hasSelectedRoot = !!String(read("customRootId", "") || "").trim();
        const canBackToBrowserRoot = hasSelectedRoot && !rel;
        const canBackByPath = !!rel;
        const backDisabled =
            folderBackStack.length === 0 && !canBackToBrowserRoot && !canBackByPath;
        const upDisabled = !rel || parentFolderPath(currentFolderPath()) === currentFolderPath();

        const handleBack = async () => {
            const prev = popDistinctHistory(folderBackStack, currentFolderPath());
            if (prev != null) {
                await navigateFolder(prev, { pushHistory: false });
                return;
            }
            const cur = currentFolderPath();
            if (cur) {
                const parent = parentFolderPath(cur);
                if (parent === cur) {
                    if (hasSelectedRoot) await resetToBrowserRoot();
                    return;
                }
                await navigateFolder(parent, { pushHistory: false });
                return;
            }
            if (canBackToBrowserRoot) await resetToBrowserRoot();
        };

        const handleUp = async () => {
            const parent = parentFolderPath(currentFolderPath());
            if (parent === currentFolderPath()) {
                if (hasSelectedRoot) await resetToBrowserRoot();
                return;
            }
            await navigateFolder(parent);
        };

        const buildItem = (label: any, target: any, isCurrent = false) => ({
            label: String(label || ""),
            target: String(target || ""),
            current: !!isCurrent,
            onClick: async () => {
                if (label === "Computer" && String(read("customRootId", "") || "").trim()) {
                    await resetToBrowserRoot();
                    return;
                }
                await navigateFolder(target);
            },
        });

        const breadcrumbItems = [buildItem(t("label.computer", "Computer"), "", !rel)];
        if (selectedRootId) {
            breadcrumbItems.push(buildItem(selectedRootLabel || selectedRootId, "", !rel));
        }
        if (rel) {
            const parts = rel.split("/").filter(Boolean);
            let acc = "";
            for (let i = 0; i < parts.length; i++) {
                if (!acc) acc = isWindowsDrive(parts[i]) ? `${parts[i]}/` : parts[i];
                else acc = `${acc}/${parts[i]}`.replace(/\/{2,}/g, "/");
                breadcrumbItems.push(buildItem(parts[i], acc, i === parts.length - 1));
            }
        }

        if (
            setVueBreadcrumb({
                visible: true,
                back: {
                    label: t("btn.back", "Back"),
                    disabled: backDisabled,
                    onClick: handleBack,
                },
                up: {
                    label: t("btn.up", "Up"),
                    disabled: upDisabled,
                    onClick: handleUp,
                },
                items: breadcrumbItems,
            })
        ) {
            return;
        }

        folderBreadcrumb.style.display = "flex";
        folderBreadcrumb.replaceChildren();

        const backBtn = document.createElement("button");
        backBtn.type = "button";
        backBtn.textContent = t("btn.back", "Back");
        backBtn.className = "mjr-btn-link mjr-folder-breadcrumb-action";
        backBtn.disabled = backDisabled;
        backBtn.addEventListener("click", handleBack, { signal: lifecycleSignal || undefined });
        folderBreadcrumb.appendChild(backBtn);

        const upBtn = document.createElement("button");
        upBtn.type = "button";
        upBtn.textContent = t("btn.up", "Up");
        upBtn.className = "mjr-btn-link mjr-folder-breadcrumb-action";
        upBtn.disabled = upDisabled;
        upBtn.addEventListener("click", handleUp, { signal: lifecycleSignal || undefined });
        folderBreadcrumb.appendChild(upBtn);

        const sep0 = document.createElement("span");
        sep0.textContent = "|";
        sep0.className = "mjr-folder-breadcrumb-separator";
        folderBreadcrumb.appendChild(sep0);

        const mk = (label: any, target: any, isCurrent = false) => {
            const el = document.createElement("button");
            el.type = "button";
            el.textContent = label;
            el.className = isCurrent
                ? "mjr-btn-link mjr-folder-breadcrumb-segment is-current"
                : "mjr-btn-link mjr-folder-breadcrumb-segment";
            if (!isCurrent) {
                el.addEventListener(
                    "click",
                    async () => {
                        if (label === "Computer" && String(read("customRootId", "") || "").trim()) {
                            await resetToBrowserRoot();
                            return;
                        }
                        await navigateFolder(target);
                    },
                    { signal: lifecycleSignal || undefined },
                );
            } else {
                el.disabled = true;
            }
            return el;
        };

        for (let i = 0; i < breadcrumbItems.length; i++) {
            if (i > 0) {
                const sep = document.createElement("span");
                sep.textContent = "/";
                sep.className = "mjr-folder-breadcrumb-separator";
                folderBreadcrumb.appendChild(sep);
            }
            const item = breadcrumbItems[i];
            folderBreadcrumb.appendChild(mk(item.label, item.target, item.current));
        }
    };

    const bindGridFolderNavigation = () => {
        const onOpenFolderAsset = async (e: any) => {
            const asset = e?.detail?.asset || null;
            const target = resolveFolderTargetPath(asset || {});
            const prev = currentFolderPath();
            if (target !== prev) {
                pushUniqueHistory(folderBackStack, prev);
                setFolderPath(target);
                resetGridScrollToTop();
                notifyContext();
                try {
                    clearSelection?.();
                } catch (e) {
                    console.debug?.(e);
                }
                try {
                    await reloadGrid?.();
                } catch (e) {
                    console.debug?.(e);
                }
            }
        };

        const onCustomSubfolderChanged = async (e: any) => {
            const next = String(e?.detail?.subfolder || "")
                .trim()
                .replaceAll("\\", "/");
            const prev = currentFolderPath();
            if (next !== prev) {
                pushUniqueHistory(folderBackStack, prev);
                setFolderPath(next);
                resetGridScrollToTop();
                notifyContext();
                try {
                    clearSelection?.();
                } catch (e) {
                    console.debug?.(e);
                }
                try {
                    await reloadGrid?.();
                } catch (e) {
                    console.debug?.(e);
                }
            }
        };
        gridContainer?.addEventListener?.(
            "mjr:custom-subfolder-changed",
            onCustomSubfolderChanged,
            {
                signal: lifecycleSignal || undefined,
            },
        );
        gridContainer?.addEventListener?.("mjr:open-folder-asset", onOpenFolderAsset, {
            signal: lifecycleSignal || undefined,
        });
        try {
            gridContainer._mjrHasCustomSubfolderHandler = true;
        } catch (e) {
            console.debug?.(e);
        }
        return () => {
            try {
                gridContainer?.removeEventListener?.(
                    "mjr:custom-subfolder-changed",
                    onCustomSubfolderChanged,
                );
            } catch (e) {
                console.debug?.(e);
            }
            try {
                gridContainer?.removeEventListener?.("mjr:open-folder-asset", onOpenFolderAsset);
            } catch (e) {
                console.debug?.(e);
            }
            try {
                gridContainer._mjrHasCustomSubfolderHandler = false;
            } catch (e) {
                console.debug?.(e);
            }
        };
    };

    return {
        renderBreadcrumb,
        resetHistory: () => {
            folderBackStack.length = 0;
        },
        bindGridFolderNavigation,
        notifyContext,
    };
}
