using System.ComponentModel;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Animation;
using Microsoft.UI.Xaml.Media.Imaging;
using Microsoft.UI.Text;
using Windows.System;
using Windows.UI.Text;
using Microsoft.UI;
using Microsoft.UI.Input;
using Microsoft.UI.Windowing;
using Windows.Graphics;
using Windows.UI;
using WinRT.Interop;
using YMhut.Box.Core.Downloads;
using YMhut.Box.Core.Logging;
using YMhut.Box.Core.Plugins;
using YMhut.Box.Core.Settings;
using YMhut.Box.Core.Startup;
using YMhut.Box.Core.Tools;
using YMhut.Box.Core.Updates;
using YMhut.Box.WinUI.Controls;
using YMhut.Box.WinUI.Services;
using YMhut.Box.WinUI.Views;
using YMhut.Box.WinUI.Views.Tools;
using WinDispatcherQueueTimer = Microsoft.UI.Dispatching.DispatcherQueueTimer;

namespace YMhut.Box.WinUI;

public sealed partial class MainWindow : Window
{
    private ToolCatalog _catalog = AppServices.GetRequiredService<ToolCatalog>();
    private readonly ISettingsService _settingsService = AppServices.GetRequiredService<ISettingsService>();
    private readonly ILogService _logService = AppServices.GetRequiredService<ILogService>();
    private readonly IPluginHostProcessService _pluginHost = AppServices.GetRequiredService<IPluginHostProcessService>();
    private readonly WindowStateService _windowStateService = AppServices.GetRequiredService<WindowStateService>();
    private readonly ITrayService _trayService = AppServices.GetRequiredService<ITrayService>();
    private readonly IAppVersionService _versionService = AppServices.GetRequiredService<IAppVersionService>();
    private readonly IAppInstallerUpdateService _updateService = AppServices.GetRequiredService<IAppInstallerUpdateService>();
    private readonly ITitleWeatherService _titleWeatherService = AppServices.GetRequiredService<ITitleWeatherService>();
    private readonly IDownloadManagerService _downloadManager = AppServices.GetRequiredService<IDownloadManagerService>();
    private readonly IExternalToolCatalogService _externalToolCatalog = AppServices.GetRequiredService<IExternalToolCatalogService>();
    private readonly IBuiltinReferenceToolCatalog _builtinToolCatalog = AppServices.GetRequiredService<IBuiltinReferenceToolCatalog>();
    private readonly IStartupInitializationService _startupInitialization = AppServices.GetRequiredService<IStartupInitializationService>();
    private readonly IInstallIntegrityCheckService _integrityCheckService = AppServices.GetRequiredService<IInstallIntegrityCheckService>();
    private readonly IUiPerformanceCoordinator _uiPerformanceCoordinator = AppServices.GetRequiredService<IUiPerformanceCoordinator>();
    private readonly WebView2EnvironmentFactory _webViewEnvironmentFactory = AppServices.GetRequiredService<WebView2EnvironmentFactory>();
    private readonly IToolPageFactory _toolPageFactory = ToolPageRegistry.Current;
    private readonly PropertyChangedEventHandler _settingsChangedHandler;
    private readonly Dictionary<ShellPage, NavigationViewItem> _navItems = [];
    private readonly HashSet<string> _installPromptsShown = [];
    private NavigationViewItem DownloadNavItem = null!;

    private bool _startupServicesInitialized;
    private bool _initialPageShown;
    private string _lastLanguage = "zh-CN";
    private ShellPage _currentPage = ShellPage.Home;
    private ToolboxPage? _toolboxPage;
    private ToolboxNavigationState _toolboxState = ToolboxNavigationState.Default;
    private bool _pluginReloadInProgress;
    private string? _activePluginId;
    private string? _activePluginSurfaceId;
    private bool _searchFocusAllowedByPointer;
    private InputNonClientPointerSource? _nonClientPointerSource;
    private StackPanel? _titleActionsPanel;
    private WinDispatcherQueueTimer? _responsiveShellTimer;
    private WinDispatcherQueueTimer? _titleBarDragRegionTimer;
    private WindowMovePerformanceHelper? _movePerformanceHelper;
    private IDisposable? _moveLightModeScope;
    private RectInt32[] _lastTitleCaptionRects = [];
    private RectInt32[] _lastTitlePassthroughRects = [];
    private bool _hasResponsiveShellState;
    private bool _lastResponsiveWide;
    private bool _lastResponsiveDesktop;
    private bool _lastResponsivePhone;
    private double _lastResponsiveWidth;
    private bool _windowMoveLoopActive;
    private WeatherCapsuleControl? WeatherCapsule;
    private bool _syncingQuickSettings;
    private bool _isClosed;
    private ToggleSwitch? QuickProxySwitch;
    private ToggleSwitch? QuickUpdateSwitch;
    private ToggleSwitch? QuickHardwareAccelerationSwitch;
    private ToggleSwitch? QuickPluginSwitch;
    private Button? QuickLanguageZhButton;
    private Button? QuickLanguageEnButton;
    private Button? QuickHomeSolarButton;
    private Button? QuickHomeDashboardButton;
    private Button? QuickBackdropMicaButton;
    private Button? QuickBackdropAcrylicButton;
    private Button? QuickBackdropSolidButton;
    private Button? QuickTopInheritButton;
    private Button? QuickTopAcrylicButton;
    private Button? QuickTopSolidButton;
    private Button? QuickContentSolidButton;
    private Button? QuickContentAcrylicButton;
    private Button? QuickContentGlassButton;
    private Button? QuickCloseAskButton;
    private Button? QuickCloseMinimizeButton;
    private Button? QuickCloseExitButton;
    private Button? QuickOpenSettingsButton;

    public MainWindow()
    {
        StartupTrace.Write("MainWindow.ctor:start");
        BuildShellContent();
        Title = "YMhut Box";
        WindowIconService.ApplyAppIcon(this);
        ExtendsContentIntoTitleBar = true;
        SetTitleBar(TitleDragArea);
        ConfigureTitleBarDragRegions();
        _movePerformanceHelper = WindowMovePerformanceHelper.Attach(
            this,
            () => _settingsService.Current.WindowBackdrop,
            active =>
            {
                _windowMoveLoopActive = active;
                if (active)
                {
                    _moveLightModeScope ??= _uiPerformanceCoordinator.EnterLightMode("main-window-move");
                }
                else
                {
                    _moveLightModeScope?.Dispose();
                    _moveLightModeScope = null;
                }

                ApplyShellTheme();
            });
        ToastService.Attach(ToastPresenter);

        ConfigureNavigationItems();
        RegisterShellEvents();
        _downloadManager.ItemsChanged += DownloadManager_ItemsChanged;
        _pluginHost.SnapshotChanged += PluginHost_SnapshotChanged;
        _pluginHost.StatusChanged += PluginHost_StatusChanged;
        _settingsChangedHandler = (_, _) =>
        {
            if (_isClosed)
            {
                return;
            }

            DispatcherQueue.TryEnqueue(() =>
            {
                if (_isClosed)
                {
                    return;
                }

                ApplyLanguage();
                ThemeService.ApplyTheme(this, _settingsService.Current.Theme, _settingsService.Current.WindowBackdrop);
                ApplyShellTheme();
                RefreshQuickSettingsControls();
                RefreshPluginNavigation();
                RefreshNavigationRail();
            });
        };
        _settingsService.PropertyChanged += _settingsChangedHandler;

        RootLayout.Loaded += MainWindow_Loaded;
        Closed += (_, _) =>
        {
            _isClosed = true;
            _settingsService.PropertyChanged -= _settingsChangedHandler;
            _movePerformanceHelper?.Dispose();
            _moveLightModeScope?.Dispose();
            _pluginHost.Dispose();
            if (_downloadManager is IDisposable disposableDownloadManager)
            {
                disposableDownloadManager.Dispose();
            }
        };
        RootLayout.SizeChanged += (_, _) =>
        {
            try
            {
                ScheduleResponsiveShellUpdate();
                ScheduleTitleBarDragRegionUpdate();
            }
            catch (Exception exception)
            {
                CrashLog.Write(exception);
            }
        };
        StartupTrace.Write("MainWindow.ctor:after-build");
    }

