import { app } from "../../scripts/app.js";

/**
 * 一个简单的“转换工作流”按钮（用于“无影DiT加速推理”提示）
 * - 默认放在 ComfyUI 顶部 toolbar 内
 * - 支持拖拽为“浮动”模式，位置可移动并持久化
 * - 点击后弹出“加速限制提示弹窗”，可选择不再提示；继续加速将在当前标签页打开加速后的工作流（保留原本大逻辑）
 */
class MovableTransformButtonExtension {
    constructor() {
        this.buttonEl = null;
        this.drag = {
            active: false,
            startX: 0,
            startY: 0,
            offsetX: 0,
            offsetY: 0,
        };
        this.storageKey = "comfy_transform_btn_position";
        this.skipWarnKey = "comfy_transform_accel_skip";
        this.toolbarObserver = null;
        this.init();
    }

    async init() {
        await this.mountButtonWhenReady();
        this.observeToolbar();
    }

    // ============== Toolbar 定位 ==============
    findToolbar() {
        const candidates = [
            '.actionbar-container',
            "#comfy-toolbar",
            ".comfyui-toolbar",
            "#comfyui-menu",
            ".comfyui-menu",
            "#top-bar",
            "#comfyui-top-bar",
            '[data-testid="comfyui-toolbar"]',
        ];
        for (const sel of candidates) {
            const el = document.querySelector(sel);
            if (el) return el;
        }
        const maybeTop = document.querySelector("body > div, body > header");
        if (maybeTop && maybeTop.querySelector("button")) return maybeTop;
        return null;
    }

    // 将按钮插入到工具栏的 comfyui-menu-right 前面
    insertButtonToToolbar(toolbar) {
        if (!toolbar || !this.buttonEl) return false;
        
        // 查找 comfyui-menu-right 元素
        const menuRight = toolbar.querySelector('.comfyui-menu-right');
        const menuCenter = toolbar.querySelector('.items-center');
        
        if (menuRight) {
            // 插入到 comfyui-menu-right 前面
            toolbar.insertBefore(this.buttonEl, menuRight);
            return true;
        } else if (menuCenter) {
            // 插入到 menuCenter 前面
            toolbar.insertBefore(this.buttonEl, menuCenter);
            return true;
        } else {
            // 如果找不到 comfyui-menu-right，则添加到工具栏末尾
            toolbar.appendChild(this.buttonEl);
            return true;
        }
    }

    waitForToolbar(timeoutMs = 5000, intervalMs = 100) {
        return new Promise((resolve) => {
            const t0 = Date.now();
            const tick = () => {
                const bar = this.findToolbar();
                if (bar) return resolve(bar);
                if (Date.now() - t0 >= timeoutMs) return resolve(null);
                setTimeout(tick, intervalMs);
            };
            tick();
        });
    }

    async mountButtonWhenReady() {
        const saved = this.getSavedPosition();
        const toolbar = await this.waitForToolbar();

        this.createButton();

        if (saved?.mode === "floating") {
            document.body.appendChild(this.buttonEl);
            this.applyFloatingStyles();
            this.setFloatingPosition(saved.x ?? 16, saved.y ?? 16);
        } else if (toolbar) {
            this.insertButtonToToolbar(toolbar);
            this.applyToolbarStyles();
            this.savePosition({ mode: "toolbar" });
        } else {
            document.body.appendChild(this.buttonEl);
            this.applyFloatingStyles();
            this.setFloatingPosition(16, 16);
            this.savePosition({ mode: "floating", x: 16, y: 16 });
        }
    }

    observeToolbar() {
        if (this.toolbarObserver) this.toolbarObserver.disconnect();

        this.toolbarObserver = new MutationObserver(() => {
            const saved = this.getSavedPosition();
            if (saved?.mode !== "toolbar") return;

            const toolbar = this.findToolbar();
            if (!toolbar || !this.buttonEl) return;
            if (this.buttonEl.parentElement !== toolbar) {
                this.insertButtonToToolbar(toolbar);
                this.applyToolbarStyles();
            }
        });

        this.toolbarObserver.observe(document.documentElement || document.body, {
            childList: true,
            subtree: true,
        });
    }

    // ============== 本地持久化 ==============
    getSavedPosition() {
        try {
            const raw = localStorage.getItem(this.storageKey);
            return raw ? JSON.parse(raw) : null;
        } catch {
            return null;
        }
    }

    savePosition(data) {
        try {
            localStorage.setItem(this.storageKey, JSON.stringify(data));
        } catch {}
    }

    shouldSkipAccelWarn() {
        try {
            return localStorage.getItem(this.skipWarnKey) === "1";
        } catch {
            return false;
        }
    }

    setSkipAccelWarn(v) {
        try {
            if (v) localStorage.setItem(this.skipWarnKey, "1");
            else localStorage.removeItem(this.skipWarnKey);
        } catch {}
    }

