import React, { useState, useEffect, useRef, useCallback } from 'react';
import * as ReactDOM from 'react-dom';
import * as ReactJSXRuntime from 'react/jsx-runtime';
import { Core, createLogger, Scene } from '@esengine/ecs-framework';
import * as ECSFramework from '@esengine/ecs-framework';
import { getProfilerService } from './services/getService';

// 将 React 暴露到全局，供动态加载的插件使用
// editor-runtime.js 将 React 设为 external，需要从全局获取
(window as any).React = React;
(window as any).ReactDOM = ReactDOM;
(window as any).ReactJSXRuntime = ReactJSXRuntime;
import {
    PluginManager,
    UIRegistry,
    MessageHub,
    EntityStoreService,
    ComponentRegistry,
    LocaleService,
    LogService,
    SettingsRegistry,
    SceneManagerService,
    ProjectService,
    CompilerRegistry,
    ICompilerRegistry,
    InspectorRegistry,
    INotification,
    CommandManager,
    BuildService
} from '@esengine/editor-core';
import type { IDialogExtended } from './services/TauriDialogService';
import { GlobalBlackboardService } from '@esengine/behavior-tree';
import { ServiceRegistry, PluginInstaller, useDialogStore } from './app/managers';
import { useEditorStore } from './stores';
import { StartupPage } from './components/StartupPage';
import { ProjectCreationWizard } from './components/ProjectCreationWizard';
import { SceneHierarchy } from './components/SceneHierarchy';
import { ContentBrowser } from './components/ContentBrowser';
import { Inspector } from './components/inspectors/Inspector';
import { AssetBrowser } from './components/AssetBrowser';
import { Viewport } from './components/Viewport';
import { AdvancedProfilerWindow } from './components/AdvancedProfilerWindow';
import { RenderDebugPanel } from './components/debug/RenderDebugPanel';
import { emit, emitTo, listen } from '@tauri-apps/api/event';
import { renderDebugService } from './services/RenderDebugService';
import { PortManager } from './components/PortManager';
import { SettingsWindow } from './components/SettingsWindow';
import { AboutDialog } from './components/AboutDialog';
import { ErrorDialog } from './components/ErrorDialog';
import { ConfirmDialog } from './components/ConfirmDialog';
import { ExternalModificationDialog } from './components/ExternalModificationDialog';
import { PluginGeneratorWindow } from './components/PluginGeneratorWindow';
import { BuildSettingsWindow } from './components/BuildSettingsWindow';
import { ForumPanel } from './components/forum';
import { ToastProvider, useToast } from './components/Toast';
import { TitleBar } from './components/TitleBar';
import { MainToolbar } from './components/MainToolbar';
import { FlexLayoutDockContainer, FlexDockPanel, type FlexLayoutDockContainerHandle } from './components/FlexLayoutDockContainer';
import { StatusBar } from './components/StatusBar';
import { TauriAPI } from './api/tauri';
import { SettingsService } from './services/SettingsService';
import { PluginLoader } from './services/PluginLoader';
import { EngineService } from './services/EngineService';
import { CompilerConfigDialog } from './components/CompilerConfigDialog';
import { checkForUpdatesOnStartup } from './utils/updater';
import { useLocale } from './hooks/useLocale';
import { useStoreSubscriptions } from './hooks/useStoreSubscriptions';
import { en, zh, es } from './locales';
import type { Locale } from '@esengine/editor-core';
import { UserCodeService } from '@esengine/editor-core';
import { Loader2 } from 'lucide-react';
import './styles/App.css';

const coreInstance = Core.create({ debug: true });

const localeService = new LocaleService();
localeService.registerTranslations('en', en);
localeService.registerTranslations('zh', zh);
localeService.registerTranslations('es', es);
Core.services.registerInstance(LocaleService, localeService);

Core.services.registerSingleton(GlobalBlackboardService);
Core.services.registerSingleton(CompilerRegistry);

// 在 CompilerRegistry 实例化后，也用 Symbol 注册，用于跨包插件访问
// 注意：registerSingleton 会延迟实例化，所以需要在第一次使用后再注册 Symbol
const compilerRegistryInstance = Core.services.resolve(CompilerRegistry);
Core.services.registerInstance(ICompilerRegistry, compilerRegistryInstance);

const logger = createLogger('App');

// 检查是否为独立窗口模式 | Check if standalone window mode
const isFrameDebuggerMode = new URLSearchParams(window.location.search).get('mode') === 'frame-debugger';