    private void BuildShellContent()
    {
        RootLayout = new Grid { Background = ModernUi.AppBackground };
        RootLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(52) });
        RootLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });

        AppTitleBar = new Grid
        {
            Padding = new Thickness(16, 6, 16, 6),
            Background = ModernUi.SidebarBackground,
            BorderBrush = ModernUi.Stroke,
            BorderThickness = new Thickness(0, 0, 0, 1)
        };
        AppTitleBar.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(240) });
        AppTitleBar.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
        AppTitleBar.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });

        TitleDragArea = new Border { Background = ModernUi.Brush("#00FFFFFF") };
        Grid.SetColumn(TitleDragArea, 0);
        Grid.SetColumnSpan(TitleDragArea, 3);
        AppTitleBar.Children.Add(TitleDragArea);

        var brandPanel = new StackPanel
        {
            Orientation = Orientation.Horizontal,
            Spacing = 10,
            VerticalAlignment = VerticalAlignment.Center
        };
        brandPanel.Children.Add(new Border
        {
            Width = 32,
            Height = 32,
            CornerRadius = new CornerRadius(6),
            Background = ModernUi.Surface,
            BorderBrush = ModernUi.Stroke,
            BorderThickness = new Thickness(1),
            Child = new Image
            {
                Source = new BitmapImage(new Uri("ms-appx:///Assets/icons/app_icon.png")),
                Width = 22,
                Height = 22,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            }
        });
        VersionText = new TextBlock
        {
            Text = $"v{_versionService.GetCurrent().Version}",
            FontSize = 11,
            Foreground = ModernUi.TextSecondary
        };
        brandPanel.Children.Add(new StackPanel
        {
            VerticalAlignment = VerticalAlignment.Center,
            Spacing = 0,
            Children =
            {
                new TextBlock
                {
                    Text = "YMhut Box",
                    FontSize = 14,
                    FontWeight = FontWeights.SemiBold,
                    Foreground = ModernUi.TextPrimary
                },
                VersionText
            }
        });
        AppTitleBar.Children.Add(brandPanel);

        GlobalSearchBox = new AutoSuggestBox
        {
            IsTabStop = false,
            MinWidth = 220,
            MaxWidth = 580,
            Height = 36,
            QueryIcon = new SymbolIcon(Symbol.Find),
            PlaceholderText = "搜索工具、页面或命令 (Ctrl+K)",
            HorizontalAlignment = HorizontalAlignment.Stretch,
            Margin = new Thickness(16, 0, 16, 0),
            VerticalAlignment = VerticalAlignment.Center
        };
        Grid.SetColumn(GlobalSearchBox, 1);
        AppTitleBar.Children.Add(GlobalSearchBox);
        GlobalSearchBox.AddHandler(
            UIElement.PointerPressedEvent,
            new PointerEventHandler((_, _) => _searchFocusAllowedByPointer = true),
            true);
        GlobalSearchBox.GettingFocus += GlobalSearchBox_GettingFocus;
        GlobalSearchBox.LostFocus += (_, _) => _searchFocusAllowedByPointer = false;

        CloudButton = CreateTitleButton("\uE753");
        QuickSettingsButton = CreateTitleButton("\uE9D2");
        ThemeToggleButton = CreateTitleButton("\uE706");
        WeatherCapsule = new WeatherCapsuleControl(_titleWeatherService);
        _titleActionsPanel = new StackPanel
        {
            Orientation = Orientation.Horizontal,
            Spacing = 8,
            Margin = new Thickness(0, 0, 146, 0),
            VerticalAlignment = VerticalAlignment.Center,
            Children = { WeatherCapsule, CloudButton, QuickSettingsButton, ThemeToggleButton }
        };
        Grid.SetColumn(_titleActionsPanel, 2);
        AppTitleBar.Children.Add(_titleActionsPanel);
        RootLayout.Children.Add(AppTitleBar);

        RootNavigation = new NavigationView
        {
            IsBackButtonVisible = NavigationViewBackButtonVisible.Collapsed,
            IsSettingsVisible = false,
            PaneDisplayMode = NavigationViewPaneDisplayMode.LeftCompact,
            IsPaneOpen = false,
            CompactPaneLength = 56,
            OpenPaneLength = 248,
            SelectionFollowsFocus = NavigationViewSelectionFollowsFocus.Disabled,
            Background = ModernUi.AppBackground
        };
        HomeNavItem = CreateNavItem("首页", "home", "\uE80F");
        ToolboxNavItem = CreateNavItem("工具箱", "toolbox", "\uE90F");
        LogsNavItem = CreateNavItem("日志", "logs", "\uE9F9");
        PluginsNavItem = CreateNavItem("插件", "plugins", "\uECAA");
        FeedbackNavItem = CreateNavItem("反馈", "feedback", "\uE939");
        SettingsNavItem = CreateNavItem("设置", "settings", "\uE713");
        AboutNavItem = CreateNavItem("关于", "about", "\uE946");
        DownloadNavItem = CreateNavItem("下载管理", "downloads", "\uE896");
        RootNavigation.MenuItems.Add(HomeNavItem);
        RootNavigation.MenuItems.Add(ToolboxNavItem);
        RootNavigation.MenuItems.Add(LogsNavItem);
        RootNavigation.MenuItems.Add(DownloadNavItem);
        RootNavigation.FooterMenuItems.Add(PluginsNavItem);
        RootNavigation.FooterMenuItems.Add(FeedbackNavItem);
        RootNavigation.FooterMenuItems.Add(SettingsNavItem);
        RootNavigation.FooterMenuItems.Add(AboutNavItem);
        ContentHost = new ContentControl
        {
            IsTabStop = true,
            HorizontalContentAlignment = HorizontalAlignment.Stretch,
            VerticalContentAlignment = VerticalAlignment.Stretch,
            HorizontalAlignment = HorizontalAlignment.Stretch,
            VerticalAlignment = VerticalAlignment.Stretch
        };
        RootNavigation.Content = ContentHost;
        Grid.SetRow(RootNavigation, 1);
        RootLayout.Children.Add(RootNavigation);

        QuickSettingsOverlay = BuildQuickSettingsOverlay();
        Grid.SetRowSpan(QuickSettingsOverlay, 2);
        RootLayout.Children.Add(QuickSettingsOverlay);

        ToastPresenter = new StackPanel
        {
            HorizontalAlignment = HorizontalAlignment.Right,
            VerticalAlignment = VerticalAlignment.Bottom,
            Margin = new Thickness(0, 0, 24, 24),
            Spacing = 10,
            IsHitTestVisible = false
        };
        Grid.SetRowSpan(ToastPresenter, 2);
        RootLayout.Children.Add(ToastPresenter);

        Content = RootLayout;
    }

    private void ConfigureTitleBarDragRegions()
    {
        try
        {
            var hwnd = WindowNative.GetWindowHandle(this);
            var windowId = Win32Interop.GetWindowIdFromWindow(hwnd);
            _nonClientPointerSource = InputNonClientPointerSource.GetForWindowId(windowId);

            AppTitleBar.Loaded += (_, _) => ScheduleTitleBarDragRegionUpdate(TimeSpan.FromMilliseconds(1));
            AppTitleBar.SizeChanged += (_, _) => ScheduleTitleBarDragRegionUpdate();
            GlobalSearchBox.SizeChanged += (_, _) => ScheduleTitleBarDragRegionUpdate();
            if (_titleActionsPanel is not null)
            {
                _titleActionsPanel.SizeChanged += (_, _) => ScheduleTitleBarDragRegionUpdate();
            }
        }
        catch (Exception exception)
        {
            CrashLog.Write(exception);
        }
    }

    private void UpdateTitleBarDragRegions()
    {
        var source = _nonClientPointerSource;
        if (source is null || AppTitleBar.XamlRoot is null || AppTitleBar.ActualWidth <= 0 || AppTitleBar.ActualHeight <= 0)
        {
            return;
        }

        try
        {
            var scale = AppTitleBar.XamlRoot.RasterizationScale;
            var rightLimit = Math.Max(0, AppTitleBar.ActualWidth - 146);
            var segments = new List<(double Left, double Right)> { (0, rightLimit) };
            var passthrough = new List<RectInt32>();

            foreach (var bounds in new[] { BoundsInTitleBar(GlobalSearchBox), BoundsInTitleBar(_titleActionsPanel) })
            {
                if (bounds is null)
                {
                    continue;
                }

                var expandedLeft = Math.Max(0, bounds.Value.Left - 6);
                var expandedRight = Math.Min(rightLimit, bounds.Value.Right + 6);
                passthrough.Add(ToPixelRect(bounds.Value.Left, bounds.Value.Top, bounds.Value.Width, bounds.Value.Height, scale));
                segments = SubtractSegment(segments, expandedLeft, expandedRight);
            }

            var captionRects = segments
                .Where(segment => segment.Right - segment.Left > 8)
                .Select(segment => ToPixelRect(segment.Left, 0, segment.Right - segment.Left, AppTitleBar.ActualHeight, scale))
                .ToArray();
            var passthroughRects = passthrough.ToArray();

            if (RectsEqual(_lastTitleCaptionRects, captionRects) &&
                RectsEqual(_lastTitlePassthroughRects, passthroughRects))
            {
                return;
            }

            source.SetRegionRects(NonClientRegionKind.Caption, captionRects);
            source.SetRegionRects(NonClientRegionKind.Passthrough, passthroughRects);
            _lastTitleCaptionRects = captionRects;
            _lastTitlePassthroughRects = passthroughRects;
        }
        catch (Exception exception)
        {
            CrashLog.Write(exception);
        }
    }

    private Windows.Foundation.Rect? BoundsInTitleBar(FrameworkElement? element)
    {
        if (element is null || element.Visibility != Visibility.Visible || element.ActualWidth <= 0 || element.ActualHeight <= 0)
        {
            return null;
        }

        try
        {
            var point = element.TransformToVisual(AppTitleBar).TransformPoint(new Windows.Foundation.Point(0, 0));
            return new Windows.Foundation.Rect(point.X, point.Y, element.ActualWidth, element.ActualHeight);
        }
        catch
        {
            return null;
        }
    }

    private static List<(double Left, double Right)> SubtractSegment(
        List<(double Left, double Right)> segments,
        double excludeLeft,
        double excludeRight)
    {
        if (excludeRight <= excludeLeft)
        {
            return segments;
        }

        var result = new List<(double Left, double Right)>();
        foreach (var segment in segments)
        {
            if (excludeRight <= segment.Left || excludeLeft >= segment.Right)
            {
                result.Add(segment);
                continue;
            }

            if (excludeLeft > segment.Left)
            {
                result.Add((segment.Left, excludeLeft));
            }

            if (excludeRight < segment.Right)
            {
                result.Add((excludeRight, segment.Right));
            }
        }

        return result;
    }

    private static RectInt32 ToPixelRect(double x, double y, double width, double height, double scale)
    {
        return new RectInt32
        {
            X = (int)Math.Round(x * scale),
            Y = (int)Math.Round(y * scale),
            Width = Math.Max(1, (int)Math.Round(width * scale)),
            Height = Math.Max(1, (int)Math.Round(height * scale))
        };
    }

    private void ScheduleTitleBarDragRegionUpdate(TimeSpan? delay = null)
    {
        if (_isClosed)
        {
            return;
        }

        _titleBarDragRegionTimer ??= CreateOneShotTimer(
            delay ?? TimeSpan.FromMilliseconds(48),
            UpdateTitleBarDragRegions);
        _titleBarDragRegionTimer.Interval = delay ?? TimeSpan.FromMilliseconds(48);
        _titleBarDragRegionTimer.Stop();
        _titleBarDragRegionTimer.Start();
    }

    private void ScheduleResponsiveShellUpdate()
    {
        if (_isClosed)
        {
            return;
        }

        _responsiveShellTimer ??= CreateOneShotTimer(
            TimeSpan.FromMilliseconds(72),
            ApplyResponsiveShell);
        _responsiveShellTimer.Stop();
        _responsiveShellTimer.Start();
    }

    private WinDispatcherQueueTimer CreateOneShotTimer(TimeSpan interval, Action callback)
    {
        var timer = DispatcherQueue.CreateTimer();
        timer.Interval = interval;
        timer.IsRepeating = false;
        timer.Tick += (_, _) =>
        {
            try
            {
                callback();
            }
            catch (Exception exception)
            {
                CrashLog.Write(exception);
            }
        };
        return timer;
    }

    private static bool RectsEqual(IReadOnlyList<RectInt32> left, IReadOnlyList<RectInt32> right)
    {
        if (left.Count != right.Count)
        {
            return false;
        }

        for (var i = 0; i < left.Count; i++)
        {
            if (left[i].X != right[i].X ||
                left[i].Y != right[i].Y ||
                left[i].Width != right[i].Width ||
                left[i].Height != right[i].Height)
            {
                return false;
            }
        }

        return true;
    }

    private static Button CreateTitleButton(string glyph)
    {
        return new Button
        {
            Width = 34,
            Height = 34,
            Padding = new Thickness(0),
            CornerRadius = new CornerRadius(6),
            UseSystemFocusVisuals = true,
            Background = ModernUi.Brush("#00FFFFFF"),
            BorderBrush = ModernUi.Brush("#00FFFFFF"),
            Content = new FontIcon { Glyph = glyph, FontSize = 15 }
        };
    }

    private static NavigationViewItem CreateNavItem(string content, string tag, string glyph)
    {
        return new NavigationViewItem
        {
            Content = content,
            Tag = tag,
            Icon = new FontIcon { Glyph = glyph },
            UseSystemFocusVisuals = true
        };
    }

    private Grid BuildQuickSettingsOverlay()
    {
        QuickSettingsScrim = new Border { Background = ModernUi.Brush("#66000000") };
        QuickSettingsTransform = new TranslateTransform { X = 420 };
        CloseQuickSettingsButton = CreateTitleButton("\uE711");
        CloseQuickSettingsButton.Width = 38;
        QuickLightButton = QuickOptionButton("浅色", "Light");
        QuickDarkButton = QuickOptionButton("深色", "Dark");
        QuickLanguageZhButton = QuickOptionButton("中文", "Chinese");
        QuickLanguageEnButton = QuickOptionButton("English", "English");
        QuickHomeSolarButton = QuickOptionButton("太阳系", "Solar");
        QuickHomeDashboardButton = QuickOptionButton("仪表盘", "Dashboard");
        QuickBackdropMicaButton = QuickOptionButton("云母", "Mica");
        QuickBackdropAcrylicButton = QuickOptionButton("亚克力", "Acrylic");
        QuickBackdropSolidButton = QuickOptionButton("纯色", "Solid");
        QuickTopInheritButton = QuickOptionButton("继承", "Inherit");
        QuickTopAcrylicButton = QuickOptionButton("亚克力", "Acrylic");
        QuickTopSolidButton = QuickOptionButton("纯色", "Solid");
        QuickContentSolidButton = QuickOptionButton("纯色", "Solid");
        QuickContentAcrylicButton = QuickOptionButton("亚克力", "Acrylic");
        QuickContentGlassButton = QuickOptionButton("毛玻璃", "Glass");
        QuickCloseAskButton = QuickOptionButton("询问", "Ask");
        QuickCloseMinimizeButton = QuickOptionButton("托盘", "Tray");
        QuickCloseExitButton = QuickOptionButton("退出", "Exit");
        QuickAnimationSwitch = QuickSwitch("界面动画", "Animations");
        QuickProxySwitch = QuickSwitch("启用代理", "Use proxy");
        QuickUpdateSwitch = QuickSwitch("更新提醒", "Update reminders");
        QuickHardwareAccelerationSwitch = QuickSwitch("硬件加速", "Hardware acceleration");
        QuickPluginSwitch = QuickSwitch("插件系统", "Plugin system");
        QuickFontSmallButton = QuickOptionButton("小", "Small");
        QuickFontNormalButton = QuickOptionButton("标准", "Normal");
        QuickFontLargeButton = QuickOptionButton("大", "Large");
        QuickOpenSettingsButton = ModernUi.PillButton(AppLocalizer.T("打开完整设置", "Open full settings"), "\uE713", () =>
        {
            HideQuickSettings();
            ShowSettingsPage();
        }, primary: true);
        QuickOpenSettingsButton.Tag = new LocalizedText("打开完整设置", "Open full settings");
        QuickOpenSettingsButton.HorizontalAlignment = HorizontalAlignment.Stretch;

        var header = new Grid();
        header.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
        header.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        header.Children.Add(new StackPanel
        {
            Spacing = 4,
            Children =
            {
                QuickText("快速设置", "Quick settings", 24, FontWeights.SemiBold),
                QuickText("常用显示、行为和运行选项集中在这里。", "Common display, behavior, and runtime options live here.", 14, foreground: ModernUi.TextSecondary)
            }
        });
        Grid.SetColumn(CloseQuickSettingsButton, 1);
        header.Children.Add(CloseQuickSettingsButton);

        QuickSettingsPanel = new Border
        {
            Width = 420,
            HorizontalAlignment = HorizontalAlignment.Right,
            Background = ModernUi.SidebarBackground,
            BorderBrush = ModernUi.Stroke,
            BorderThickness = new Thickness(1, 0, 0, 0),
            RenderTransform = QuickSettingsTransform,
            Child = new ScrollViewer
            {
                VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
                HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled,
                Padding = new Thickness(0, 0, 8, 0),
                Content = new StackPanel
                {
                    Padding = new Thickness(22, 24, 14, 22),
                    Spacing = 16,
                    Children =
                    {
                        header,
                        QuickSettingsCard("外观", "Appearance", "\uE706",
                            QuickLabel("主题", "Theme"),
                            QuickColumns(QuickLightButton, QuickDarkButton),
                            QuickLabel("窗口材质", "Window material"),
                            QuickColumns(QuickBackdropMicaButton, QuickBackdropAcrylicButton, QuickBackdropSolidButton),
                            QuickLabel("顶部材质", "Top bar material"),
                            QuickColumns(QuickTopInheritButton, QuickTopAcrylicButton, QuickTopSolidButton),
                            QuickLabel("内容材质", "Content material"),
                            QuickColumns(QuickContentSolidButton, QuickContentAcrylicButton, QuickContentGlassButton),
                            QuickLabel("字体缩放", "Font scale"),
                            QuickColumns(QuickFontSmallButton, QuickFontNormalButton, QuickFontLargeButton),
                            QuickAnimationSwitch),
                        QuickSettingsCard("页面与输入", "Pages and input", "\uE80F",
                            QuickLabel("首页内容", "Home content"),
                            QuickColumns(QuickHomeSolarButton, QuickHomeDashboardButton),
                            QuickLabel("语言", "Language"),
                            QuickColumns(QuickLanguageZhButton, QuickLanguageEnButton),
                            QuickLabel("关闭按钮", "Close button"),
                            QuickColumns(QuickCloseAskButton, QuickCloseMinimizeButton, QuickCloseExitButton)),
                        QuickSettingsCard("运行选项", "Runtime options", "\uE7F4",
                            QuickProxySwitch,
                            QuickUpdateSwitch,
                            QuickHardwareAccelerationSwitch,
                            QuickPluginSwitch),
                        QuickOpenSettingsButton
                    }
                }
            }
        };

        return new Grid
        {
            Visibility = Visibility.Collapsed,
            Opacity = 0,
            Children = { QuickSettingsScrim, QuickSettingsPanel }
        };
    }

    private Button QuickOptionButton(string zh, string en)
    {
        var label = AppLocalizer.T(zh, en);
        var button = new Button
        {
            Content = label,
            Tag = new LocalizedText(zh, en),
            HorizontalAlignment = HorizontalAlignment.Stretch,
            Padding = new Thickness(10, 7, 10, 7),
            CornerRadius = new CornerRadius(6),
            BorderThickness = new Thickness(1),
            UseSystemFocusVisuals = true
        };
        ToolTipService.SetToolTip(button, label);
        AutomationProperties.SetName(button, label);
        return button;
    }

    private ToggleSwitch QuickSwitch(string zh, string en)
    {
        var label = AppLocalizer.T(zh, en);
        var toggle = new ToggleSwitch
        {
            Header = label,
            Tag = new LocalizedText(zh, en),
            HorizontalAlignment = HorizontalAlignment.Stretch
        };
        AutomationProperties.SetName(toggle, label);
        return toggle;
    }

    private TextBlock QuickLabel(string zh, string en)
    {
        return QuickText(zh, en, 13, FontWeights.SemiBold, ModernUi.TextSecondary, maxLines: 1);
    }

    private static Grid QuickColumns(params FrameworkElement?[] elements)
    {
        var grid = new Grid { ColumnSpacing = 8 };
        var column = 0;
        foreach (var element in elements.Where(element => element is not null))
        {
            grid.ColumnDefinitions.Add(new ColumnDefinition());
            Grid.SetColumn(element!, column++);
            grid.Children.Add(element!);
        }

        return grid;
    }

    private Border QuickSettingsCard(string zh, string en, string glyph, params UIElement?[] rows)
    {
        var stack = new StackPanel { Spacing = 12 };
        stack.Children.Add(new StackPanel
        {
            Orientation = Orientation.Horizontal,
            Spacing = 10,
            Children =
            {
                ModernUi.IconTile(glyph, 32, ModernUi.SurfaceAlt, ModernUi.Accent, 15),
                QuickText(zh, en, 18, FontWeights.SemiBold)
            }
        });
        foreach (var row in rows.Where(row => row is not null))
        {
            stack.Children.Add(row!);
        }

        return ModernUi.Card(stack, new Thickness(16), radius: 8);
    }

    private TextBlock QuickText(string zh, string en, double size, FontWeight? weight = null, Brush? foreground = null, int maxLines = 0)
    {
        var text = ModernUi.Text(AppLocalizer.T(zh, en), size, weight, foreground, maxLines);
        text.Tag = new LocalizedText(zh, en);
        return text;
    }

    private void ConfigureNavigationItems()
    {
        _navItems[ShellPage.Home] = HomeNavItem;
        _navItems[ShellPage.Toolbox] = ToolboxNavItem;
        _navItems[ShellPage.Downloads] = DownloadNavItem;
        _navItems[ShellPage.Plugins] = PluginsNavItem;
        _navItems[ShellPage.Logs] = LogsNavItem;
        _navItems[ShellPage.Feedback] = FeedbackNavItem;
        _navItems[ShellPage.Settings] = SettingsNavItem;
        _navItems[ShellPage.About] = AboutNavItem;

        if (RootNavigation.MenuItems.Contains(PluginsNavItem))
        {
            RootNavigation.MenuItems.Remove(PluginsNavItem);
        }
        if (RootNavigation.FooterMenuItems.Contains(LogsNavItem))
        {
            RootNavigation.FooterMenuItems.Remove(LogsNavItem);
        }
        if (!RootNavigation.MenuItems.Contains(LogsNavItem))
        {
            var logsIndex = RootNavigation.MenuItems.IndexOf(ToolboxNavItem) + 1;
            RootNavigation.MenuItems.Insert(Math.Max(0, logsIndex), LogsNavItem);
        }
        if (!RootNavigation.FooterMenuItems.Contains(PluginsNavItem))
        {
            RootNavigation.FooterMenuItems.Insert(0, PluginsNavItem);
        }
        if (!RootNavigation.FooterMenuItems.Contains(FeedbackNavItem))
        {
            RootNavigation.FooterMenuItems.Insert(Math.Min(1, RootNavigation.FooterMenuItems.Count), FeedbackNavItem);
        }

        ToolTipService.SetToolTip(CloudButton, "服务状态");
        ToolTipService.SetToolTip(QuickSettingsButton, "快速设置");
        ToolTipService.SetToolTip(ThemeToggleButton, "切换主题");
        ConfigureTopButtonFeedback();
        ApplyLanguage();
        RootNavigation.PaneDisplayMode = NavigationViewPaneDisplayMode.LeftCompact;
        RootNavigation.IsPaneOpen = false;
        RootNavigation.SelectedItem = HomeNavItem;
        RefreshPluginNavigation();
    }

    private void ConfigureTopButtonFeedback()
    {
        foreach (var button in new[] { CloudButton, QuickSettingsButton, ThemeToggleButton })
        {
            button.PointerEntered += (_, _) =>
            {
                button.Background = ModernUi.SurfaceAlt;
                button.BorderBrush = ModernUi.Stroke;
            };
            button.PointerPressed += (_, _) =>
            {
                button.Background = ModernUi.AccentSoft;
                button.BorderBrush = ModernUi.Accent;
            };
            button.PointerReleased += (_, _) =>
            {
                button.Background = ModernUi.SurfaceAlt;
                button.BorderBrush = ModernUi.Stroke;
            };
            button.PointerExited += (_, _) =>
            {
                button.Background = ModernUi.Brush("#00FFFFFF");
                button.BorderBrush = ModernUi.Brush("#00FFFFFF");
            };
        }
    }

    private void ApplyLanguageLegacy()
    {
        var english = string.Equals(_settingsService.Current.Language, "en-US", StringComparison.OrdinalIgnoreCase);
        RefreshDownloadNavItem();
        HomeNavItem.Content = english ? "Home" : "首页";
        ToolboxNavItem.Content = english ? "Toolbox" : "工具箱";
        LogsNavItem.Content = english ? "Logs" : "日志";
        SettingsNavItem.Content = english ? "Settings" : "设置";
        AboutNavItem.Content = english ? "About" : "关于";
        PluginsNavItem.Content = english ? "Plugins" : "插件";
        FeedbackNavItem.Content = english ? "Feedback" : "反馈";
        GlobalSearchBox.PlaceholderText = english
            ? "Search tools, pages, or commands (Ctrl+K)"
            : "搜索工具、页面或命令 (Ctrl+K)";
        ToolTipService.SetToolTip(CloudButton, english ? "Service status" : "服务状态");
        ToolTipService.SetToolTip(QuickSettingsButton, english ? "Quick settings" : "快速设置");
        ToolTipService.SetToolTip(ThemeToggleButton, english ? "Switch theme" : "切换主题");
    }

    private void ApplyLanguage()
    {
        var language = _settingsService.Current.Language;
        var english = string.Equals(language, "en-US", StringComparison.OrdinalIgnoreCase);
        RefreshDownloadNavItem();
        HomeNavItem.Content = english ? "Home" : "首页";
        ToolboxNavItem.Content = english ? "Toolbox" : "工具箱";
        LogsNavItem.Content = english ? "Logs" : "日志";
        SettingsNavItem.Content = english ? "Settings" : "设置";
        AboutNavItem.Content = english ? "About" : "关于";
        PluginsNavItem.Content = english ? "Plugins" : "插件";
        FeedbackNavItem.Content = english ? "Feedback" : "反馈";
        GlobalSearchBox.PlaceholderText = english
            ? "Search tools, pages, or commands (Ctrl+K)"
            : "搜索工具、页面或命令 (Ctrl+K)";
        ApplyShellAutomationNames(english);
        WeatherCapsule?.RefreshLanguage();
        RefreshLocalizedQuickSettingsText(RootLayout);

        if (_initialPageShown && !string.Equals(_lastLanguage, language, StringComparison.OrdinalIgnoreCase))
        {
            _lastLanguage = language;
            RefreshCurrentPageForLanguage();
        }
        else
        {
            _lastLanguage = language;
        }
    }

    private void ApplyShellAutomationNames(bool english)
    {
        SetControlName(HomeNavItem, english ? "Home" : "首页");
        SetControlName(ToolboxNavItem, english ? "Toolbox" : "工具箱");
        SetControlName(LogsNavItem, english ? "Logs" : "日志");
        SetControlName(DownloadNavItem, english ? "Downloads" : "下载管理");
        SetControlName(PluginsNavItem, english ? "Plugins" : "插件");
        SetControlName(FeedbackNavItem, english ? "Feedback" : "反馈");
        SetControlName(SettingsNavItem, english ? "Settings" : "设置");
        SetControlName(AboutNavItem, english ? "About" : "关于");
        SetControlName(GlobalSearchBox, GlobalSearchBox.PlaceholderText);
        SetControlName(CloudButton, english ? "Service status" : "服务状态");
        SetControlName(QuickSettingsButton, english ? "Quick settings" : "快速设置");
        SetControlName(ThemeToggleButton, english ? "Switch theme" : "切换主题");
    }

    private static void SetControlName(FrameworkElement element, string name)
    {
        AutomationProperties.SetName(element, name);
        ToolTipService.SetToolTip(element, name);
    }

    private void RefreshLocalizedQuickSettingsText(DependencyObject root)
    {
        if (root is TextBlock textBlock && textBlock.Tag is LocalizedText text)
        {
            textBlock.Text = text.Current;
        }
        else if (root is Button button && button.Tag is LocalizedText buttonText)
        {
            if (button.Content is string)
            {
                button.Content = buttonText.Current;
            }
            else
            {
                UpdateLocalizedContent(button.Content);
                TryUpdateFirstTextBlock(button.Content, buttonText.Current);
            }

            AutomationProperties.SetName(button, buttonText.Current);
            ToolTipService.SetToolTip(button, buttonText.Current);
        }
        else if (root is ToggleSwitch toggle && toggle.Tag is LocalizedText toggleText)
        {
            toggle.Header = toggleText.Current;
            AutomationProperties.SetName(toggle, toggleText.Current);
        }
        else
        {
            UpdateLocalizedContent(root);
        }

        var count = VisualTreeHelper.GetChildrenCount(root);
        for (var index = 0; index < count; index++)
        {
            RefreshLocalizedQuickSettingsText(VisualTreeHelper.GetChild(root, index));
        }
    }

    private static void UpdateLocalizedContent(object? content)
    {
        if (content is TextBlock textBlock && textBlock.Tag is LocalizedText text)
        {
            textBlock.Text = text.Current;
        }
        else if (content is Panel panel)
        {
            foreach (var child in panel.Children)
            {
                UpdateLocalizedContent(child);
            }
        }
        else if (content is Border border)
        {
            UpdateLocalizedContent(border.Child);
        }
        else if (content is ContentControl contentControl)
        {
            UpdateLocalizedContent(contentControl.Content);
        }
    }

    private static bool TryUpdateFirstTextBlock(object? content, string value)
    {
        if (content is TextBlock textBlock)
        {
            textBlock.Text = value;
            return true;
        }

        if (content is Panel panel)
        {
            foreach (var child in panel.Children)
            {
                if (TryUpdateFirstTextBlock(child, value))
                {
                    return true;
                }
            }
        }
        else if (content is Border border)
        {
            return TryUpdateFirstTextBlock(border.Child, value);
        }
        else if (content is ContentControl contentControl)
        {
            return TryUpdateFirstTextBlock(contentControl.Content, value);
        }

        return false;
    }

    private void RefreshCurrentPageForLanguage()
    {
        switch (_currentPage)
        {
            case ShellPage.Home:
                ShowHomePage();
                break;
            case ShellPage.Toolbox:
                ShowToolboxPage();
                break;
            case ShellPage.Downloads:
                ShowDownloadManagerPage();
                break;
            case ShellPage.ServiceStatus:
                ShowServiceStatusPage();
                break;
            case ShellPage.Plugins:
                ShowPluginsPage();
                break;
            case ShellPage.Logs:
                ShowLogsPage();
                break;
            case ShellPage.Feedback:
                ShowFeedbackPage();
                break;
            case ShellPage.Settings:
                ShowSettingsPage();
                break;
            case ShellPage.About:
                ShowAboutPage();
                break;
        }
    }

    private void RegisterShellEvents()
    {
        RootNavigation.ItemInvoked += RootNavigation_ItemInvoked;
        CloudButton.Click += (_, _) => ShowServiceStatusPage();
        QuickSettingsButton.Click += (_, _) => ShowQuickSettings();
        CloseQuickSettingsButton.Click += (_, _) => HideQuickSettings();
        QuickSettingsScrim.Tapped += (_, _) => HideQuickSettings();
        QuickSettingsPanel.Tapped += (_, e) => e.Handled = true;
        ThemeToggleButton.Click += async (_, _) => await ToggleThemeAsync();
        QuickLightButton.Click += async (_, _) => await SetThemeAsync("Light");
        QuickDarkButton.Click += async (_, _) => await SetThemeAsync("Dark");
        QuickLanguageZhButton!.Click += async (_, _) => await SetLanguageAsync("zh-CN");
        QuickLanguageEnButton!.Click += async (_, _) => await SetLanguageAsync("en-US");
        QuickHomeSolarButton!.Click += async (_, _) => await SetHomePageModeAsync("solar");
        QuickHomeDashboardButton!.Click += async (_, _) => await SetHomePageModeAsync("dashboard");
        QuickBackdropMicaButton!.Click += async (_, _) => await SetWindowBackdropAsync("mica");
        QuickBackdropAcrylicButton!.Click += async (_, _) => await SetWindowBackdropAsync("acrylic");
        QuickBackdropSolidButton!.Click += async (_, _) => await SetWindowBackdropAsync("solid");
        QuickTopInheritButton!.Click += async (_, _) => await SetTopBarMaterialAsync("inherit");
        QuickTopAcrylicButton!.Click += async (_, _) => await SetTopBarMaterialAsync("acrylic");
        QuickTopSolidButton!.Click += async (_, _) => await SetTopBarMaterialAsync("solid");
        QuickContentSolidButton!.Click += async (_, _) => await SetContentMaterialAsync("solid");
        QuickContentAcrylicButton!.Click += async (_, _) => await SetContentMaterialAsync("acrylic");
        QuickContentGlassButton!.Click += async (_, _) => await SetContentMaterialAsync("glass");
        QuickCloseAskButton!.Click += async (_, _) => await SetCloseBehaviorAsync("ask");
        QuickCloseMinimizeButton!.Click += async (_, _) => await SetCloseBehaviorAsync("minimize_to_tray");
        QuickCloseExitButton!.Click += async (_, _) => await SetCloseBehaviorAsync("exit_directly");
        QuickFontSmallButton.Click += async (_, _) => await SetFontScaleAsync(0.9);
        QuickFontNormalButton.Click += async (_, _) => await SetFontScaleAsync(1.0);
        QuickFontLargeButton.Click += async (_, _) => await SetFontScaleAsync(1.18);
        QuickAnimationSwitch.Toggled += async (_, _) =>
        {
            if (_startupServicesInitialized && !_syncingQuickSettings)
            {
                await _settingsService.UpdateAsync(settings => settings.AnimationsEnabled = QuickAnimationSwitch.IsOn);
                RefreshQuickSettingsControls();
            }
        };
        QuickProxySwitch!.Toggled += async (_, _) =>
        {
            if (_startupServicesInitialized && !_syncingQuickSettings)
            {
                await _settingsService.UpdateAsync(settings => settings.ProxyEnabled = QuickProxySwitch.IsOn);
                RefreshQuickSettingsControls();
            }
        };
        QuickUpdateSwitch!.Toggled += async (_, _) =>
        {
            if (_startupServicesInitialized && !_syncingQuickSettings)
            {
                await _settingsService.UpdateAsync(settings => settings.UpdateNotification = QuickUpdateSwitch.IsOn);
                RefreshQuickSettingsControls();
            }
        };
        QuickHardwareAccelerationSwitch!.Toggled += async (_, _) =>
        {
            if (_startupServicesInitialized && !_syncingQuickSettings)
            {
                await _settingsService.UpdateAsync(settings => settings.HardwareAccelerationEnabled = QuickHardwareAccelerationSwitch.IsOn);
                RefreshQuickSettingsControls();
                ToastService.Show(
                    QuickHardwareAccelerationSwitch.IsOn
                        ? AppLocalizer.T("硬件加速已开启，重启后完全生效。", "Hardware acceleration is on. Restart to fully apply it.")
                        : AppLocalizer.T("硬件加速已关闭，重启后完全生效。", "Hardware acceleration is off. Restart to fully apply it."),
                    ToastKind.Info);
            }
        };
        QuickPluginSwitch!.Toggled += async (_, _) =>
        {
            if (_startupServicesInitialized && !_syncingQuickSettings)
            {
                await SetPluginsEnabledAsync(QuickPluginSwitch.IsOn);
                RefreshQuickSettingsControls();
                ToastService.Show(QuickPluginSwitch.IsOn ? "插件系统已开启" : "插件系统已关闭", ToastKind.Success);
            }
        };

        GlobalSearchBox.TextChanged += (_, _) =>
        {
            if (_currentPage == ShellPage.Toolbox && _toolboxPage is not null)
            {
                _toolboxPage.ApplySearch(GlobalSearchBox.Text);
            }
        };
        GlobalSearchBox.QuerySubmitted += (_, _) =>
        {
            ShowToolboxPage(GlobalSearchBox.Text, resetCategory: true);
        };
        RootLayout.KeyDown += RootLayout_KeyDown;
    }

    private void GlobalSearchBox_GettingFocus(UIElement sender, GettingFocusEventArgs args)
    {
        if (_searchFocusAllowedByPointer)
        {
            return;
        }

        args.TryCancel();
    }

    private void RootNavigation_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
    {
        if (args.InvokedItemContainer is not NavigationViewItem item || item.Tag is not string tag)
        {
            return;
        }

        NavigateByTag(tag);
    }

    private void NavigateByTag(string tag)
    {
        switch (tag)
        {
            case "home":
                ShowHomePage();
                break;
            case "toolbox":
                ShowToolboxPage();
                break;
            case "downloads":
                ShowDownloadManagerPage();
                break;
            case "plugins":
                ShowPluginsPage();
                break;
            case "logs":
                ShowLogsPage();
                break;
            case "feedback":
                ShowFeedbackPage();
                break;
            case "settings":
                ShowSettingsPage();
                break;
            case "about":
                ShowAboutPage();
                break;
        }
    }

    private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        StartupTrace.Write("MainWindow.Loaded:start");
        if (!_startupServicesInitialized)
        {
            _startupServicesInitialized = true;
            try
            {
                if (_startupInitialization.CurrentSnapshot is null)
                {
                    await _settingsService.LoadAsync();
                    await _downloadManager.InitializeAsync();
                }
                VersionText.Text = $"v{_versionService.GetCurrent().Version}";
                RefreshQuickSettingsControls();
                ApplyLanguage();
                ThemeService.ApplyTheme(this, _settingsService.Current.Theme, _settingsService.Current.WindowBackdrop);
                ApplyShellTheme();
                ThemeService.ApplyFontScale(_settingsService.Current.FontSize);
                _ = WeatherCapsule?.LoadAsync();
                ShowInitialHomePage();
                _ = PrewarmWebViewsAsync();
                await ReloadCatalogAsync(refreshToolbox: false);
                var pageReport = _toolPageFactory.Validate(_catalog);
                if (!pageReport.IsComplete)
                {
                    var detail = $"catalog={pageReport.CatalogCount}; native={pageReport.NativeCatalogCount}; dynamic={pageReport.IgnoredDynamicCount}; resolvable={pageReport.ResolvableCount}; registered={pageReport.RegisteredCount}; missing={string.Join(", ", pageReport.MissingIds)}";
                    await _logService.WriteAsync("Error", "tool", "工具页面注册不完整", detail);
                }
                _windowStateService.Attach(this);
                _trayService.Initialize(this);
                ApplyResponsiveShell();
                RefreshPluginNavigation();
                RefreshNavigationRail();
                _ = ShowUpdateNotificationIfNeededAsync();
                _ = RunMonthlyIntegrityCheckAsync();
                StartupTrace.Write($"ToolCatalog.Count:{_catalog.Modules.Count}");
                StartupTrace.Write("MainWindow.Loaded:services-ready");
            }
            catch (Exception exception)
            {
                CrashLog.Write(exception);
                StartupTrace.Write("MainWindow.Loaded:services-failed");
            }
        }

        ShowInitialHomePage();
    }

    private async Task PrewarmWebViewsAsync()
    {
        try
        {
            await _webViewEnvironmentFactory.PrewarmAsync("HomeGlobe", "ToolPages", "ToolResults");
        }
        catch (Exception exception)
        {
            CrashLog.Write(exception);
            await _logService.WriteAsync("Warning", "webview", "WebView2 环境预热失败", AppLocalizer.SanitizeSensitiveText(exception.Message, 220));
        }
    }

    private async Task RunMonthlyIntegrityCheckAsync()
    {
        try
        {
            var report = await _integrityCheckService.RunMonthlyIntegrityCheckAsync();
            await _logService.WriteAsync(
                report.HasVisibleIssues ? "Warning" : "Information",
                "startup-check",
                report.HasVisibleIssues ? "月度安装完整性检查完成：有问题" : "月度安装完整性检查完成：无问题",
                $"kind={report.Kind}; issues={report.IssueCount}; visible={report.VisibleIssueCount}; critical={report.CriticalIssueCount}; warnings={report.WarningIssueCount}");
        }
        catch (Exception exception)
        {
            CrashLog.Write(exception);
            await _logService.WriteAsync("Warning", "startup-check", "月度安装完整性检查失败", AppLocalizer.SanitizeSensitiveText(exception.Message, 220));
        }
    }

    private void ShowInitialHomePage()
    {
        if (_initialPageShown)
        {
            return;
        }

        _initialPageShown = true;
        ShowHomePage();
        DispatcherQueue.TryEnqueue(RefreshNavigationRail);
    }

    private async Task ShowUpdateNotificationIfNeededAsync()
    {
        if (!_settingsService.Current.UpdateNotification)
        {
            return;
        }

        try
        {
            await Task.Delay(TimeSpan.FromSeconds(2));
            var info = await _updateService.GetUpdateInfoAsync();
            if (info is null || !info.IsNewerThan(_versionService.GetCurrent().Version))
            {
                return;
            }

            ToastService.Show(
                AppLocalizer.T($"发现新版本 {info.DisplayVersion}，可在关于页检查更新", $"New version {info.DisplayVersion} is available. Check updates from About."),
                ToastKind.Info,
                TimeSpan.FromSeconds(5));
            await _logService.WriteAsync("Information", "update", "发现新版本", info.DisplayVersion);
        }
        catch (Exception exception)
        {
            await _logService.WriteAsync("Warning", "update", "更新通知检查失败", AppLocalizer.SanitizeSensitiveText(exception.Message, 180));
        }
    }

    private void SelectNav(ShellPage page)
    {
        if (_navItems.TryGetValue(page, out var item) && !ReferenceEquals(RootNavigation.SelectedItem, item))
        {
            RootNavigation.SelectedItem = item;
        }
    }

    private void ShowHomePage()
    {
        ClearActivePluginHost();
        SafeNavigate(
            () => new HomePage(_catalog, query => ShowToolboxPage(query, resetCategory: !string.IsNullOrWhiteSpace(query)), ShowToolDetailPage, ShowServiceStatusPage, ShowLogsPage),
            ShellPage.Home,
            "navigation",
            "Open home page");
        _ = _logService.WriteAsync("Information", "navigation", "打开首页");
    }

    private void ShowToolboxPage(string? query = null, bool resetCategory = false)
    {
        ClearActivePluginHost();
        if (query is not null)
        {
            _toolboxState = resetCategory
                ? new ToolboxNavigationState(ToolCategory.All, query)
                : _toolboxState with { SearchQuery = query };
        }

        SafeNavigate(
            () =>
            {
                _toolboxPage = new ToolboxPage(
                    _catalog,
                    ShowToolDetailPage,
                    _toolboxState.SearchQuery,
                    _toolboxState,
                    state => _toolboxState = state);
                return _toolboxPage;
            },
            ShellPage.Toolbox,
            "navigation",
            "Open toolbox");
        _ = _logService.WriteAsync("Information", "navigation", "打开工具箱");
    }

    private void ShowToolDetailPage(IToolModule module)
    {
        if (_toolboxPage is not null)
        {
            _toolboxState = _toolboxPage.CaptureState(module.Id);
        }

        if (module is PluginToolModule pluginModule)
        {
            ShowPluginHostPage(pluginModule.Plugin, pluginModule.Surface);
            return;
        }

        if (module is ExternalToolModule externalToolModule)
        {
            ClearActivePluginHost();
            SafeNavigate(
                () => new ExternalToolDetailPage(externalToolModule, () => ShowToolboxPage()),
                ShellPage.Toolbox,
                "tool",
                $"Open external tool: {externalToolModule.Tool.Name}",
                externalToolModule.Tool.RelativePath);
            _ = _logService.WriteAsync("Information", "tool", $"打开外部工具：{externalToolModule.Tool.Name}", externalToolModule.Id);
            return;
        }

        if (module is BuiltinReferenceToolModule builtinToolModule)
        {
            ClearActivePluginHost();
            SafeNavigate(
                () => new BuiltinReferenceToolPage(builtinToolModule, () => ShowToolboxPage()),
                ShellPage.Toolbox,
                "tool",
                $"Open built-in reference tool: {builtinToolModule.Definition.Name}",
                builtinToolModule.Id);
            _ = _logService.WriteAsync("Information", "tool", $"打开内置工具：{builtinToolModule.Definition.Name}", builtinToolModule.Id);
            return;
        }

        ClearActivePluginHost();

        SafeNavigate(
            () => _toolPageFactory.Create(module, () => ShowToolboxPage()),
            ShellPage.Toolbox,
            "tool",
            $"Open tool: {ToolText.Name(module)}",
            module.Id);
        _ = _logService.WriteAsync("Information", "tool", $"打开工具：{ToolText.Name(module)}", module.Id);
    }

    public void ShowDownloadManagerPage()
    {
        ClearActivePluginHost();
        SafeNavigate(() => new DownloadManagerPage(), ShellPage.Downloads, "navigation", "Open download manager");
        _ = _logService.WriteAsync("Information", "navigation", "Open download manager");
    }

    private void ShowPluginsPage()
    {
        ClearActivePluginHost();
        if (!_settingsService.Current.PluginsEnabled)
        {
            ShowSettingsPage();
            ToastService.Show(AppLocalizer.T("插件系统已关闭，可在设置中开启。", "Plugins are disabled. Enable them in Settings."), ToastKind.Info);
            return;
        }

        SafeNavigate(
            () => new PluginPage(
                _pluginHost,
                _logService,
                ShowPluginDocsPage,
                ShowPluginHostPage,
                ApplyPluginSnapshotAsync),
            ShellPage.Plugins,
            "navigation",
            "Open plugins");
        _ = _logService.WriteAsync("Information", "navigation", "打开插件页");
    }

    private void ShowPluginDocsPage()
    {
        ClearActivePluginHost();
        SafeNavigate(() => new PluginDocsPage(ShowPluginsPage), ShellPage.Plugins, "navigation", "Open plugin docs");
    }

    private void ShowPluginHostPage(LoadedPlugin plugin, PluginSurface surface)
    {
        ClearActivePluginHost();
        PluginHostWindowManager.Open(plugin, surface);
        _ = _logService.WriteAsync("Information", "plugin", $"Open plugin surface: {plugin.Manifest.Id}/{surface.Id}");
    }

    public async Task SetPluginsEnabledAsync(bool enabled)
    {
        await _settingsService.UpdateAsync(settings => settings.PluginsEnabled = enabled);
        if (!enabled)
        {
            _pluginHost.Stop();
        }

        await ReloadCatalogAsync(restartPluginHost: enabled);
    }

    public async Task SetPluginRootPathAsync(string pluginRootPath)
    {
        await _settingsService.UpdateAsync(settings => settings.PluginRootPath = pluginRootPath);
        _pluginHost.Stop();
        await ReloadCatalogAsync(restartPluginHost: true);
    }

    public async Task ReloadCatalogAsync(bool refreshToolbox = true, bool restartPluginHost = true)
    {
        if (_pluginReloadInProgress)
        {
            return;
        }

        _pluginReloadInProgress = true;
        try
        {
            PluginSnapshot? snapshot = null;
            if (_settingsService.Current.PluginsEnabled)
            {
                try
                {
                    snapshot = restartPluginHost || _pluginHost.CurrentSnapshot is null
                        ? await _pluginHost.ReloadAsync()
                        : await _pluginHost.GetSnapshotAsync();
                }
                catch (Exception exception)
                {
                    CrashLog.Write(exception);
                    await _logService.WriteAsync("Error", "plugin", "Load plugin snapshot failed", AppLocalizer.SanitizeSensitiveText(exception.Message, 220));
                    ToastService.Show(AppLocalizer.T("插件系统加载失败，可在插件页重试。", "Plugin system failed to load. Retry from the plugin page."), ToastKind.Warning);
                }
            }

            var enabledTools = snapshot?.EnabledTools ?? _pluginHost.CurrentSnapshot?.EnabledTools;
            _catalog = await BuildCatalogAsync(enabledTools, cancellationToken: default);
            RefreshPluginNavigation();
            RefreshNavigationRail();
            if (refreshToolbox && _currentPage == ShellPage.Toolbox)
            {
                ShowToolboxPage();
            }
            if (!_settingsService.Current.PluginsEnabled && _currentPage == ShellPage.Plugins)
            {
                _pluginHost.Stop();
                ShowSettingsPage();
            }
            else if (_settingsService.Current.PluginsEnabled && _currentPage == ShellPage.Plugins)
            {
                if (restartPluginHost && _activePluginId is not null && _activePluginSurfaceId is not null)
                {
                    await RestartActivePluginHostAsync();
                }
                else if (ContentHost.Content is PluginPage)
                {
                    ShowPluginsPage();
                }
            }
        }
        catch (Exception exception)
        {
            CrashLog.Write(exception);
            await _logService.WriteAsync("Error", "plugin", "Reload plugin catalog failed", AppLocalizer.SanitizeSensitiveText(exception.Message, 220));
        }
        finally
        {
            _pluginReloadInProgress = false;
        }
    }

    private async Task RestartActivePluginHostAsync()
    {
        if (_activePluginId is null || _activePluginSurfaceId is null)
        {
            return;
        }

        var pluginId = _activePluginId;
        var surfaceId = _activePluginSurfaceId;
        var snapshot = _pluginHost.CurrentSnapshot ?? await _pluginHost.GetSnapshotAsync();
        var plugin = snapshot.Plugins.FirstOrDefault(candidate =>
                candidate.IsValid &&
                candidate.State.Enabled &&
                string.Equals(candidate.Manifest.Id, pluginId, StringComparison.OrdinalIgnoreCase))
            ?.ToLoadedPlugin();
        var surface = plugin?.Manifest.Surfaces.FirstOrDefault(candidate =>
            string.Equals(candidate.Id, surfaceId, StringComparison.OrdinalIgnoreCase));

        if (plugin is not null && surface is not null)
        {
            ShowPluginHostPage(plugin, surface);
        }
        else
        {
            ClearActivePluginHost();
            ShowPluginsPage();
        }
    }

    private void ClearActivePluginHost()
    {
        _activePluginId = null;
        _activePluginSurfaceId = null;
    }

    private void PluginHost_SnapshotChanged(object? sender, PluginSnapshot snapshot)
    {
        DispatcherQueue.TryEnqueue(async () =>
        {
            await ApplyPluginSnapshotAsync(snapshot);
        });
    }

    private void PluginHost_StatusChanged(object? sender, PluginHostStatus status)
    {
        if (status == PluginHostStatus.Failed)
        {
            DispatcherQueue.TryEnqueue(() =>
            {
                ToastService.Show(AppLocalizer.T("插件宿主进程异常，可在插件页重试。", "Plugin host failed. Retry from the plugin page."), ToastKind.Warning);
            });
        }
    }

    private async Task ApplyPluginSnapshotAsync(PluginSnapshot snapshot)
    {
        if (!_settingsService.Current.PluginsEnabled)
        {
            return;
        }

        _catalog = await BuildCatalogAsync(snapshot.EnabledTools, cancellationToken: default);
        RefreshPluginNavigation();
        RefreshNavigationRail();
        if (_currentPage == ShellPage.Toolbox)
        {
            ShowToolboxPage();
        }
    }

    private void ShowLogsPage()
    {
        ClearActivePluginHost();
        SafeNavigate(() => new LogPage(), ShellPage.Logs, "navigation", "Open logs");
        _ = _logService.WriteAsync("Information", "navigation", "打开日志");
    }

    private async Task<ToolCatalog> BuildCatalogAsync(
        IEnumerable<PluginToolDto>? enabledTools = null,
        CancellationToken cancellationToken = default)
    {
        var pluginTools = _settingsService.Current.PluginsEnabled && enabledTools is not null
            ? enabledTools.Select(tool => tool.ToToolModule()).Cast<IToolModule>()
            : Enumerable.Empty<IToolModule>();
        var externalTools = await _externalToolCatalog.GetModulesAsync(cancellationToken);
        var builtinTools = _builtinToolCatalog.GetModules();

        var modules = ToolCatalog.DefaultModules()
            .Concat(builtinTools)
            .Concat(externalTools)
            .Concat(pluginTools)
            .GroupBy(module => module.Id, StringComparer.OrdinalIgnoreCase)
            .Select(group => group.First())
            .ToArray();

        await _logService.WriteAsync(
            "Information",
            "tool-catalog",
            "Tool catalog rebuilt",
            $"native={ToolCatalog.DefaultModules().Count()}; builtin={builtinTools.Count}; external={externalTools.Count}; plugin={pluginTools.Count()}",
            cancellationToken);

        return new ToolCatalog(modules);
    }

    private void ShowFeedbackPage()
    {
        ClearActivePluginHost();
        SafeNavigate(() => new FeedbackPage(), ShellPage.Feedback, "navigation", "Open feedback");
        _ = _logService.WriteAsync("Information", "navigation", "打开反馈页");
    }

    private void ShowServiceStatusPage()
    {
        ClearActivePluginHost();
        SafeNavigate(() => new ServiceStatusPage(ShowStartupCheckResultPage), ShellPage.ServiceStatus, "navigation", "Open service status");
        _ = _logService.WriteAsync("Information", "navigation", "打开服务状态");
    }

    private void ShowStartupCheckResultPage(StartupCheckResultPayload payload)
    {
        ClearActivePluginHost();
        SafeNavigate(() => new StartupCheckResultPage(payload, ShowServiceStatusPage), ShellPage.ServiceStatus, "navigation", "Open startup check results");
        _ = _logService.WriteAsync("Information", "navigation", "打开启动自检结果");
    }

    private void ShowSettingsPage()
    {
        ClearActivePluginHost();
        SafeNavigate(() => new SettingsPage(), ShellPage.Settings, "navigation", "Open settings");
        _ = _logService.WriteAsync("Information", "navigation", "打开设置");
    }

    private void ShowAboutPage()
    {
        ClearActivePluginHost();
        SafeNavigate(() => new AboutPage(OpenToolFromAbout), ShellPage.About, "navigation", "Open about");
        _ = _logService.WriteAsync("Information", "navigation", "打开关于");
    }

    private void OpenToolFromAbout(string toolId)
    {
        var module = _catalog.GetById(toolId);
        if (module is not null)
        {
            ShowToolDetailPage(module);
            return;
        }

        ShowToolboxPage("开发环境配置", resetCategory: true);
        ToastService.Show(AppLocalizer.T("未找到该工具，已打开工具箱搜索。", "The tool was not found, so Toolbox search was opened."), ToastKind.Warning);
    }

    private void DownloadManager_ItemsChanged(object? sender, EventArgs e)
    {
        DispatcherQueue.TryEnqueue(RefreshDownloadNavItem);
        var installCandidates = _downloadManager.Items
            .Where(item =>
                item.State == DownloadState.Completed &&
                !string.IsNullOrWhiteSpace(item.InstallCommand) &&
                !_installPromptsShown.Contains(item.Id))
            .ToArray();

        foreach (var item in installCandidates)
        {
            _installPromptsShown.Add(item.Id);
            DispatcherQueue.TryEnqueue(async () => await PromptInstallAsync(item));
        }
    }

    private async Task PromptInstallAsync(DownloadItem item)
    {
        if (ContentHost.XamlRoot is null)
        {
            return;
        }

        var content = new StackPanel
        {
            Spacing = 8,
            Children =
            {
                ModernUi.Text(item.Source.DisplayName, 15, FontWeights.SemiBold, maxLines: 2),
                ModernUi.Text(item.TargetPath, 12, foreground: ModernUi.TextSecondary, maxLines: 3),
                ModernUi.Text(AppLocalizer.T("下载已完成。确认后才会打开安装程序或下载文件。", "The download is complete. The installer or file opens only after you confirm."), 13, foreground: ModernUi.TextSecondary, maxLines: 3)
            }
        };

        var dialog = new ContentDialog
        {
            XamlRoot = ContentHost.XamlRoot,
            Title = AppLocalizer.T("安装下载项？", "Install downloaded item?"),
            Content = content,
            PrimaryButtonText = AppLocalizer.T("安装 / 打开", "Install / open"),
            SecondaryButtonText = AppLocalizer.T("稍后", "Later"),
            CloseButtonText = AppLocalizer.T("取消", "Cancel"),
            DefaultButton = ContentDialogButton.Primary
        };

        try
        {
            var result = await dialog.ShowAsync();
            if (result == ContentDialogResult.Primary)
            {
                var process = DownloadManagerService.LaunchInstaller(item);
                await _downloadManager.MarkInstallLaunchedAsync(item.Id);
                if (process is not null && item.DeleteAfterInstall)
                {
                    try
                    {
                        await process.WaitForExitAsync();
                        await _downloadManager.TryCleanupAfterInstallAsync(item.Id);
                    }
                    catch
                    {
                        // Elevated installers can detach; keep the package unless cleanup is reliable.
                    }
                }

                await _logService.WriteAsync("Information", "download", "User launched downloaded installer", item.TargetPath);
            }
        }
        catch (Exception exception)
        {
            CrashLog.Write(exception);
            ToastService.Show(AppLocalizer.T("无法打开安装确认框。", "Could not open the install confirmation."), ToastKind.Warning);
        }
    }

    private void RefreshDownloadNavItem()
    {
        if (DownloadNavItem is null)
        {
            return;
        }

        var english = string.Equals(_settingsService.Current.Language, "en-US", StringComparison.OrdinalIgnoreCase);
        var running = _downloadManager.Items.Count(item => item.State == DownloadState.Running);
        var queued = _downloadManager.Items.Count(item => item.State == DownloadState.Queued);
        var active = running + queued;
        DownloadNavItem.Content = active > 0
            ? (english ? $"Downloads ({active})" : $"下载管理 ({active})")
            : (english ? "Downloads" : "下载管理");
        ToolTipService.SetToolTip(DownloadNavItem, active > 0
            ? (english ? $"{running} running, {queued} queued" : $"{running} 个运行，{queued} 个排队")
            : (english ? "Download Manager" : "下载管理"));
    }

    private void SafeNavigate(
        Func<UIElement> pageFactory,
        ShellPage shellPage,
        string logCategory,
        string logMessage,
        string? detail = null)
    {
        try
        {
            var page = pageFactory();
            ShowPage(page, shellPage);
            _ = _logService.WriteAsync("Information", logCategory, logMessage, detail);
        }
        catch (Exception exception)
        {
            CrashLog.Write(exception);
            StartupTrace.Write($"SafeNavigate failed:{shellPage}:{exception.GetType().Name}");
            var safeMessage = AppLocalizer.SanitizeSensitiveText(exception.Message, 220);
            _ = _logService.WriteAsync("Error", "navigation", $"Navigation failed: {shellPage}", safeMessage);
            ShowPage(BuildNavigationErrorPage(safeMessage), shellPage);
            ToastService.Show(AppLocalizer.T("页面打开失败，程序已保持运行。", $"Could not open {shellPage}. The app stayed running."), ToastKind.Error);
        }
    }

    private static UIElement BuildNavigationErrorPage(string detailsText)
    {
        var details = new TextBlock
        {
            Text = detailsText,
            TextWrapping = TextWrapping.Wrap,
            IsTextSelectionEnabled = true,
            FontFamily = new Microsoft.UI.Xaml.Media.FontFamily("Cascadia Mono"),
            Foreground = ModernUi.TextSecondary
        };

        var panel = new StackPanel
        {
            MaxWidth = 760,
            Spacing = 12,
            Children =
            {
                ModernUi.Text(AppLocalizer.T("无法打开页面", "Could not open page"), 28, FontWeights.SemiBold, ModernUi.Danger),
                ModernUi.Text(AppLocalizer.T("页面初始化失败，YMhut Box 已保持主壳运行并写入崩溃日志。", "The page failed to initialize, so YMhut Box kept the shell alive and logged the crash details."), 15, foreground: ModernUi.TextSecondary),
                ModernUi.Card(details, new Thickness(14), radius: 8)
            }
        };

        return new Grid
        {
            Padding = new Thickness(32),
            Background = ModernUi.AppBackground,
            Children = { panel }
        };
    }

    private void ShowPage(UIElement page, ShellPage shellPage)
    {
        ContentHost.Content = page;
        _currentPage = shellPage;
        SelectNav(shellPage);
        ClearGlobalSearchFocusIfNeeded();
        StartupTrace.Write($"ContentHost.ShowPage:{page.GetType().Name}");
    }

    private void ClearGlobalSearchFocusIfNeeded()
    {
        if (!DispatcherQueue.TryEnqueue(MoveFocusToContent))
        {
            MoveFocusToContent();
        }
    }

    private void MoveFocusToContent()
    {
        if (ContentHost.Content is Control control)
        {
            control.IsTabStop = true;
            if (control.Focus(FocusState.Programmatic))
            {
                return;
            }
        }

        ContentHost.IsTabStop = true;
        if (ContentHost.Focus(FocusState.Programmatic))
        {
            return;
        }

        RootLayout.IsTabStop = true;
        RootLayout.Focus(FocusState.Programmatic);
    }

    private void RootLayout_KeyDown(object sender, KeyRoutedEventArgs e)
    {
        if (e.Key == VirtualKey.Escape && QuickSettingsOverlay.Visibility == Visibility.Visible)
        {
            HideQuickSettings();
            e.Handled = true;
            return;
        }

        var state = Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Control);
        if (e.Key == VirtualKey.K && state.HasFlag(Windows.UI.Core.CoreVirtualKeyStates.Down))
        {
            ShowToolboxPage(GlobalSearchBox.Text, resetCategory: true);
            e.Handled = true;
        }
    }

    private async Task ToggleThemeAsync()
    {
        var next = string.Equals(_settingsService.Current.Theme, "Dark", StringComparison.OrdinalIgnoreCase)
            ? "Light"
            : "Dark";
        await SetThemeAsync(next);
    }

    private async Task SetThemeAsync(string theme)
    {
        await _settingsService.UpdateAsync(settings => settings.Theme = theme);
        ThemeService.ApplyTheme(this, theme, _settingsService.Current.WindowBackdrop);
        ApplyShellTheme();
        RefreshQuickSettingsControls();
        HideQuickSettings();
    }

    private async Task SetFontScaleAsync(double scale)
    {
        await _settingsService.UpdateAsync(settings => settings.FontSize = scale);
        ThemeService.ApplyFontScale(scale);
        RefreshQuickSettingsControls();
    }

    private async Task SetLanguageAsync(string language)
    {
        await _settingsService.UpdateAsync(settings => settings.Language = language);
        ApplyLanguage();
        RefreshQuickSettingsControls();
    }

    private async Task SetHomePageModeAsync(string mode)
    {
        await _settingsService.UpdateAsync(settings => settings.HomePageMode = mode);
        RefreshQuickSettingsControls();
        if (_currentPage == ShellPage.Home)
        {
            ShowHomePage();
        }
    }

    private async Task SetWindowBackdropAsync(string backdrop)
    {
        await _settingsService.UpdateAsync(settings => settings.WindowBackdrop = backdrop);
        ThemeService.ApplyTheme(this, _settingsService.Current.Theme, backdrop);
        ApplyShellTheme();
        RefreshQuickSettingsControls();
    }

    private async Task SetTopBarMaterialAsync(string material)
    {
        await _settingsService.UpdateAsync(settings => settings.TopBarMaterial = material);
        ApplyShellTheme();
        RefreshQuickSettingsControls();
    }

    private async Task SetContentMaterialAsync(string material)
    {
        await _settingsService.UpdateAsync(settings => settings.SettingsPanelMaterial = material);
        ApplyShellTheme();
        RefreshQuickSettingsControls();
    }

    private async Task SetCloseBehaviorAsync(string behavior)
    {
        await _settingsService.UpdateAsync(settings => settings.CloseBehavior = behavior);
        RefreshQuickSettingsControls();
    }

    private void ShowQuickSettings()
    {
        RefreshQuickSettingsControls();
        AnimateQuickSettings(show: true);
    }

    private void HideQuickSettings()
    {
        AnimateQuickSettings(show: false);
    }

    private void RefreshQuickSettingsControls()
    {
        if (QuickAnimationSwitch is null)
        {
            return;
        }

        var settings = _settingsService.Current;
        _syncingQuickSettings = true;
        try
        {
            QuickAnimationSwitch.IsOn = settings.AnimationsEnabled;
            if (QuickProxySwitch is not null)
            {
                QuickProxySwitch.IsOn = settings.ProxyEnabled;
            }
            if (QuickUpdateSwitch is not null)
            {
                QuickUpdateSwitch.IsOn = settings.UpdateNotification;
            }
            if (QuickHardwareAccelerationSwitch is not null)
            {
                QuickHardwareAccelerationSwitch.IsOn = settings.HardwareAccelerationEnabled;
            }
            if (QuickPluginSwitch is not null)
            {
                QuickPluginSwitch.IsOn = settings.PluginsEnabled;
            }

            SelectQuickButton(QuickLightButton, string.Equals(settings.Theme, "Light", StringComparison.OrdinalIgnoreCase));
            SelectQuickButton(QuickDarkButton, string.Equals(settings.Theme, "Dark", StringComparison.OrdinalIgnoreCase));
            SelectQuickButton(QuickLanguageZhButton, !string.Equals(settings.Language, "en-US", StringComparison.OrdinalIgnoreCase));
            SelectQuickButton(QuickLanguageEnButton, string.Equals(settings.Language, "en-US", StringComparison.OrdinalIgnoreCase));
            SelectQuickButton(QuickHomeSolarButton, !string.Equals(settings.HomePageMode, "dashboard", StringComparison.OrdinalIgnoreCase));
            SelectQuickButton(QuickHomeDashboardButton, string.Equals(settings.HomePageMode, "dashboard", StringComparison.OrdinalIgnoreCase));

            var backdrop = (settings.WindowBackdrop ?? string.Empty).Trim().ToLowerInvariant();
            SelectQuickButton(QuickBackdropMicaButton, backdrop is "" or "mica" or "micaalt" or "mica_alt" or "mica-alt");
            SelectQuickButton(QuickBackdropAcrylicButton, backdrop is "acrylic" or "desktopacrylic" or "desktop_acrylic");
            SelectQuickButton(QuickBackdropSolidButton, backdrop is "solid" or "none");

            var top = (settings.TopBarMaterial ?? string.Empty).Trim().ToLowerInvariant();
            SelectQuickButton(QuickTopInheritButton, top is "" or "inherit");
            SelectQuickButton(QuickTopAcrylicButton, top is "acrylic");
            SelectQuickButton(QuickTopSolidButton, top is "solid" or "none");

            var content = (settings.SettingsPanelMaterial ?? string.Empty).Trim().ToLowerInvariant();
            SelectQuickButton(QuickContentSolidButton, content is "" or "solid" or "none");
            SelectQuickButton(QuickContentAcrylicButton, content is "acrylic");
            SelectQuickButton(QuickContentGlassButton, content is "glass" or "frosted" or "frosted_glass");

            var close = (settings.CloseBehavior ?? string.Empty).Trim().ToLowerInvariant();
            SelectQuickButton(QuickCloseAskButton, close is "" or "ask");
            SelectQuickButton(QuickCloseMinimizeButton, close is "minimize_to_tray" or "minimize_then_exit");
            SelectQuickButton(QuickCloseExitButton, close is "exit_directly");

            SelectQuickButton(QuickFontSmallButton, settings.FontSize < 0.95);
            SelectQuickButton(QuickFontNormalButton, settings.FontSize is >= 0.95 and <= 1.08);
            SelectQuickButton(QuickFontLargeButton, settings.FontSize > 1.08);
        }
        finally
        {
            _syncingQuickSettings = false;
        }
    }

    private static void SelectQuickButton(Button? button, bool selected)
    {
        if (button is null)
        {
            return;
        }

        button.Background = selected ? ModernUi.AccentSoft : ModernUi.Surface;
        button.BorderBrush = selected ? ModernUi.Accent : ModernUi.Stroke;
        button.Foreground = selected ? ModernUi.Accent : ModernUi.TextPrimary;
    }

    public void ApplyVisualSettings()
    {
        ThemeService.ApplyTheme(this, _settingsService.Current.Theme, _settingsService.Current.WindowBackdrop);
        ThemeService.ApplyFontScale(_settingsService.Current.FontSize);
        ApplyShellTheme();
    }

    private void AnimateQuickSettings(bool show)
    {
        var animationsEnabled = _settingsService.Current.AnimationsEnabled;
        if (show)
        {
            QuickSettingsOverlay.Visibility = Visibility.Visible;
        }

        if (!animationsEnabled)
        {
            QuickSettingsOverlay.Opacity = show ? 1 : 0;
            QuickSettingsTransform.X = show ? 0 : 420;
            QuickSettingsOverlay.Visibility = show ? Visibility.Visible : Visibility.Collapsed;
            return;
        }

        var storyboard = new Storyboard();
        var opacity = new DoubleAnimation
        {
            To = show ? 1 : 0,
            Duration = TimeSpan.FromMilliseconds(180),
            EnableDependentAnimation = true
        };
        Storyboard.SetTarget(opacity, QuickSettingsOverlay);
        Storyboard.SetTargetProperty(opacity, "Opacity");
        storyboard.Children.Add(opacity);

        var slide = new DoubleAnimation
        {
            To = show ? 0 : 420,
            Duration = TimeSpan.FromMilliseconds(220),
            EnableDependentAnimation = true,
            EasingFunction = new CubicEase { EasingMode = show ? EasingMode.EaseOut : EasingMode.EaseIn }
        };
        Storyboard.SetTarget(slide, QuickSettingsTransform);
        Storyboard.SetTargetProperty(slide, "X");
        storyboard.Children.Add(slide);

        if (!show)
        {
            storyboard.Completed += (_, _) => QuickSettingsOverlay.Visibility = Visibility.Collapsed;
        }

        storyboard.Begin();
    }

    private void ApplyShellTheme()
    {
        var isDark = string.Equals(_settingsService.Current.Theme, "Dark", StringComparison.OrdinalIgnoreCase);
        var settings = _settingsService.Current;
        var transparentBackdrop = !_windowMoveLoopActive && UsesTransparentBackdrop(settings.WindowBackdrop);
        var topBarMaterial = _windowMoveLoopActive ? "solid" : settings.TopBarMaterial;
        var contentMaterial = _windowMoveLoopActive ? "solid" : settings.SettingsPanelMaterial;
        AppTitleBar.Background = ThemeService.CreateTopBarBrush(topBarMaterial, isDark, settings.WindowBackdrop);
        RootNavigation.Background = ThemeService.CreateContentBrush(contentMaterial, isDark);
        QuickSettingsPanel.Background = ThemeService.CreateContentBrush(contentMaterial, isDark);
        if (transparentBackdrop)
        {
            RootLayout.Background = new SolidColorBrush(Color.FromArgb(isDark ? (byte)170 : (byte)190, isDark ? (byte)31 : (byte)245, isDark ? (byte)36 : (byte)246, isDark ? (byte)38 : (byte)247));
            return;
        }

        RootLayout.Background = ModernUi.AppBackground;
    }

    private static bool UsesTransparentBackdrop(string? backdrop)
    {
        return (backdrop ?? string.Empty).Trim().ToLowerInvariant() is not ("solid" or "none");
    }

    private void ApplyResponsiveShell()
    {
        var width = RootLayout.ActualWidth;
        if (width <= 0)
        {
            return;
        }

        var wide = width >= 1280;
        var desktop = width >= 760;
        var phone = width < 520;
        var bucketChanged = !_hasResponsiveShellState ||
            wide != _lastResponsiveWide ||
            desktop != _lastResponsiveDesktop ||
            phone != _lastResponsivePhone;
        var widthChangedEnough = !_hasResponsiveShellState ||
            Math.Abs(width - _lastResponsiveWidth) >= 24;

        if (!bucketChanged && !widthChangedEnough)
        {
            return;
        }

        RootNavigation.PaneDisplayMode = wide
            ? NavigationViewPaneDisplayMode.Left
            : phone
                ? NavigationViewPaneDisplayMode.LeftMinimal
                : NavigationViewPaneDisplayMode.LeftCompact;
        RootNavigation.IsPaneOpen = wide;
        RootNavigation.CompactPaneLength = 56;
        RootNavigation.OpenPaneLength = wide ? 248 : 220;

        GlobalSearchBox.Visibility = width < 640 ? Visibility.Collapsed : Visibility.Visible;
        GlobalSearchBox.MaxWidth = Math.Clamp(width - (wide ? 720 : 540), 220, 560);
        if (WeatherCapsule is not null)
        {
            WeatherCapsule.Visibility = desktop && width >= 960 ? Visibility.Visible : Visibility.Collapsed;
        }
        if (_titleActionsPanel is not null)
        {
            _titleActionsPanel.Margin = new Thickness(0, 0, desktop ? 146 : 136, 0);
        }

        _hasResponsiveShellState = true;
        _lastResponsiveWide = wide;
        _lastResponsiveDesktop = desktop;
        _lastResponsivePhone = phone;
        _lastResponsiveWidth = width;

        if (bucketChanged)
        {
            DispatcherQueue.TryEnqueue(RefreshNavigationRail);
        }

        ScheduleTitleBarDragRegionUpdate();
    }

    private void RefreshNavigationRail()
    {
        var page = _currentPage;
        RootNavigation.CompactPaneLength = 56;
        RootNavigation.OpenPaneLength = RootLayout.ActualWidth >= 1280 ? 248 : 220;
        SelectNav(page);
        RootNavigation.InvalidateMeasure();
        DispatcherQueue.TryEnqueue(() =>
        {
            SelectNav(page);
            RootNavigation.InvalidateArrange();
        });
    }

    private void RefreshPluginNavigation()
    {
        PluginsNavItem.Visibility = _settingsService.Current.PluginsEnabled
            ? Visibility.Visible
            : Visibility.Collapsed;
    }

    private bool IsWindowMaximized()
    {
        try
        {
            var hwnd = WindowNative.GetWindowHandle(this);
            var id = Win32Interop.GetWindowIdFromWindow(hwnd);
            var appWindow = AppWindow.GetFromWindowId(id);
            return appWindow.Presenter is OverlappedPresenter presenter &&
                presenter.State == OverlappedPresenterState.Maximized;
        }
        catch
        {
            return RootLayout.ActualWidth >= 1500;
        }
    }
}

internal enum ShellPage
{
    Home,
    Toolbox,
    Downloads,
    ServiceStatus,
    Plugins,
    Logs,
    Feedback,
    Settings,
    About
}

internal sealed record LocalizedText(string Zh, string En)
{
    public string Current => AppLocalizer.T(Zh, En);
}

internal static class StartupTrace
{
    internal static void Write(string message)
    {
        try
        {
            var path = Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                "YMhut Box",
                "WinUI",
                "Logs",
                "startup-trace.log");
            Directory.CreateDirectory(Path.GetDirectoryName(path)!);
            File.AppendAllText(path, $"{DateTime.Now:O} {message}{Environment.NewLine}");
        }
        catch
        {
        }
    }
}