    // ============== 按钮与样式 ==============
    createButton() {
        if (this.buttonEl) return;

        // 创建容器（徽章样式）
        const badge = document.createElement("div");
        badge.id = "comfy-transform-workflow-btn";
        badge.title = "启动无影DiT加速推理\n点击后将显示加速限制提示弹窗（可选择不再提示）";
        
        // 容器样式
        badge.style.cssText = `
            border-radius: 2px;
            background: linear-gradient(99deg, #355DFF, #52BDFF);
            display: flex;
            flex-direction: row;
            width: fit-content;
            box-sizing: border-box;
            padding: 0 8px;
            justify-content: center;
            align-items: center;
            min-width: 126px;
            height: 27px;
            cursor: pointer;
            user-select: none;
            transition: transform 0.2s ease, box-shadow 0.2s ease;
        `;

        // 创建内容区域
        const badgeContent = document.createElement("div");
        badgeContent.style.cssText = `
            display: flex;
            flex-direction: row;
            width: fit-content;
            gap: 2px;
            justify-content: center;
            align-items: center;
            min-width: 110px;
            height: 27px;
        `;

        // 创建图标
        const badgeIcon = document.createElement("img");
        badgeIcon.src = "https://img.alicdn.com/imgextra/i3/6000000003454/O1CN01EklNUh1bNz7CEuCp8_!!6000000003454-2-gg_dtc.png";
        badgeIcon.alt = "icon";
        badgeIcon.style.cssText = `
            width: 16px;
            height: 16px;
        `;

        // 创建文本
        const badgeText = document.createElement("span");
        badgeText.textContent = "无影DiT加速推理";
        badgeText.style.cssText = `
            font-size: 12px;
            font-weight: 500;
            line-height: 20px;
            color: #FFFFFF;
            white-space: nowrap;
        `;

        // 组装结构
        badgeContent.appendChild(badgeIcon);
        badgeContent.appendChild(badgeText);
        badge.appendChild(badgeContent);

        // Hover 效果
        badge.addEventListener("mouseenter", () => {
            badge.style.transform = "translateY(-1px)";
            badge.style.boxShadow = "0 4px 12px rgba(53, 93, 255, 0.4)";
        });
        badge.addEventListener("mouseleave", () => {
            badge.style.transform = "translateY(0)";
            badge.style.boxShadow = "none";
        });

        // 点击事件
        badge.addEventListener("click", async (e) => {
            if (this.drag.active) return;
            await this.handleTransform(badge);
        });

        // 右键和双击回到工具栏
        badge.addEventListener("contextmenu", (e) => {
            e.preventDefault();
            this.snapToToolbar();
        });
        badge.addEventListener("dblclick", () => this.snapToToolbar());

        // 拖拽事件
        // badge.addEventListener("pointerdown", (e) => this.onDragStart(e));
        // window.addEventListener("pointermove", (e) => this.onDragMove(e));
        // window.addEventListener("pointerup", () => this.onDragEnd());

        this.buttonEl = badge;
    }

    applyToolbarStyles() {
        const badge = this.buttonEl;
        if (!badge) return;
        
        // 只重置位置相关样式，保留徽章样式
        badge.style.position = "";
        badge.style.left = "";
        badge.style.top = "";
        badge.style.zIndex = "";
        badge.style.marginLeft = "6px";
        
        // 保持徽章的渐变背景和其他样式不变
        // hover 效果已在 createButton 中定义
    }

    applyFloatingStyles() {
        const badge = this.buttonEl;
        if (!badge) return;

        // 浮动模式：只设置位置和阴影
        badge.style.position = "fixed";
        badge.style.zIndex = "10000";
        badge.style.boxShadow = "0 6px 16px rgba(0,0,0,0.35)";
        
        // 保持徽章的渐变背景和其他样式不变
        // hover 效果已在 createButton 中定义
    }

    // 辅助方法：更新徽章文本
    updateBadgeText(text) {
        if (!this.buttonEl) return;
        const textElement = this.buttonEl.querySelector("span");
        if (textElement) {
            textElement.textContent = text;
        }
    }

    // 辅助方法：获取徽章文本
    getBadgeText() {
        if (!this.buttonEl) return "";
        const textElement = this.buttonEl.querySelector("span");
        return textElement ? textElement.textContent : "";
    }

    setFloatingPosition(x, y) {
        const btn = this.buttonEl;
        if (!btn) return;

        const rect = btn.getBoundingClientRect();
        const maxX = Math.max(0, window.innerWidth - rect.width - 4);
        const maxY = Math.max(0, window.innerHeight - rect.height - 4);

        const clampedX = Math.min(Math.max(4, x), maxX);
        const clampedY = Math.min(Math.max(4, y), maxY);

        btn.style.left = `${clampedX}px`;
        btn.style.top = `${clampedY}px`;
    }

    snapToToolbar() {
        const toolbar = this.findToolbar();
        if (!this.buttonEl) return;

        if (toolbar) {
            this.insertButtonToToolbar(toolbar);
            this.applyToolbarStyles();
            this.savePosition({ mode: "toolbar" });
        } else {
            document.body.appendChild(this.buttonEl);
            this.applyFloatingStyles();
            this.setFloatingPosition(12, 12);
            this.savePosition({ mode: "floating", x: 12, y: 12 });
        }
    }

    // ============== 工作流转换（通过后端 Python） ==============
    getCurrentWorkflow() {
        if (app?.graph?.serialize) {
            return app.graph.serialize();
        }
        throw new Error("无法获取当前工作流（app.graph.serialize 不可用）");
    }