function App() {
    const initRef = useRef(false);
    const layoutContainerRef = useRef<FlexLayoutDockContainerHandle>(null);
    const [pluginLoader] = useState(() => new PluginLoader());
    const { showToast, hideToast } = useToast();

    // 如果是独立调试窗口模式，只渲染调试面板 | If standalone debugger mode, only render debug panel
    if (isFrameDebuggerMode) {
        return (
            <div style={{ width: '100vw', height: '100vh', overflow: 'hidden' }}>
                <RenderDebugPanel visible={true} onClose={() => window.close()} standalone />
            </div>
        );
    }

    // ===== 本地初始化状态（只用于初始化阶段）| Local init state (only for initialization) =====
    const [initialized, setInitialized] = useState(false);

    // ===== 从 EditorStore 获取状态 | Get state from EditorStore =====
    const {
        projectLoaded, setProjectLoaded,
        currentProjectPath, setCurrentProjectPath,
        availableScenes, setAvailableScenes,
        isLoading, setIsLoading,
        loadingMessage,
        panels, setPanels,
        activeDynamicPanels, addDynamicPanel, removeDynamicPanel, clearDynamicPanels,
        dynamicPanelTitles, setDynamicPanelTitle,
        activePanelId, setActivePanelId,
        pluginUpdateTrigger, triggerPluginUpdate,
        isRemoteConnected, setIsRemoteConnected,
        isContentBrowserDocked, setIsContentBrowserDocked,
        isEditorFullscreen, setIsEditorFullscreen,
        status, setStatus,
        showProjectWizard, setShowProjectWizard,
        settingsInitialCategory, setSettingsInitialCategory,
        compilerDialog, openCompilerDialog, closeCompilerDialog,
    } = useEditorStore();

    // ===== 服务实例用 useRef（不触发重渲染）| Service instances use useRef (no re-renders) =====
    const pluginManagerRef = useRef<PluginManager | null>(null);
    const entityStoreRef = useRef<EntityStoreService | null>(null);
    const messageHubRef = useRef<MessageHub | null>(null);
    const inspectorRegistryRef = useRef<InspectorRegistry | null>(null);
    const logServiceRef = useRef<LogService | null>(null);
    const uiRegistryRef = useRef<UIRegistry | null>(null);
    const settingsRegistryRef = useRef<SettingsRegistry | null>(null);
    const sceneManagerRef = useRef<SceneManagerService | null>(null);
    const notificationRef = useRef<INotification | null>(null);
    const dialogRef = useRef<IDialogExtended | null>(null);
    const buildServiceRef = useRef<BuildService | null>(null);
    const projectServiceRef = useRef<ProjectService | null>(null);

    // 兼容层：提供 getter 访问服务 | Compatibility layer: provide getter access to services
    const pluginManager = pluginManagerRef.current;
    const entityStore = entityStoreRef.current;
    const messageHub = messageHubRef.current;
    const inspectorRegistry = inspectorRegistryRef.current;
    const logService = logServiceRef.current;
    const uiRegistry = uiRegistryRef.current;
    const settingsRegistry = settingsRegistryRef.current;
    const sceneManager = sceneManagerRef.current;
    const notification = notificationRef.current;
    const dialog = dialogRef.current;
    const buildService = buildServiceRef.current;
    const projectServiceState = projectServiceRef.current;

    const [commandManager] = useState(() => new CommandManager());
    const { t, locale, changeLocale } = useLocale();

    // Play 模式状态（用于层级面板实时同步）
    // Play mode state (for hierarchy panel real-time sync)
    const [isPlaying, setIsPlaying] = useState(false);

    // 监听 Play 状态变化
    // Listen for play state changes
    useEffect(() => {
        if (!messageHubRef.current || !initialized) return;

        const unsubscribe = messageHubRef.current.subscribe('viewport:playState:changed', (data: { isPlaying: boolean }) => {
            setIsPlaying(data.isPlaying);
        });

        return () => unsubscribe();
    }, [initialized]);

    // 初始化 Store 订阅（集中管理 MessageHub 订阅）
    // Initialize store subscriptions (centrally manage MessageHub subscriptions)
    useStoreSubscriptions({
        messageHub: messageHubRef.current,
        entityStore: entityStoreRef.current,
        sceneManager: sceneManagerRef.current,
        enabled: initialized,
        isPlaying,
    });

    // 同步 locale 到 TauriDialogService
    useEffect(() => {
        if (dialogRef.current) {
            dialogRef.current.setLocale(locale);
        }
    }, [locale]);

    // ===== 从 DialogStore 获取对话框状态 | Get dialog state from DialogStore =====
    const {
        showProfiler, setShowProfiler,
        showAdvancedProfiler, setShowAdvancedProfiler,
        showPortManager, setShowPortManager,
        showSettings, setShowSettings,
        showAbout, setShowAbout,
        showPluginGenerator, setShowPluginGenerator,
        showBuildSettings, setShowBuildSettings,
        showRenderDebug, setShowRenderDebug,
        errorDialog, setErrorDialog,
        confirmDialog, setConfirmDialog,
        externalModificationDialog, setExternalModificationDialog
    } = useDialogStore();

    // 全局监听独立调试窗口的数据请求 | Global listener for standalone debug window requests
    useEffect(() => {
        let broadcastInterval: ReturnType<typeof setInterval> | null = null;

        const unlistenPromise = listen('render-debug-request-data', () => {
            // 开始定时广播数据 | Start broadcasting data periodically
            if (!broadcastInterval) {
                const broadcast = () => {
                    renderDebugService.setEnabled(true);
                    const snap = renderDebugService.collectSnapshot();
                    if (snap) {
                        // 使用 emitTo 发送到独立窗口 | Use emitTo to send to standalone window
                        emitTo('frame-debugger', 'render-debug-snapshot', snap).catch(() => {});
                    }
                };
                broadcast(); // 立即广播一次 | Broadcast immediately
                broadcastInterval = setInterval(broadcast, 500);
            }
        });

        return () => {
            unlistenPromise.then(unlisten => unlisten());
            if (broadcastInterval) {
                clearInterval(broadcastInterval);
            }
        };
    }, []);

    useEffect(() => {
        // 禁用默认右键菜单
        const handleContextMenu = (e: MouseEvent) => {
            e.preventDefault();
        };

        document.addEventListener('contextmenu', handleContextMenu);

        return () => {
            document.removeEventListener('contextmenu', handleContextMenu);
        };
    }, []);

    // Global keyboard shortcuts for undo/redo | 全局撤销/重做快捷键
    useEffect(() => {
        const handleKeyDown = (e: KeyboardEvent) => {
            // Skip if user is typing in an input | 如果用户正在输入则跳过
            const target = e.target as HTMLElement;
            if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {
                return;
            }

            // Ctrl+Z: Undo | 撤销
            if (e.ctrlKey && !e.shiftKey && e.key === 'z') {
                e.preventDefault();
                if (commandManager.canUndo()) {
                    commandManager.undo();
                }
            }
            // Ctrl+Y or Ctrl+Shift+Z: Redo | 重做
            else if ((e.ctrlKey && e.key === 'y') || (e.ctrlKey && e.shiftKey && e.key === 'z')) {
                e.preventDefault();
                if (commandManager.canRedo()) {
                    commandManager.redo();
                }
            }
        };

        document.addEventListener('keydown', handleKeyDown);
        return () => document.removeEventListener('keydown', handleKeyDown);
    }, [commandManager]);

    // 快捷键监听
    useEffect(() => {
        const handleKeyDown = async (e: KeyboardEvent) => {
            if (e.ctrlKey || e.metaKey) {
                switch (e.key.toLowerCase()) {
                    case 's': {
                        // Skip if any modal/dialog is open
                        // 如果有模态窗口/对话框打开则跳过
                        const hasModalOpen = showBuildSettings || showSettings || showAbout ||
                            showPluginGenerator || showPortManager || showAdvancedProfiler ||
                            errorDialog || confirmDialog;
                        if (hasModalOpen) {
                            return;
                        }

                        // Skip if focus is in an input/textarea/contenteditable element
                        // 如果焦点在输入框/文本域/可编辑元素中则跳过
                        const activeEl = document.activeElement;
                        const isInInput = activeEl instanceof HTMLInputElement ||
                            activeEl instanceof HTMLTextAreaElement ||
                            activeEl?.getAttribute('contenteditable') === 'true';
                        if (isInInput) {
                            return;
                        }

                        e.preventDefault();
                        if (sceneManager) {
                            try {
                                // 检查是否在预制体编辑模式 | Check if in prefab edit mode
                                if (sceneManager.isPrefabEditMode()) {
                                    await sceneManager.savePrefab();
                                    const prefabState = sceneManager.getPrefabEditModeState();
                                    showToast(t('editMode.prefab.savedSuccess', { name: prefabState?.prefabName ?? 'Prefab' }), 'success');
                                } else {
                                    await sceneManager.saveScene();
                                    const sceneState = sceneManager.getSceneState();
                                    showToast(t('scene.savedSuccess', { name: sceneState.sceneName }), 'success');
                                }
                            } catch (error) {
                                console.error('Failed to save:', error);
                                if (sceneManager.isPrefabEditMode()) {
                                    showToast(t('editMode.prefab.saveFailed'), 'error');
                                } else {
                                    showToast(t('scene.saveFailed'), 'error');
                                }
                            }
                        }
                        break;
                    }
                    case 'r':
                        e.preventDefault();
                        handleReloadPlugins();
                        break;
                }
            }
        };

        document.addEventListener('keydown', handleKeyDown);

        return () => {
            document.removeEventListener('keydown', handleKeyDown);
        };
    }, [sceneManager, locale, currentProjectPath, pluginManager,
        showBuildSettings, showSettings, showAbout, showPluginGenerator,
        showPortManager, showAdvancedProfiler, errorDialog, confirmDialog]);

    // 插件和通知订阅 | Plugin and notification subscriptions
    useEffect(() => {
        if (!initialized || !messageHubRef.current) return;
        const hub = messageHubRef.current;

        const unsubscribeEnabled = hub.subscribe('plugin:enabled', () => {
            triggerPluginUpdate();
        });

        const unsubscribeDisabled = hub.subscribe('plugin:disabled', () => {
            triggerPluginUpdate();
        });

        const unsubscribeNotification = hub.subscribe('notification:show', (notification: { message: string; type: 'success' | 'error' | 'warning' | 'info'; timestamp: number }) => {
            if (notification && notification.message) {
                showToast(notification.message, notification.type);
            }
        });

        return () => {
            unsubscribeEnabled();
            unsubscribeDisabled();
            unsubscribeNotification();
        };
    }, [initialized, triggerPluginUpdate, showToast]);

    // 监听远程连接状态
    // Monitor remote connection status
    useEffect(() => {
        const checkConnection = () => {
            const profilerService = getProfilerService();
            const connected = !!(profilerService && profilerService.isConnected());

            setIsRemoteConnected((prevConnected) => {
                if (connected !== prevConnected) {
                    // 状态发生变化 | State has changed
                    if (connected) {
                        setStatus(t('header.status.remoteConnected'));
                    } else {
                        if (projectLoaded) {
                            const componentRegistry = Core.services.resolve(ComponentRegistry);
                            const componentCount = componentRegistry?.getAllComponents().length || 0;
                            setStatus(t('header.status.projectOpened') + (componentCount > 0 ? ` (${componentCount} components registered)` : ''));
                        } else {
                            setStatus(t('header.status.ready'));
                        }
                    }
                    return connected;
                }
                return prevConnected;
            });
        };

        const interval = setInterval(checkConnection, 1000);

        return () => clearInterval(interval);
    }, [projectLoaded, t]);

    useEffect(() => {
        const initializeEditor = async () => {
            // 使用 ref 防止 React StrictMode 的双重调用
            if (initRef.current) {
                return;
            }
            initRef.current = true;

            try {
                // ECS Framework 已通过 PluginSDKRegistry 暴露到全局
                // ECS Framework is exposed globally via PluginSDKRegistry

                const editorScene = new Scene();
                Core.setScene(editorScene);

                const serviceRegistry = new ServiceRegistry();
                const services = serviceRegistry.registerAllServices(coreInstance);

                serviceRegistry.setupRemoteLogListener(services.logService);

                const pluginInstaller = new PluginInstaller();
                await pluginInstaller.installBuiltinPlugins(services.pluginManager);

                // 初始化编辑器模块（安装设置、面板等）
                await services.pluginManager.initializeEditor(Core.services);

                services.notification.setCallbacks(showToast, hideToast);
                (services.dialog as IDialogExtended).setConfirmCallback(setConfirmDialog);

                services.messageHub.subscribe('ui:openWindow', (data: any) => {
                    const { windowId } = data;

                    if (windowId === 'profiler') {
                        setShowProfiler(true);
                    } else if (windowId === 'advancedProfiler') {
                        setShowAdvancedProfiler(true);
                    } else if (windowId === 'pluginManager') {
                        // 插件管理现在整合到设置窗口中
                        setSettingsInitialCategory('plugins');
                        setShowSettings(true);
                    }
                });

                // 设置服务引用（不触发重渲染）| Set service refs (no re-renders)
                pluginManagerRef.current = services.pluginManager;
                entityStoreRef.current = services.entityStore;
                messageHubRef.current = services.messageHub;
                inspectorRegistryRef.current = services.inspectorRegistry;
                logServiceRef.current = services.logService;
                uiRegistryRef.current = services.uiRegistry;
                settingsRegistryRef.current = services.settingsRegistry;
                sceneManagerRef.current = services.sceneManager;
                notificationRef.current = services.notification;
                dialogRef.current = services.dialog as IDialogExtended;
                buildServiceRef.current = services.buildService;

                // 设置初始化完成（触发一次重渲染）| Set initialized (triggers one re-render)
                setInitialized(true);
                setStatus(t('header.status.ready'));

                // Check for updates on startup (after 3 seconds)
                checkForUpdatesOnStartup();
            } catch (error) {
                console.error('Failed to initialize editor:', error);
                setStatus(t('header.status.failed'));
            }
        };

        initializeEditor();
    }, []);

    // 初始化后订阅消息 | Subscribe to messages after initialization
    useEffect(() => {
        if (!initialized || !messageHubRef.current) return;
        const hub = messageHubRef.current;

        const unsubscribe = hub.subscribe('dynamic-panel:open', (data: any) => {
            const { panelId, title } = data;
            logger.info('Opening dynamic panel:', panelId, 'with title:', title);
            addDynamicPanel(panelId, title);
            setActivePanelId(panelId);
        });

        return () => unsubscribe?.();
    }, [initialized, addDynamicPanel, setActivePanelId]);

    useEffect(() => {
        if (!initialized || !messageHubRef.current) return;
        const hub = messageHubRef.current;

        const unsubscribe = hub.subscribe('editor:fullscreen', (data: any) => {
            const { fullscreen } = data;
            logger.info('Editor fullscreen state changed:', fullscreen);
            setIsEditorFullscreen(fullscreen);
        });

        return () => unsubscribe?.();
    }, [initialized, setIsEditorFullscreen]);

    useEffect(() => {
        if (!initialized || !messageHubRef.current) return;
        const hub = messageHubRef.current;

        const unsubscribe = hub.subscribe('compiler:open-dialog', (data: {
            compilerId: string;
            currentFileName?: string;
            projectPath?: string;
        }) => {
            logger.info('Opening compiler dialog:', data.compilerId);
            openCompilerDialog(data.compilerId, data.currentFileName);
        });

        return () => unsubscribe?.();
    }, [initialized, openCompilerDialog]);

    // 注册引擎快照请求处理器（用于预制体编辑模式）
    // Register engine snapshot request handlers (for prefab edit mode)
    useEffect(() => {
        if (!initialized || !messageHubRef.current) return;
        const hub = messageHubRef.current;

        const unsubscribeSave = hub.onRequest<void, boolean>(
            'engine:saveSceneSnapshot',
            async () => {
                const engineService = EngineService.getInstance();
                return engineService.saveSceneSnapshot();
            }
        );

        const unsubscribeRestore = hub.onRequest<void, boolean>(
            'engine:restoreSceneSnapshot',
            async () => {
                const engineService = EngineService.getInstance();
                return await engineService.restoreSceneSnapshot();
            }
        );

        return () => {
            unsubscribeSave?.();
            unsubscribeRestore?.();
        };
    }, [initialized]);

    // Handle external scene file changes
    // 处理外部场景文件变更
    useEffect(() => {
        if (!initialized || !messageHubRef.current || !sceneManagerRef.current) return;
        const hub = messageHubRef.current;
        const sm = sceneManagerRef.current;

        const unsubscribe = hub.subscribe('scene:external-change', (data: {
            path: string;
            sceneName: string;
        }) => {
            logger.info('Scene externally modified:', data.path);

            // Show confirmation dialog to reload the scene
            // 显示确认对话框以重新加载场景
            setConfirmDialog({
                title: t('scene.externalChange.title'),
                message: t('scene.externalChange.message', { name: data.sceneName }),
                confirmText: t('scene.externalChange.reload'),
                cancelText: t('scene.externalChange.ignore'),
                onConfirm: async () => {
                    setConfirmDialog(null);
                    try {
                        await sm.openScene(data.path);
                        showToast(t('scene.reloadedSuccess', { name: data.sceneName }), 'success');
                    } catch (error) {
                        console.error('Failed to reload scene:', error);
                        showToast(t('scene.reloadFailed'), 'error');
                    }
                },
                onCancel: () => {
                    // User chose to ignore, do nothing
                    // 用户选择忽略，不做任何操作
                }
            });
        });

        return () => unsubscribe?.();
    }, [initialized, t, showToast]);

    // Handle external modification when saving scene
    // 处理保存场景时的外部修改检测
    useEffect(() => {
        if (!initialized || !messageHubRef.current || !sceneManagerRef.current) return;
        const hub = messageHubRef.current;
        const sm = sceneManagerRef.current;

        const unsubscribe = hub.subscribe('scene:externalModification', (data: {
            path: string;
            sceneName: string;
        }) => {
            logger.info('Scene file externally modified during save:', data.path);

            // Show external modification dialog with three options
            // 显示外部修改对话框，提供三个选项
            setExternalModificationDialog({
                sceneName: data.sceneName,
                onReload: async () => {
                    setExternalModificationDialog(null);
                    try {
                        await sm.reloadScene();
                        showToast(t('scene.reloadedSuccess', { name: data.sceneName }), 'success');
                    } catch (error) {
                        console.error('Failed to reload scene:', error);
                        showToast(t('scene.reloadFailed'), 'error');
                    }
                },
                onOverwrite: async () => {
                    setExternalModificationDialog(null);
                    try {
                        await sm.saveScene(true); // Force save, overwriting external changes
                        showToast(t('scene.savedSuccess', { name: data.sceneName }), 'success');
                    } catch (error) {
                        console.error('Failed to save scene:', error);
                        showToast(t('scene.saveFailed'), 'error');
                    }
                }
            });
        });

        return () => unsubscribe?.();
    }, [initialized, t, showToast, setExternalModificationDialog]);

    // Handle user code compilation results
    // 处理用户代码编译结果
    useEffect(() => {
        if (!initialized || !messageHubRef.current) return;
        const hub = messageHubRef.current;

        const unsubscribe = hub.subscribe('usercode:compilation-result', (data: {
            success: boolean;
            exports: string[];
            errors: string[];
        }) => {
            if (data.success) {
                if (data.exports.length > 0) {
                    showToast(t('usercode.compileSuccess', { count: data.exports.length }), 'success');
                }
            } else {
                const errorMsg = data.errors[0] ?? t('usercode.compileError');
                showToast(errorMsg, 'error');
            }
        });

        return () => unsubscribe?.();
    }, [initialized, t, showToast]);

    const handleOpenRecentProject = async (projectPath: string) => {
        try {
            setIsLoading(true, t('loading.step1'));

            const projectService = Core.services.resolve(ProjectService);

            if (!projectService) {
                console.error('Required services not available');
                setIsLoading(false);
                return;
            }

            projectServiceRef.current = projectService;
            await projectService.openProject(projectPath);

            // 注意：插件配置会在引擎初始化后加载和激活
            // Note: Plugin config will be loaded and activated after engine initialization

            // 设置 Tauri project:// 协议的基础路径（用于加载插件等项目文件）
            await TauriAPI.setProjectBasePath(projectPath);

            // 更新项目 tsconfig，直接引用引擎类型定义
            // Update project tsconfig to reference engine type definitions directly
            try {
                await TauriAPI.updateProjectTsconfig(projectPath);
            } catch (e) {
                console.warn('[App] Failed to update project tsconfig:', e);
            }

            const settings = SettingsService.getInstance();
            settings.addRecentProject(projectPath);

            setCurrentProjectPath(projectPath);

            // Scan for available scenes in project
            // 扫描项目中可用的场景
            try {
                const sceneFiles = await TauriAPI.scanDirectory(`${projectPath}/scenes`, '*.ecs');
                const sceneNames = sceneFiles.map(f => `scenes/${f.split(/[\\/]/).pop()}`);
                setAvailableScenes(sceneNames);
            } catch (e) {
                console.warn('[App] Failed to scan scenes:', e);
            }

            // 设置 projectLoaded 为 true，触发主界面渲染（包括 Viewport）
            setProjectLoaded(true);

            // 等待引擎初始化完成（Viewport 渲染后会触发引擎初始化）
            setIsLoading(true, t('loading.step2'));
            const engineService = EngineService.getInstance();

            // 等待引擎初始化（最多等待 30 秒，因为需要等待 Viewport 渲染）
            const engineReady = await engineService.waitForInitialization(30000);
            if (!engineReady) {
                throw new Error(t('loading.engineTimeoutError'));
            }

            // 加载项目插件配置并激活插件（在引擎初始化后、模块系统初始化前）
            // Load project plugin config and activate plugins (after engine init, before module system init)
            if (pluginManagerRef.current) {
                const pluginSettings = projectService.getPluginSettings();
                if (pluginSettings && pluginSettings.enabledPlugins.length > 0) {
                    await pluginManagerRef.current.loadConfig({ enabledPlugins: pluginSettings.enabledPlugins });
                }
            }

            // 初始化模块系统（所有插件的 runtimeModule 会在 PluginManager 安装时自动注册）
            await engineService.initializeModuleSystems();

            // 应用项目的 UI 设计分辨率
            // Apply project's UI design resolution
            const uiResolution = projectService.getUIDesignResolution();
            engineService.setUICanvasSize(uiResolution.width, uiResolution.height);

            setStatus(t('header.status.projectOpened'));

            setIsLoading(true, t('loading.step3'));

            // Wait for user code to be compiled and registered before loading scenes
            // 等待用户代码编译和注册完成后再加载场景
            const userCodeService = Core.services.tryResolve(UserCodeService);
            if (userCodeService) {
                await userCodeService.waitForReady();
            }

            const sceneManagerService = Core.services.resolve(SceneManagerService);
            if (sceneManagerService) {
                await sceneManagerService.newScene();
            }

            if (pluginManagerRef.current) {
                setIsLoading(true, t('loading.loadingPlugins'));
                await pluginLoader.loadProjectPlugins(projectPath, pluginManagerRef.current);
            }

            setIsLoading(false);
        } catch (error) {
            console.error('Failed to open project:', error);
            setStatus(t('header.status.failed'));
            setIsLoading(false);

            const errorMessage = error instanceof Error ? error.message : String(error);
            setErrorDialog({
                title: t('project.openFailed'),
                message: `${t('project.openFailed')}:\n${errorMessage}`
            });
        }
    };

    const handleOpenProject = async () => {
        try {
            const projectPath = await TauriAPI.openProjectDialog();
            if (!projectPath) return;

            await handleOpenRecentProject(projectPath);
        } catch (error) {
            console.error('Failed to open project dialog:', error);
        }
    };

    const handleCreateProject = () => {
        setShowProjectWizard(true);
    };

    const handleCreateProjectFromWizard = async (projectName: string, projectPath: string, _templateId: string) => {
        // 使用与 projectPath 相同的路径分隔符 | Use same separator as projectPath
        const sep = projectPath.includes('/') ? '/' : '\\';
        const fullProjectPath = `${projectPath}${sep}${projectName}`;

        try {
            setIsLoading(true, t('project.creating'));

            const projectService = Core.services.resolve(ProjectService);
            if (!projectService) {
                console.error('ProjectService not available');
                setIsLoading(false);
                setErrorDialog({
                    title: t('project.createFailed'),
                    message: t('project.serviceUnavailable')
                });
                return;
            }

            await projectService.createProject(fullProjectPath);

            setIsLoading(true, t('project.createdOpening'));

            await handleOpenRecentProject(fullProjectPath);
        } catch (error) {
            console.error('Failed to create project:', error);
            setIsLoading(false);

            const errorMessage = error instanceof Error ? error.message : String(error);

            if (errorMessage.includes('already exists')) {
                setConfirmDialog({
                    title: t('project.alreadyExists'),
                    message: t('project.existsQuestion'),
                    confirmText: t('project.open'),
                    cancelText: t('common.cancel'),
                    onConfirm: () => {
                        setConfirmDialog(null);
                        setIsLoading(true, t('project.opening'));
                        handleOpenRecentProject(fullProjectPath).catch((err) => {
                            console.error('Failed to open project:', err);
                            setIsLoading(false);
                            setErrorDialog({
                                title: t('project.openFailed'),
                                message: `${t('project.openFailed')}:\n${err instanceof Error ? err.message : String(err)}`
                            });
                        });
                    }
                });
            } else {
                setStatus(t('project.createFailed'));
                setErrorDialog({
                    title: t('project.createFailed'),
                    message: `${t('project.createFailed')}:\n${errorMessage}`
                });
            }
        }
    };

    const handleBrowseProjectPath = async (): Promise<string | null> => {
        try {
            const path = await TauriAPI.openProjectDialog();
            return path || null;
        } catch (error) {
            console.error('Failed to browse path:', error);
            return null;
        }
    };

    const handleNewScene = async () => {
        if (!sceneManager) {
            console.error('SceneManagerService not available');
            return;
        }

        try {
            await sceneManager.newScene();
            setStatus(t('scene.newCreated'));
        } catch (error) {
            console.error('Failed to create new scene:', error);
            setStatus(t('scene.createFailed'));
        }
    };

    const handleOpenScene = async () => {
        if (!sceneManager) {
            console.error('SceneManagerService not available');
            return;
        }

        try {
            // Wait for user code to be ready before loading scene
            // 在加载场景前等待用户代码就绪
            const userCodeService = Core.services.tryResolve(UserCodeService);
            if (userCodeService) {
                await userCodeService.waitForReady();
            }

            await sceneManager.openScene();
            const sceneState = sceneManager.getSceneState();
            setStatus(t('scene.openedSuccess', { name: sceneState.sceneName }));
        } catch (error) {
            console.error('Failed to open scene:', error);
            setStatus(t('scene.openFailed'));
        }
    };

    const handleOpenSceneByPath = useCallback(async (scenePath: string) => {
        console.log('[App] handleOpenSceneByPath called:', scenePath);
        if (!sceneManager) {
            console.error('SceneManagerService not available');
            return;
        }

        try {
            // Wait for user code to be ready before loading scene
            // 在加载场景前等待用户代码就绪
            const userCodeService = Core.services.tryResolve(UserCodeService);
            if (userCodeService) {
                console.log('[App] Waiting for user code service...');
                await userCodeService.waitForReady();
                console.log('[App] User code service ready');
            }

            console.log('[App] Calling sceneManager.openScene...');
            await sceneManager.openScene(scenePath);
            console.log('[App] Scene opened successfully');
            const sceneState = sceneManager.getSceneState();
            setStatus(t('scene.openedSuccess', { name: sceneState.sceneName }));
        } catch (error) {
            console.error('Failed to open scene:', error);
            setStatus(t('scene.openFailed'));
            setErrorDialog({
                title: t('scene.openFailed'),
                message: `${t('scene.openFailed')}:\n${error instanceof Error ? error.message : String(error)}`
            });
        }
    }, [sceneManager, locale]);


    const handleSaveScene = async () => {
        if (!sceneManager) {
            console.error('SceneManagerService not available');
            return;
        }

        try {
            await sceneManager.saveScene();
            const sceneState = sceneManager.getSceneState();
            setStatus(t('scene.savedSuccess', { name: sceneState.sceneName }));
        } catch (error) {
            console.error('Failed to save scene:', error);
            setStatus(t('scene.saveFailed'));
        }
    };

    const handleSaveSceneAs = async () => {
        if (!sceneManager) {
            console.error('SceneManagerService not available');
            return;
        }

        try {
            await sceneManager.saveSceneAs();
            const sceneState = sceneManager.getSceneState();
            setStatus(t('scene.savedSuccess', { name: sceneState.sceneName }));
        } catch (error) {
            console.error('Failed to save scene as:', error);
            setStatus(t('scene.saveAsFailed'));
        }
    };

    const handleCloseProject = async () => {
        // 卸载项目插件
        if (pluginManager) {
            await pluginLoader.unloadProjectPlugins(pluginManager);
        }

        // 清理场景（会清理所有实体和系统）
        // Clear scene (clears all entities and systems)
        const scene = Core.scene;
        if (scene) {
            scene.end();
        }

        // 清理模块系统
        const engineService = EngineService.getInstance();
        engineService.clearModuleSystems();

        // 关闭 ProjectService 中的项目
        const projectService = Core.services.tryResolve(ProjectService);
        if (projectService) {
            await projectService.closeProject();
        }

        setProjectLoaded(false);
        setCurrentProjectPath(null);
        setStatus(t('header.status.ready'));
    };

    const handleExit = () => {
        window.close();
    };

    const handleLocaleChange = (newLocale: Locale) => {
        changeLocale(newLocale);

        // 通知所有已加载的插件更新语言 | Notify all loaded plugins to update locale
        if (pluginManagerRef.current) {
            pluginManagerRef.current.setLocale(newLocale);

            // 通过 MessageHub 通知需要重新获取节点模板 | Notify via MessageHub to refetch node templates
            if (messageHubRef.current) {
                messageHubRef.current.publish('locale:changed', { locale: newLocale });
            }
        }
    };

    const handleToggleDevtools = async () => {
        try {
            await TauriAPI.toggleDevtools();
        } catch (error) {
            console.error('Failed to toggle devtools:', error);
        }
    };

    const handleOpenAbout = () => {
        setShowAbout(true);
    };

    const handleCreatePlugin = () => {
        setShowPluginGenerator(true);
    };

    const handleReloadPlugins = async () => {
        if (currentProjectPath && pluginManagerRef.current) {
            try {
                // 1. 关闭所有动态面板 | Close all dynamic panels
                clearDynamicPanels();

                // 2. 清空当前面板列表（强制卸载插件面板组件）| Clear panel list (force unmount plugin panels)
                setPanels((prev) => prev.filter((p) =>
                    ['scene-hierarchy', 'inspector', 'console', 'asset-browser'].includes(p.id)
                ));

                // 3. 等待React完成卸载 | Wait for React to unmount
                await new Promise((resolve) => setTimeout(resolve, 200));

                // 4. 卸载所有项目插件（清理UIRegistry、调用uninstall）| Unload all project plugins
                await pluginLoader.unloadProjectPlugins(pluginManagerRef.current);

                // 5. 等待卸载完成 | Wait for unload
                await new Promise((resolve) => setTimeout(resolve, 100));

                // 6. 重新加载插件 | Reload plugins
                await pluginLoader.loadProjectPlugins(currentProjectPath, pluginManagerRef.current);

                // 7. 触发面板重新渲染 | Trigger panel re-render
                triggerPluginUpdate();

                showToast(t('plugin.reloadedSuccess'), 'success');
            } catch (error) {
                console.error('Failed to reload plugins:', error);
                showToast(t('plugin.reloadFailed'), 'error');
            }
        }
    };

    // ===== 面板构建（拆分依赖减少重建）| Panel building (split deps to reduce rebuilds) =====
    // 使用 ref 存储面板构建函数，避免频繁重建
    // Use ref to store panel builder function to avoid frequent rebuilds
    const buildPanelsRef = useRef<() => void>(() => {});

    // 更新面板构建函数（不触发重渲染）| Update panel builder (no re-render)
    buildPanelsRef.current = () => {
        if (!projectLoaded || !initialized) return;

        const hub = messageHubRef.current;
        const store = entityStoreRef.current;
        const registry = uiRegistryRef.current;
        const inspReg = inspectorRegistryRef.current;

        if (!hub || !store || !registry) return;

        const corePanels: FlexDockPanel[] = [
            {
                id: 'scene-hierarchy',
                title: t('panel.sceneHierarchy'),
                content: <SceneHierarchy entityStore={store} messageHub={hub} commandManager={commandManager} />,
                closable: false,
                layout: { position: 'right-top' }
            },
            {
                id: 'viewport',
                title: t('panel.viewport'),
                content: <Viewport locale={locale} messageHub={hub} commandManager={commandManager} />,
                closable: false,
                layout: { position: 'center' }
            },
            {
                id: 'inspector',
                title: t('panel.inspector'),
                content: <Inspector entityStore={store} messageHub={hub} inspectorRegistry={inspReg!} projectPath={currentProjectPath} commandManager={commandManager} />,
                closable: false,
                layout: { position: 'right-bottom' }
            },
            {
                id: 'forum',
                title: t('panel.forum'),
                content: <ForumPanel />,
                closable: true,
                layout: { position: 'center' }
            }
        ];

        // 如果内容管理器已停靠，添加到面板 | If content browser is docked, add to panels
        if (isContentBrowserDocked) {
            corePanels.push({
                id: 'content-browser',
                title: t('panel.contentBrowser'),
                content: (
                    <ContentBrowser
                        projectPath={currentProjectPath}
                        locale={locale}
                        onOpenScene={handleOpenSceneByPath}
                        isDrawer={false}
                        onDockInLayout={() => setIsContentBrowserDocked(false)}
                    />
                ),
                closable: true,
                layout: { position: 'bottom', weight: 20, requiresSeparateTabset: true }
            });
        }

        // 获取启用的插件面板 | Get enabled plugin panels
        const pluginPanels: FlexDockPanel[] = registry.getAllPanels()
            .filter((panelDesc) => panelDesc.component && !panelDesc.isDynamic)
            .map((panelDesc) => {
                const Component = panelDesc.component!;
                const title = panelDesc.titleKey ? t(panelDesc.titleKey) : panelDesc.title;
                return {
                    id: panelDesc.id,
                    title,
                    content: <Component key={`${panelDesc.id}-${pluginUpdateTrigger}`} projectPath={currentProjectPath} />,
                    closable: panelDesc.closable ?? true
                };
            });

        // 添加激活的动态面板 | Add active dynamic panels
        const dynamicPanels: FlexDockPanel[] = activeDynamicPanels
            .filter((panelId) => {
                const panelDesc = registry.getPanel(panelId);
                return panelDesc && (panelDesc.component || panelDesc.render);
            })
            .map((panelId) => {
                const panelDesc = registry.getPanel(panelId)!;
                const customTitle = dynamicPanelTitles.get(panelId);
                const defaultTitle = panelDesc.titleKey ? t(panelDesc.titleKey) : panelDesc.title;

                let content: React.ReactNode;
                if (panelDesc.component) {
                    const Component = panelDesc.component;
                    content = <Component projectPath={currentProjectPath} locale={locale} />;
                } else if (panelDesc.render) {
                    content = panelDesc.render();
                }

                return {
                    id: panelDesc.id,
                    title: customTitle || defaultTitle,
                    content,
                    closable: panelDesc.closable ?? true
                };
            });

        setPanels([...corePanels, ...pluginPanels, ...dynamicPanels]);
    };

    // Effect 1: 项目加载后首次构建面板 | Build panels after project loads
    useEffect(() => {
        if (projectLoaded && initialized) {
            buildPanelsRef.current();
        }
    }, [projectLoaded, initialized]);

    // Effect 2: 插件更新时重建 | Rebuild on plugin update
    useEffect(() => {
        if (projectLoaded && initialized && pluginUpdateTrigger > 0) {
            buildPanelsRef.current();
        }
    }, [projectLoaded, initialized, pluginUpdateTrigger]);

    // Effect 3: 动态面板变化时重建 | Rebuild on dynamic panel change
    useEffect(() => {
        if (projectLoaded && initialized) {
            buildPanelsRef.current();
        }
    }, [projectLoaded, initialized, activeDynamicPanels, isContentBrowserDocked]);

    // Effect 4: 语言变化时更新面板标题（不重建组件）| Update panel titles on locale change (don't rebuild components)
    useEffect(() => {
        if (projectLoaded && initialized) {
            // 只更新标题，不重建组件 | Only update titles, don't rebuild components
            setPanels((prev) => prev.map(panel => ({
                ...panel,
                title: panel.id === 'scene-hierarchy' ? t('panel.sceneHierarchy') :
                       panel.id === 'viewport' ? t('panel.viewport') :
                       panel.id === 'inspector' ? t('panel.inspector') :
                       panel.id === 'forum' ? t('panel.forum') :
                       panel.id === 'content-browser' ? t('panel.contentBrowser') :
                       panel.title
            })));
        }
    }, [locale, t, projectLoaded, initialized, setPanels]);


    if (!initialized) {
        return (
            <div className="editor-loading">
                <Loader2 size={32} className="animate-spin" />
                <h2>Loading Editor...</h2>
            </div>
        );
    }

    if (!projectLoaded) {
        const settings = SettingsService.getInstance();
        const recentProjects = settings.getRecentProjects();

        return (
            <>
                <StartupPage
                    onOpenProject={handleOpenProject}
                    onCreateProject={handleCreateProject}
                    onOpenRecentProject={handleOpenRecentProject}
                    onRemoveRecentProject={(projectPath) => {
                        settings.removeRecentProject(projectPath);
                        // 强制重新渲染 | Force re-render
                        setStatus(t('header.status.ready'));
                    }}
                    onDeleteProject={async (projectPath) => {
                        console.log('[App] onDeleteProject called with path:', projectPath);
                        try {
                            console.log('[App] Calling TauriAPI.deleteFolder...');
                            await TauriAPI.deleteFolder(projectPath);
                            console.log('[App] deleteFolder succeeded');
                            // 删除成功后从列表中移除并触发重新渲染
                            // Remove from list and trigger re-render after successful deletion
                            settings.removeRecentProject(projectPath);
                            setStatus(t('header.status.ready'));
                        } catch (error) {
                            console.error('[App] Failed to delete project:', error);
                            setErrorDialog({
                                title: t('project.deleteFailed'),
                                message: `${t('project.deleteFailed')}:\n${error instanceof Error ? error.message : String(error)}`
                            });
                        }
                    }}
                    onLocaleChange={handleLocaleChange}
                    recentProjects={recentProjects}
                />
                <ProjectCreationWizard
                    isOpen={showProjectWizard}
                    onClose={() => setShowProjectWizard(false)}
                    onCreateProject={handleCreateProjectFromWizard}
                    onBrowsePath={handleBrowseProjectPath}
                    locale={locale}
                />
                {isLoading && (
                    <div className="loading-overlay">
                        <div className="loading-content">
                            <Loader2 size={40} className="animate-spin" />
                            <p className="loading-message">{loadingMessage}</p>
                        </div>
                    </div>
                )}
                {errorDialog && (
                    <ErrorDialog
                        title={errorDialog.title}
                        message={errorDialog.message}
                        onClose={() => setErrorDialog(null)}
                    />
                )}
                {confirmDialog && (
                    <ConfirmDialog
                        title={confirmDialog.title}
                        message={confirmDialog.message}
                        confirmText={confirmDialog.confirmText}
                        cancelText={confirmDialog.cancelText}
                        onConfirm={() => {
                            confirmDialog.onConfirm();
                            setConfirmDialog(null);
                        }}
                        onCancel={() => {
                            if (confirmDialog.onCancel) {
                                confirmDialog.onCancel();
                            }
                            setConfirmDialog(null);
                        }}
                    />
                )}
                {externalModificationDialog && (
                    <ExternalModificationDialog
                        sceneName={externalModificationDialog.sceneName}
                        onReload={externalModificationDialog.onReload}
                        onOverwrite={externalModificationDialog.onOverwrite}
                        onCancel={() => setExternalModificationDialog(null)}
                    />
                )}
            </>
        );
    }

    const projectName = currentProjectPath ? currentProjectPath.split(/[\\/]/).pop() : 'Untitled';

    return (
        <div className="editor-container">
            {!isEditorFullscreen && (
                <>
                    <TitleBar
                        projectName={projectName}
                        uiRegistry={uiRegistry || undefined}
                        messageHub={messageHub || undefined}
                        pluginManager={pluginManager || undefined}
                        onNewScene={handleNewScene}
                        onOpenScene={handleOpenScene}
                        onSaveScene={handleSaveScene}
                        onSaveSceneAs={handleSaveSceneAs}
                        onOpenProject={handleOpenProject}
                        onCloseProject={handleCloseProject}
                        onExit={handleExit}
                        onOpenPluginManager={() => {
                            setSettingsInitialCategory('plugins');
                            setShowSettings(true);
                        }}
                        onOpenProfiler={() => setShowProfiler(true)}
                        onOpenPortManager={() => setShowPortManager(true)}
                        onOpenSettings={() => setShowSettings(true)}
                        onToggleDevtools={handleToggleDevtools}
                        onOpenAbout={handleOpenAbout}
                        onCreatePlugin={handleCreatePlugin}
                        onReloadPlugins={handleReloadPlugins}
                        onOpenBuildSettings={() => setShowBuildSettings(true)}
                        onOpenRenderDebug={() => setShowRenderDebug(true)}
                    />
                    <MainToolbar
                        messageHub={messageHub || undefined}
                        commandManager={commandManager}
                        onSaveScene={handleSaveScene}
                        onOpenScene={handleOpenScene}
                    />
                </>
            )}

            <CompilerConfigDialog
                isOpen={compilerDialog.isOpen}
                compilerId={compilerDialog.compilerId}
                projectPath={currentProjectPath}
                currentFileName={compilerDialog.currentFileName}
                onClose={closeCompilerDialog}
                onCompileComplete={(result) => {
                    if (result.success) {
                        showToast(result.message, 'success');
                    } else {
                        showToast(result.message, 'error');
                    }
                }}
            />

            <div className="editor-content">
                <FlexLayoutDockContainer
                    ref={layoutContainerRef}
                    panels={panels}
                    activePanelId={activePanelId}
                    messageHub={messageHubRef.current}
                    onPanelClose={(panelId) => {
                        logger.info('Panel closed:', panelId);
                        // 如果关闭的是内容管理器，重置停靠状态
                        // If closing content browser, reset dock state
                        if (panelId === 'content-browser') {
                            setIsContentBrowserDocked(false);
                        }
                        removeDynamicPanel(panelId);
                    }}
                />
            </div>

            <StatusBar
                pluginCount={pluginManager?.getAllPlugins().length ?? 0}
                entityCount={entityStore?.getAllEntities().length ?? 0}
                messageHub={messageHub}
                logService={logService}
                locale={locale}
                projectPath={currentProjectPath}
                onOpenScene={handleOpenSceneByPath}
                onDockContentBrowser={() => setIsContentBrowserDocked(true)}
                onResetLayout={() => layoutContainerRef.current?.resetLayout()}
            />


            {(showProfiler || showAdvancedProfiler) && (
                <AdvancedProfilerWindow onClose={() => {
                    setShowProfiler(false);
                    setShowAdvancedProfiler(false);
                }} />
            )}

            {showPortManager && (
                <PortManager onClose={() => setShowPortManager(false)} />
            )}

            {showSettings && settingsRegistry && (
                <SettingsWindow
                    onClose={() => {
                        setShowSettings(false);
                        setSettingsInitialCategory(undefined);
                    }}
                    settingsRegistry={settingsRegistry}
                    initialCategoryId={settingsInitialCategory}
                />
            )}

            {showAbout && (
                <AboutDialog onClose={() => setShowAbout(false)} />
            )}

            {showPluginGenerator && (
                <PluginGeneratorWindow
                    onClose={() => setShowPluginGenerator(false)}
                    projectPath={currentProjectPath}
                    onSuccess={async () => {
                        if (currentProjectPath && pluginManager) {
                            await pluginLoader.loadProjectPlugins(currentProjectPath, pluginManager);
                        }
                    }}
                />
            )}

            {showBuildSettings && (
                <BuildSettingsWindow
                    onClose={() => setShowBuildSettings(false)}
                    projectPath={currentProjectPath || undefined}
                    buildService={buildService || undefined}
                    sceneManager={sceneManager || undefined}
                    projectService={projectServiceState || undefined}
                    availableScenes={availableScenes}
                />
            )}

            {/* 渲染调试面板 | Render Debug Panel */}
            <RenderDebugPanel
                visible={showRenderDebug}
                onClose={() => setShowRenderDebug(false)}
            />

            {errorDialog && (
                <ErrorDialog
                    title={errorDialog.title}
                    message={errorDialog.message}
                    onClose={() => setErrorDialog(null)}
                />
            )}

            {confirmDialog && (
                <ConfirmDialog
                    title={confirmDialog.title}
                    message={confirmDialog.message}
                    confirmText={confirmDialog.confirmText}
                    cancelText={confirmDialog.cancelText}
                    onConfirm={() => {
                        confirmDialog.onConfirm();
                        setConfirmDialog(null);
                    }}
                    onCancel={() => {
                        if (confirmDialog.onCancel) {
                            confirmDialog.onCancel();
                        }
                        setConfirmDialog(null);
                    }}
                />
            )}

            {externalModificationDialog && (
                <ExternalModificationDialog
                    sceneName={externalModificationDialog.sceneName}
                    onReload={externalModificationDialog.onReload}
                    onOverwrite={externalModificationDialog.onOverwrite}
                    onCancel={() => setExternalModificationDialog(null)}
                />
            )}
        </div>
    );
}

function AppWithToast() {
    return (
        <ToastProvider>
            <App />
        </ToastProvider>
    );
}

export default AppWithToast;