    /**
     * 向后端请求转换，返回后端整个响应 data 对象（包含 ok, workflow, conversion_result 等）
     */
    async requestTransformOnServer(workflow) {
        const res = await fetch(`${window.location.origin}/workflow/transform`, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ workflow }),
        });
        if (!res.ok) {
            const text = await res.text().catch(() => "");
            throw new Error(`后端返回错误状态：${res.status} ${text}`);
        }
        const data = await res.json();
        // 如果后端明确标注已经转换（即 conversion_result 为特定值），直接返回 data 让前端处理提示
        if (data?.conversion_result === "FAILURE_ALREADY_CONVERTED") {
            return data;
        }
        if (data?.conversion_result === "FAILED") {

          // 加速失败，聚焦相关节点
          if (
            data.related_nodes_id &&
            Array.isArray(data.related_nodes_id) &&
            data.related_nodes_id.length > 0
          ) {
            this.focusNodesByIds(data.related_nodes_id);
          }
          // 加速失败，显示手动配置引导弹窗
          this.showGuideModal();
          return data;
        }

        // 否则要求 ok 为真且包含 workflow
        if (!data?.ok) throw new Error(data?.error || "后端返回失败");
        if (!data?.workflow) throw new Error("后端响应缺少 workflow 字段");
        return data;
    }

    async openWorkflow(workflow) {
        if (typeof app?.loadGraphData === "function") {
            await app.loadGraphData(workflow);
            return;
        }
        if (app?.graph?.configure) {
            app.graph.clear?.();
            app.graph.configure(workflow);
            app.graph.setDirtyCanvas?.(true, true);
            return;
        }
        throw new Error("无法打开工作流（app.loadGraphData / app.graph.configure 不可用）");
    }

    // ============== 弹窗（提示） ==============
    /**
     * 弹出加速限制提示弹窗，返回 Promise<boolean>：
     *  - true: 继续加速（在当前标签页打开加速工作流）
     *  - false: 取消加速（仅关闭弹窗）
     *
     * 勾选“不再提醒”会持久化到 localStorage。
     */
    promptAcceleration() {
        return new Promise((resolve) => {
            // 如果用户已选择跳过提示，直接 resolve true
            if (this.shouldSkipAccelWarn()) return resolve(true);

            // 如果已有弹窗则不重复创建
            if (document.getElementById("comfy-accel-modal")) {
                return resolve(false);
            }

            // 创建遮罩
            const overlay = document.createElement("div");
            overlay.id = "comfy-accel-modal-overlay";
            overlay.style.cssText = `
                position: fixed;
                left: 0;
                top: 0;
                right: 0;
                bottom: 0;
                background: rgba(0, 0, 0, 0.4);
                z-index: 20000;
                display: flex;
                align-items: center;
                justify-content: center;
            `;

            // 容器
            const container = document.createElement("div");
            container.id = "comfy-accel-modal";
            container.style.cssText = `
                border-radius: 4px;
                background: #1F2024;
                box-shadow: 0px 6px 16px 0px rgba(0, 0, 0, 0.08);
                display: flex;
                flex-direction: column;
                height: fit-content;
                overflow: hidden;
                width: 480px;
                min-height: 310px;
            `;

            // 内容区域
            const content = document.createElement("div");
            content.style.cssText = `
                display: flex;
                flex-direction: row;
                gap: 8px;
                box-sizing: border-box;
                padding: 20px 24px 16px 24px;
                position: relative;
                width: 480px;
                min-height: 258px;
            `;

            // 主图标
            const icon = document.createElement("img");
            icon.src = "https://img.alicdn.com/imgextra/i3/6000000000593/O1CN01tx15kF1GFdyH2RnUN_!!6000000000593-2-gg_dtc.png";
            icon.alt = "icon";
            icon.style.cssText = `
                width: 24px;
                height: 24px;
            `;

            // 文本容器
            const textContainer = document.createElement("div");
            textContainer.style.cssText = `
                display: flex;
                flex-direction: column;
                gap: 16px;
                box-sizing: border-box;
                padding: 0 0 20px 0;
                flex: 1;
                width: 400px;
                min-height: 222px;
            `;

            // 标题
            const title = document.createElement("span");
            title.textContent = "无影DiT加速推理";
            title.style.cssText = `
                font-size: 16px;
                font-weight: 600;
                line-height: 24px;
                color: #FFFFFF;
                white-space: nowrap;
            `;

            // 描述
            const description = document.createElement("span");
            description.textContent = "启动无影DiT加速推理后自动在工作流中增加无影DiT加速节点，可提升训练与推理效率。";
            description.style.cssText = `
                font-size: 14px;
                font-weight: 400;
                line-height: 22px;
                color: #FFFFFF;
                width: 400px;
                display: -webkit-box;
                height: 44px;
                -webkit-line-clamp: 2;
                -webkit-box-orient: vertical;
                white-space: pre-wrap;
                word-break: break-all;
                text-overflow: ellipsis;
                overflow: hidden;
            `;

            // 支持部分
            const supportSection = document.createElement("div");
            supportSection.style.cssText = `
                display: flex;
                flex-direction: column;
                gap: 8px;
                width: 400px;
                min-height: 102px;
            `;

            const supportText = document.createElement("span");
            supportText.textContent = "当前支持以下底模，后续将不断升级可支持加速的底模类型。";
            supportText.style.cssText = `
                font-size: 14px;
                font-weight: 400;
                line-height: 22px;
                color: #FFFFFF;
                white-space: nowrap;
            `;

            // 模型列表
            const modelList = document.createElement("div");
            modelList.style.cssText = `
                display: flex;
                flex-direction: column;
                gap: 8px;
                width: 400px;
                min-height: 72px;
            `;

            // 模型数据
            const models = [
                [
                    { icon: "https://img.alicdn.com/imgextra/i1/6000000001547/O1CN01xDtz5h1NIZolwfISg_!!6000000001547-2-gg_dtc.png", text: "qwen_image_edit" },
                    { icon: "https://img.alicdn.com/imgextra/i1/6000000001547/O1CN01xDtz5h1NIZolwfISg_!!6000000001547-2-gg_dtc.png", text: "wan2.1、wan2.2" }
                ],
                [
                    { icon: "https://img.alicdn.com/imgextra/i4/6000000001029/O1CN01HiG8jv1JTKehtsOLK_!!6000000001029-2-gg_dtc.png", text: "hunyuan_video" },
                    { icon: "https://img.alicdn.com/imgextra/i1/6000000005496/O1CN01MpRPJA1qTDsiFVO0M_!!6000000005496-2-gg_dtc.png", text: "Flux1.0" }
                ]
            ];

            models.forEach(row => {
                const modelRow = document.createElement("div");
                modelRow.style.cssText = `
                    display: flex;
                    flex-direction: row;
                    gap: 8px;
                    width: 400px;
                    min-height: 32px;
                `;

                row.forEach(model => {
                    const modelItem = document.createElement("div");
                    modelItem.style.cssText = `
                        border-radius: 4px;
                        background: #353539;
                        display: flex;
                        flex-direction: row;
                        gap: 4px;
                        box-sizing: border-box;
                        padding: 4px 8px;
                        flex: 1;
                        width: 196px;
                        min-height: 32px;
                        align-items: center;
                    `;

                    const modelIcon = document.createElement("img");
                    modelIcon.src = model.icon;
                    modelIcon.alt = model.text;
                    modelIcon.style.cssText = `
                        width: 24px;
                        height: 24px;
                    `;

                    const modelText = document.createElement("span");
                    modelText.textContent = model.text;
                    modelText.style.cssText = `
                        font-size: 14px;
                        font-weight: 400;
                        line-height: 22px;
                        color: #FFFFFF;
                        white-space: nowrap;
                        flex: 1;
                    `;

                    modelItem.appendChild(modelIcon);
                    modelItem.appendChild(modelText);
                    modelRow.appendChild(modelItem);
                });

                modelList.appendChild(modelRow);
            });

            supportSection.appendChild(supportText);
            supportSection.appendChild(modelList);

            textContainer.appendChild(title);
            textContainer.appendChild(description);
            textContainer.appendChild(supportSection);

            // 关闭图标
            const closeIcon = document.createElement("img");
            closeIcon.src = "https://img.alicdn.com/imgextra/i3/6000000004392/O1CN01iiZOEm1iJacoA66LH_!!6000000004392-2-gg_dtc.png";
            closeIcon.alt = "close";
            closeIcon.style.cssText = `
                width: 24px;
                height: 24px;
                position: absolute;
                right: 12px;
                top: 12px;
                cursor: pointer;
                transition: opacity 0.2s;
            `;
            closeIcon.addEventListener("mouseenter", () => closeIcon.style.opacity = "0.7");
            closeIcon.addEventListener("mouseleave", () => closeIcon.style.opacity = "1");

            content.appendChild(icon);
            content.appendChild(textContainer);
            content.appendChild(closeIcon);

            // 底部区域
            const footer = document.createElement("div");
            footer.style.cssText = `
                display: flex;
                flex-direction: row;
                box-sizing: border-box;
                padding: 0 24px 20px 56px;
                justify-content: space-between;
                align-items: center;
                width: 480px;
                min-height: 52px;
            `;

            // Checkbox 容器
            const checkboxContainer = document.createElement("label");
            checkboxContainer.style.cssText = `
                display: flex;
                flex-direction: row;
                align-items: center;
                min-width: 80px;
                min-height: 22px;
                cursor: pointer;
            `;

            // 创建自定义复选框容器
            const checkboxWrapper = document.createElement("div");
            checkboxWrapper.style.cssText = `
                position: relative;
                width: 16px;
                height: 16px;
                flex-shrink: 0;
            `;

            const checkbox = document.createElement("input");
            checkbox.type = "checkbox";
            checkbox.style.cssText = `
                appearance: none;
                border-radius: 2px;
                background: #101012;
                box-shadow: inset 0 0 0 1px #7E7E8A;
                width: 16px;
                height: 16px;
                cursor: pointer;
                margin: 0;
                position: absolute;
                top: 0;
                left: 0;
            `;

            // 创建勾选标记
            const checkmark = document.createElement("div");
            checkmark.innerHTML = `
                <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path d="M13.3333 4L6 11.3333L2.66667 8" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                </svg>
            `;
            checkmark.style.cssText = `
                position: absolute;
                top: 0;
                left: 0;
                width: 16px;
                height: 16px;
                pointer-events: none;
                opacity: 0;
                transition: opacity 0.15s ease;
            `;

            checkboxWrapper.appendChild(checkbox);
            checkboxWrapper.appendChild(checkmark);

            // Checkbox 选中样式
            checkbox.addEventListener("change", () => {
                if (checkbox.checked) {
                    checkbox.style.background = "#3391FF";
                    checkbox.style.boxShadow = "inset 0 0 0 1px #3391FF";
                    checkmark.style.opacity = "1";
                } else {
                    checkbox.style.background = "#101012";
                    checkbox.style.boxShadow = "inset 0 0 0 1px #7E7E8A";
                    checkmark.style.opacity = "0";
                }
            });

            const checkboxText = document.createElement("span");
            checkboxText.textContent = "不再提示";
            checkboxText.style.cssText = `
                font-size: 14px;
                font-weight: 400;
                line-height: 22px;
                color: #FFFFFF;
                white-space: nowrap;
                margin-left: 8px;
                user-select: none;
            `;

            checkboxContainer.appendChild(checkboxWrapper);
            checkboxContainer.appendChild(checkboxText);

            // 按钮组
            const buttonGroup = document.createElement("div");
            buttonGroup.style.cssText = `
                display: flex;
                flex-direction: row;
                gap: 8px;
                min-width: 216px;
                min-height: 32px;
            `;

            // 取消按钮
            const cancelButton = document.createElement("div");
            cancelButton.style.cssText = `
                border-radius: 8px;
                background: rgba(255, 255, 255, 0.06);
                box-shadow: inset 0 0 0 1px #353539;
                display: flex;
                box-sizing: border-box;
                padding: 0 16px;
                justify-content: center;
                align-items: center;
                min-width: 60px;
                min-height: 32px;
                cursor: pointer;
                transition: background 0.2s;
            `;
            cancelButton.addEventListener("mouseenter", () => {
                cancelButton.style.background = "rgba(255, 255, 255, 0.1)";
            });
            cancelButton.addEventListener("mouseleave", () => {
                cancelButton.style.background = "rgba(255, 255, 255, 0.06)";
            });

            const cancelText = document.createElement("span");
            cancelText.textContent = "取消";
            cancelText.style.cssText = `
                font-size: 14px;
                font-weight: 400;
                line-height: 22px;
                color: #FFFFFF;
                white-space: nowrap;
            `;
            cancelButton.appendChild(cancelText);

            // 确认按钮
            const confirmButton = document.createElement("div");
            confirmButton.style.cssText = `
                border-radius: 8px;
                background: #3391FF;
                display: flex;
                box-sizing: border-box;
                padding: 0 16px;
                justify-content: center;
                align-items: center;
                min-width: 148px;
                min-height: 32px;
                cursor: pointer;
                transition: background 0.2s;
            `;
            confirmButton.addEventListener("mouseenter", () => {
                confirmButton.style.background = "#2680E8";
            });
            confirmButton.addEventListener("mouseleave", () => {
                confirmButton.style.background = "#3391FF";
            });

            const confirmText = document.createElement("span");
            confirmText.textContent = "我知道了,继续加速";
            confirmText.style.cssText = `
                font-size: 14px;
                font-weight: 400;
                line-height: 22px;
                color: #FFFFFF;
                white-space: nowrap;
            `;
            confirmButton.appendChild(confirmText);

            buttonGroup.appendChild(cancelButton);
            buttonGroup.appendChild(confirmButton);

            footer.appendChild(checkboxContainer);
            footer.appendChild(buttonGroup);

            container.appendChild(content);
            container.appendChild(footer);
            overlay.appendChild(container);
            document.body.appendChild(overlay);

            // 关闭函数
            const closeModal = () => {
                try {
                    overlay.remove();
                } catch {}
            };

            // 事件绑定
            closeIcon.addEventListener("click", () => {
                if (checkbox.checked) this.setSkipAccelWarn(true);
                closeModal();
                resolve(false);
            });

            cancelButton.addEventListener("click", () => {
                if (checkbox.checked) this.setSkipAccelWarn(true);
                closeModal();
                resolve(false);
            });

            confirmButton.addEventListener("click", () => {
                if (checkbox.checked) this.setSkipAccelWarn(true);
                closeModal();
                resolve(true);
            });

            // 允许点遮罩关闭（等同取消）
            overlay.addEventListener("click", (ev) => {
                if (ev.target === overlay) {
                    if (checkbox.checked) this.setSkipAccelWarn(true);
                    closeModal();
                    resolve(false);
                }
            });

            // 防止点击 container 导致 overlay 的关闭处理
            container.addEventListener("click", (ev) => ev.stopPropagation());
        });
    }

    /**
     * 高亮节点库按钮
     */
    highlightNodeLibraryButton() {
        const button = document.querySelector('[aria-label="Node Library (n)"]');
        
        if (!button) return null;
        
        // 保存原始样式
        const originalStyles = {
            border: button.style.border,
            boxShadow: button.style.boxShadow,
            outline: button.style.outline
        };
        
        // 添加高亮样式
        button.style.border = "2px solid #3391FF";
        button.style.boxShadow = "0 0 12px rgba(51, 145, 255, 0.8)";
        button.style.outline = "none";
        
        // 添加脉冲动画
        if (!document.getElementById('node-library-pulse')) {
            const style = document.createElement('style');
            style.id = 'node-library-pulse';
            style.textContent = `
                @keyframes nodeLibraryPulse {
                    0%, 100% {
                        box-shadow: 0 0 8px rgba(51, 145, 255, 0.6);
                    }
                    50% {
                        box-shadow: 0 0 20px rgba(51, 145, 255, 1);
                    }
                }
            `;
            document.head.appendChild(style);
        }
        
        button.style.animation = "nodeLibraryPulse 2s infinite";
        
        // 返回清除函数
        return () => {
            button.style.border = originalStyles.border;
            button.style.boxShadow = originalStyles.boxShadow;
            button.style.outline = originalStyles.outline;
            button.style.animation = "";
        };
    }

    /**
     * 显示手动配置引导弹窗
     */
    showGuideModal() {
        // 如果已有弹窗则不重复创建
        if (document.getElementById("comfy-guide-panel")) {
            return;
        }

        const skipGuideKey = "comfy_guide_modal_skip";

        // 检查是否已选择不再提示
        const shouldSkip = localStorage.getItem(skipGuideKey) === "1";
        if (shouldSkip) {
            return;
        }

        // 高亮节点库按钮
        const clearHighlight = this.highlightNodeLibraryButton();

        // 获取左侧菜单的实际宽度
        const leftMenu = document.getElementById("comfyui-body-left");
        const leftMenuWidth = leftMenu ? leftMenu.offsetWidth : 64; // 默认 64px
        const topOffset = 40; // 顶部工具栏高度
        const panelWidth = 480;
        
        // 每次都使用初始位置
        const initialLeft = leftMenuWidth;
        const initialTop = topOffset;
        
        // 创建侧边栏提示面板（无遮罩，不阻止用户操作）
        const modal = document.createElement("div");
        modal.id = "comfy-guide-panel";
        modal.style.cssText = `
            position: fixed;
            left: ${initialLeft}px;
            top: ${initialTop}px;
            border-radius: 8px;
            background: #1F2024;
            box-shadow: 0 4px 24px rgba(0, 0, 0, 0.5), inset 0 0 0 1px #353539;
            display: flex;
            flex-direction: column;
            overflow: hidden;
            width: ${panelWidth}px;
            max-width: calc(100vw - ${leftMenuWidth + 16}px);
            height: calc(100vh - ${topOffset + 16}px);
            transform: translateX(-120%);
            transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease;
            opacity: 0;
            z-index: 10000;
            pointer-events: auto;
        `;

        // 创建内容区域（整个区域可拖动）
        const content = document.createElement("div");
        content.style.cssText = `
            display: flex;
            flex-direction: row;
            gap: 8px;
            padding: 20px 24px 16px 24px;
            position: relative;
            flex: 1;
            overflow-y: auto;
            overflow-x: hidden;
            cursor: move;
        `;
        content.title = "拖动以移动面板";

        const header = document.createElement("div");
        header.style.cssText = `
            display: flex;
            flex-direction: column;
            gap: 16px;
            flex: 1;
        `;

        // 标题区域容器
        const dragHandle = document.createElement("div");
        dragHandle.style.cssText = `
            display: flex;
            flex-direction: column;
            gap: 4px;
            user-select: none;
        `;
        
        // 标题
        const title = document.createElement("span");
        title.textContent = "无影DiT加速推理启动失败";
        title.style.cssText = `
            font-size: 16px;
            font-weight: 600;
            line-height: 24px;
            color: #FFFFFF;
        `;

        // 副标题
        const subtitle = document.createElement("span");
        subtitle.textContent = "请跟随操作指引完成手动配置无影DiT加速节点";
        subtitle.style.cssText = `
            font-size: 14px;
            font-weight: 400;
            line-height: 22px;
            color: #B6B6C7;
        `;

        // 将标题和副标题放入可拖动区域
        dragHandle.appendChild(title);
        dragHandle.appendChild(subtitle);

        // 步骤容器
        const steps = document.createElement("div");
        steps.style.cssText = `
            display: flex;
            flex-direction: column;
            gap: 8px;
            padding-bottom: 20px;
        `;

        // 步骤1
        const step1 = document.createElement("div");
        step1.style.cssText = `
            display: flex;
            flex-direction: row;
            gap: 8px;
            align-items: flex-start;
        `;
        step1.innerHTML = `
            <div style="
                border-radius: 263px;
                background: #353539;
                width: 24px;
                height: 24px;
                display: flex;
                align-items: center;
                justify-content: center;
                flex-shrink: 0;
            ">
                <span style="font-size: 16px; font-weight: 600; color: #FFFFFF;">1</span>
            </div>
            <span style="font-size: 14px; line-height: 22px; color: #B6B6C7; padding-top: 1px;">打开"节点"目录</span>
        `;

        // 步骤2（带内容）
        const step2 = document.createElement("div");
        step2.style.cssText = `
            display: flex;
            flex-direction: row;
            gap: 8px;
        `;

        const step2Indicator = document.createElement("div");
        step2Indicator.style.cssText = `
            display: flex;
            flex-direction: column;
            align-items: center;
            flex-shrink: 0;
        `;
        step2Indicator.innerHTML = `
            <div style="
                border-radius: 263px;
                background: #353539;
                width: 24px;
                height: 24px;
                display: flex;
                align-items: center;
                justify-content: center;
                margin-bottom: 8px;
            ">
                <span style="font-size: 16px; font-weight: 600; color: #FFFFFF;">2</span>
            </div>
            <div style="background: #474A52; width: 2px; flex: 1;"></div>
        `;

        const step2Content = document.createElement("div");
        step2Content.style.cssText = `
            display: flex;
            flex-direction: column;
            gap: 8px;
            padding-bottom: 20px;
            flex: 1;
        `;
        step2Content.innerHTML = `
            <span style="
                font-size: 14px;
                line-height: 22px;
                color: #B6B6C7;
                white-space: pre-wrap;
            ">将"wuyingOptim"节点拖移至右侧工作流操作区，
并放置在"Load Diffusion Model"或"Load Model"节点之后。此节点用于配置模型的有损优化级别，参数越高则推理速度越快，但会相对降低图像和视频的生成质量。</span>
            <img 
                src="https://img.alicdn.com/imgextra/i2/O1CN01ZGTcYi1wwtENfeQvP_!!6000000006373-2-tps-1280-944.png" 
                style="width: 320px; height: auto; max-width: 100%;"
                alt="操作示例图"
            />
        `;

        step2.appendChild(step2Indicator);
        step2.appendChild(step2Content);

        // 步骤3
        const step3 = document.createElement("div");
        step3.style.cssText = `
            display: flex;
            flex-direction: row;
            gap: 8px;
            align-items: flex-start;
        `;
        step3.innerHTML = `
            <div style="
                border-radius: 263px;
                background: #353539;
                width: 24px;
                height: 24px;
                display: flex;
                align-items: center;
                justify-content: center;
                flex-shrink: 0;
            ">
                <span style="font-size: 16px; font-weight: 600; color: #FFFFFF;">3</span>
            </div>
            <span style="
                font-size: 14px;
                line-height: 22px;
                color: #B6B6C7;
                white-space: pre-wrap;
                flex: 1;
            ">将"wuyingOptim"节点中的modle分别关联至"Load Model"节点和"Sample采样器"节点的modle。</span>
        `;

        steps.appendChild(step1);
        steps.appendChild(step2);
        steps.appendChild(step3);

        // 关闭按钮（更明显的样式）
        const closeIcon = document.createElement("div");
        closeIcon.textContent = "×";
        closeIcon.title = "关闭 (或按 ESC)";
        closeIcon.style.cssText = `
            width: 36px;
            height: 36px;
            position: absolute;
            right: 12px;
            top: 12px;
            cursor: pointer;
            opacity: 0.7;
            transition: all 0.2s ease;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 32px;
            color: #fff;
            border-radius: 6px;
            line-height: 1;
            user-select: none;
            background: rgba(0, 0, 0, 0.2);
        `;
        closeIcon.onmouseenter = () => {
            closeIcon.style.opacity = "1";
            closeIcon.style.background = "rgba(255, 255, 255, 0.15)";
            closeIcon.style.transform = "scale(1.1)";
        };
        closeIcon.onmouseleave = () => {
            closeIcon.style.opacity = "0.7";
            closeIcon.style.background = "rgba(0, 0, 0, 0.2)";
            closeIcon.style.transform = "scale(1)";
        };

        header.appendChild(dragHandle);
        header.appendChild(steps);
        content.appendChild(header);
        content.appendChild(closeIcon);

        // 底部区域
        const footer = document.createElement("div");
        footer.style.cssText = `
            display: flex;
            flex-direction: row;
            padding: 0 24px 20px 24px;
            justify-content: space-between;
            align-items: center;
        `;

        // 复选框
        const checkboxContainer = document.createElement("label");
        checkboxContainer.style.cssText = `
            display: flex;
            align-items: center;
            gap: 8px;
            cursor: pointer;
        `;

        // 创建自定义复选框容器
        const checkboxWrapper = document.createElement("div");
        checkboxWrapper.style.cssText = `
            position: relative;
            width: 16px;
            height: 16px;
            flex-shrink: 0;
        `;

        const checkbox = document.createElement("input");
        checkbox.type = "checkbox";
        checkbox.style.cssText = `
            appearance: none;
            border-radius: 2px;
            background: #101012;
            box-shadow: inset 0 0 0 1px #7E7E8A;
            width: 16px;
            height: 16px;
            cursor: pointer;
            margin: 0;
            position: absolute;
            top: 0;
            left: 0;
        `;

        // 创建勾选标记
        const checkmark = document.createElement("div");
        checkmark.innerHTML = `
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M13.3333 4L6 11.3333L2.66667 8" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
        `;
        checkmark.style.cssText = `
            position: absolute;
            top: 0;
            left: 0;
            width: 16px;
            height: 16px;
            pointer-events: none;
            opacity: 0;
            transition: opacity 0.15s ease;
        `;

        checkboxWrapper.appendChild(checkbox);
        checkboxWrapper.appendChild(checkmark);

        // Checkbox 选中样式
        checkbox.addEventListener("change", () => {
            if (checkbox.checked) {
                checkbox.style.background = "#3391FF";
                checkbox.style.boxShadow = "inset 0 0 0 1px #3391FF";
                checkmark.style.opacity = "1";
            } else {
                checkbox.style.background = "#101012";
                checkbox.style.boxShadow = "inset 0 0 0 1px #7E7E8A";
                checkmark.style.opacity = "0";
            }
        });

        const checkboxLabel = document.createElement("span");
        checkboxLabel.textContent = "不再提示";
        checkboxLabel.style.cssText = `
            font-size: 14px;
            line-height: 22px;
            color: #FFFFFF;
            user-select: none;
        `;

        checkboxContainer.appendChild(checkboxWrapper);
        checkboxContainer.appendChild(checkboxLabel);

        // 确认按钮
        const confirmButton = document.createElement("button");
        confirmButton.textContent = "我知道了";
        confirmButton.style.cssText = `
            border-radius: 8px;
            background: #3391FF;
            padding: 5px 16px;
            min-width: 88px;
            height: 32px;
            border: none;
            font-size: 14px;
            color: #FFFFFF;
            cursor: pointer;
            transition: background 0.2s;
        `;
        confirmButton.onmouseenter = () => confirmButton.style.background = "#2680e8";
        confirmButton.onmouseleave = () => confirmButton.style.background = "#3391FF";

        footer.appendChild(checkboxContainer);
        footer.appendChild(confirmButton);

        // 组装侧边栏
        modal.appendChild(content);
        modal.appendChild(footer);
        
        // 添加到页面
        document.body.appendChild(modal);

        // ===== 拖动功能 =====
        let isDragging = false;
        let dragStartX = 0;
        let dragStartY = 0;
        let modalStartLeft = 0;
        let modalStartTop = 0;

        // 开始拖动
        const onDragStart = (e) => {
            // 防止拖动关闭按钮、确认按钮、复选框时触发
            if (e.target === closeIcon || closeIcon.contains(e.target)) {
                return;
            }
            
            // 防止在点击按钮或复选框时触发拖动
            if (e.target.tagName === 'BUTTON' || e.target.tagName === 'INPUT' || 
                e.target.tagName === 'LABEL' || e.target.closest('button') || 
                e.target.closest('label')) {
                return;
            }
            
            isDragging = true;
            dragStartX = e.clientX;
            dragStartY = e.clientY;
            
            const rect = modal.getBoundingClientRect();
            modalStartLeft = rect.left;
            modalStartTop = rect.top;

            // 禁用过渡效果，使拖动更流畅
            modal.style.transition = "none";
            content.style.background = "rgba(255, 255, 255, 0.05)";
            
            e.preventDefault();
        };

        // 拖动中
        const onDragMove = (e) => {
            if (!isDragging) return;

            const deltaX = e.clientX - dragStartX;
            const deltaY = e.clientY - dragStartY;

            let newLeft = modalStartLeft + deltaX;
            let newTop = modalStartTop + deltaY;

            // 限制拖动范围，不让面板拖出视口
            const rect = modal.getBoundingClientRect();
            const maxLeft = window.innerWidth - rect.width;
            const maxTop = window.innerHeight - rect.height;

            newLeft = Math.max(0, Math.min(newLeft, maxLeft));
            newTop = Math.max(0, Math.min(newTop, maxTop));

            modal.style.left = `${newLeft}px`;
            modal.style.top = `${newTop}px`;
        };

        // 结束拖动
        const onDragEnd = () => {
            if (!isDragging) return;
            
            isDragging = false;
            modal.style.transition = "transform 0.4s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease";
            content.style.background = "";
        };

        // 绑定拖动事件到整个 content 区域
        content.addEventListener("mousedown", onDragStart);
        document.addEventListener("mousemove", onDragMove);
        document.addEventListener("mouseup", onDragEnd);

        // 悬停效果
        content.addEventListener("mouseenter", () => {
            if (!isDragging) {
                content.style.background = "rgba(255, 255, 255, 0.02)";
            }
        });
        content.addEventListener("mouseleave", () => {
            if (!isDragging) {
                content.style.background = "";
            }
        });

        // 关闭函数（带退出动画）
        function closeModal() {
            try {
                // 清除节点库按钮高亮
                if (clearHighlight) {
                    clearHighlight();
                }
                
                // 移除拖动事件监听器
                document.removeEventListener("mousemove", onDragMove);
                document.removeEventListener("mouseup", onDragEnd);
                
                // 执行退出动画
                modal.style.transform = "translateX(-120%)";
                modal.style.opacity = "0";
                
                // 动画结束后移除元素
                setTimeout(() => {
                    try {
                        modal.remove();
                    } catch (e) {
                        console.error("移除元素失败:", e);
                    }
                }, 400);
            } catch (e) {
                console.error("关闭面板失败:", e);
            }
        }

        // 事件监听
        closeIcon.addEventListener("click", () => {
            if (checkbox.checked) {
                localStorage.setItem(skipGuideKey, "1");
            }
            closeModal();
        });

        confirmButton.addEventListener("click", () => {
            if (checkbox.checked) {
                localStorage.setItem(skipGuideKey, "1");
            }
            closeModal();
        });

        // 可选：按 ESC 键关闭
        const handleEscape = (e) => {
            if (e.key === "Escape") {
                if (checkbox.checked) {
                    localStorage.setItem(skipGuideKey, "1");
                }
                closeModal();
                document.removeEventListener("keydown", handleEscape);
            }
        };
        document.addEventListener("keydown", handleEscape);

        // 触发进入动画
        requestAnimationFrame(() => {
            requestAnimationFrame(() => {
                modal.style.transform = "translateX(0)";
                modal.style.opacity = "1";
            });
        });
    }

    /**
     * 简单的 toast 显示（顶部居中），默认时长 5000ms
     */
    showToast(message, duration = 5000) {
        try {
            const id = "comfy-accel-toast";
            if (document.getElementById(id)) return;
            
            // 创建容器
            const container = document.createElement("div");
            container.id = id;
            container.style.cssText = `
                border-radius: 2px;
                background: #2C2E33;
                box-shadow: 0px 6px 16px 0px rgba(0, 0, 0, 0.08);
                display: flex;
                flex-direction: row;
                width: fit-content;
                height: fit-content;
                gap: 8px;
                box-sizing: border-box;
                padding: 8px 16px;
                min-width: 514px;
                min-height: 38px;
                position: fixed;
                top: 20px;
                left: 50%;
                z-index: 300000;
                opacity: 0;
                transition: opacity 160ms ease-in-out, transform 160ms ease-in-out;
                transform: translate(-50%, -8px);
                align-items: center;
            `;

            // 创建图标
            const icon = document.createElement("img");
            icon.src = "https://img.alicdn.com/imgextra/i3/6000000001291/O1CN0186URa61LPKQQdfELr_!!6000000001291-2-gg_dtc.png";
            icon.alt = "notification icon";
            icon.style.cssText = `
                width: 16px;
                height: 22px;
            `;

            // 创建文本
            const text = document.createElement("span");
            text.textContent = message;
            text.style.cssText = `
                font-size: 14px;
                font-weight: 400;
                line-height: 22px;
                color: #FFFFFF;
                white-space: nowrap;
            `;

            container.appendChild(icon);
            container.appendChild(text);
            document.body.appendChild(container);

            // trigger transition
            requestAnimationFrame(() => {
                container.style.opacity = "1";
                container.style.transform = "translate(-50%, 0)";
            });

            setTimeout(() => {
                container.style.opacity = "0";
                container.style.transform = "translate(-50%, -8px)";
                setTimeout(() => {
                    try {
                        container.remove();
                    } catch {}
                }, 220);
            }, duration);
        } catch (e) {
            console.error("showToast error", e);
        }
    }

    /**
     * 根据节点ID数组聚焦节点
     * @param {Array<number>} nodeIds - 需要聚焦的节点ID数组
     */
    focusNodesByIds(nodeIds) {
        try {
            if (!app.graph || !app.graph.nodes || !app.canvas) {
                console.warn("app.graph or app.canvas not available");
                return;
            }

            // 遍历需要聚焦的节点ID
            for (const nodeId of nodeIds) {
                // 在 app.graph.nodes 中查找对应ID的节点
                const node = app.graph.nodes.find(n => n.id === nodeId);
                if (node) {
                    // 使用 selectNode 方法选中节点
                    app.canvas.selectNode(node);
                    console.log(`Selected node ${nodeId}`);
                } else {
                    console.warn(`Node with id ${nodeId} not found`);
                }
            }

            // 如果有选中的节点，将画布居中到选中的节点
            if (nodeIds.length > 0) {
                const firstNode = app.graph.nodes.find(n => n.id === nodeIds[0]);
                if (firstNode && app.canvas.centerOnNode) {
                    app.canvas.centerOnNode(firstNode);
                }
            }
        } catch (e) {
            console.error("focusNodesByIds error", e);
        }
    }

    async handleTransform(button) {
        const originalText = this.getBadgeText();
        const originalBg = button.style.background;

        // 先弹提示（根据用户偏好）
        let proceed = false;
        try {
            proceed = await this.promptAcceleration();
        } catch (e) {
            console.error("promptAcceleration error", e);
            proceed = false;
        }

        if (!proceed) {
            // 用户取消加速
            return;
        }

        // 用户选择继续加速：调用后端转换并在当前标签页打开（保留原本大逻辑）
        button.style.pointerEvents = "none";
        button.style.opacity = "0.75";
        this.updateBadgeText("处理中...");

        try {
            const current = this.getCurrentWorkflow();
            const res = await this.requestTransformOnServer(current);

            // 如果后端返回 conversion_result 指示已经转换过，显示 5 秒 toast 提示并不再打开工作流
            if (res?.conversion_result === "FAILURE_ALREADY_CONVERTED") {
                this.showToast("当前工作流已配置无影DiT加速节点，无需再次启动。", 5000);
                // 保持按钮提示短暂变化
                this.updateBadgeText("已配置加速节点");
                button.style.opacity = "0.6";
                setTimeout(() => {
                    this.updateBadgeText(originalText);
                    button.style.opacity = "1";
                }, 1200);
                return;
            } else if (res?.conversion_result === "FAILED") {
                // 保持按钮提示短暂变化
                this.updateBadgeText("工作流暂不支持");
                button.style.opacity = "0.6";
                setTimeout(() => {
                    this.updateBadgeText(originalText);
                    button.style.opacity = "1";
                }, 1200);
                return;
            }

            // 直接在当前标签页打开转换后的工作流
            await this.openWorkflow(res.workflow);
            
            if (res?.conversion_result === "SUCCEED_UNKNOWN_MODEL"){
              // 加速成功，但需要提示用户修改模型类型
              if (
                res.related_nodes_id &&
                Array.isArray(res.related_nodes_id) &&
                res.related_nodes_id.length > 0
              ) {
                this.focusNodesByIds(res.related_nodes_id);
              }
              // 加速失败，显示手动配置引导弹窗
              this.showToast("model_type无法识别，请在wyingOptim节点中手动配置",5000)
            }

            this.updateBadgeText("已打开加速工作流");
            setTimeout(() => {
                this.updateBadgeText(originalText);
            }, 1200);
        } catch (e) {
            console.error("[Transform Workflow] 加速处理失败：", e);
            this.updateBadgeText("转换失败");
            setTimeout(() => {
                this.updateBadgeText(originalText);
            }, 1800);
        } finally {
            button.style.pointerEvents = "auto";
            button.style.opacity = "1";
        }
    }

    // ============== 拖拽逻辑 ==============
    onDragStart(e) {
        if (!this.buttonEl) return;
        if (e.button !== 0 && e.pointerType !== "touch" && e.pointerType !== "pen") return;

        this.drag.active = true;
        this.buttonEl.setPointerCapture?.(e.pointerId);

        if (this.getSavedPosition()?.mode !== "floating") {
            document.body.appendChild(this.buttonEl);
            this.applyFloatingStyles();

            const rect = this.buttonEl.getBoundingClientRect();
            const startLeft = rect.left;
            const startTop = rect.top;

            this.setFloatingPosition(startLeft, startTop);
            this.savePosition({ mode: "floating", x: startLeft, y: startTop });
        }

        const rect = this.buttonEl.getBoundingClientRect();
        this.drag.startX = e.clientX;
        this.drag.startY = e.clientY;
        this.drag.offsetX = e.clientX - rect.left;
        this.drag.offsetY = e.clientY - rect.top;

        this.buttonEl.style.cursor = "grabbing";
        document.body.style.userSelect = "none";
    }

    onDragMove(e) {
        if (!this.drag.active || !this.buttonEl) return;
        const x = e.clientX - this.drag.offsetX;
        const y = e.clientY - this.drag.offsetY;
        this.setFloatingPosition(x, y);
    }

    onDragEnd() {
        if (!this.drag.active || !this.buttonEl) return;
        this.drag.active = false;

        const rect = this.buttonEl.getBoundingClientRect();
        this.savePosition({ mode: "floating", x: rect.left, y: rect.top });

        this.buttonEl.style.cursor = "pointer";
        document.body.style.userSelect = "";
    }
}

app.registerExtension({
    name: "Workflow.MovableTransformButton",
    async setup() {
        new MovableTransformButtonExtension();
    }
});