using System.Diagnostics;
using Microsoft.UI.Text;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Animation;
using Windows.UI;
using Windows.UI.ViewManagement;
using Windows.Storage.Pickers;
using Windows.System;
using WinRT.Interop;
using YMhut.Box.Core.App;
using YMhut.Box.Core.Feedback;
using YMhut.Box.Core.Logging;
using YMhut.Box.Core.Media;
using YMhut.Box.Core.Net;
using YMhut.Box.Core.Plugins;
using YMhut.Box.Core.Settings;
using YMhut.Box.Core.System;
using YMhut.Box.Core.Tools;
using YMhut.Box.WinUI.Controls;
using YMhut.Box.WinUI.Services;

namespace YMhut.Box.WinUI.Views;

public sealed class SettingsPage : Page
{
    private const double ControlCenterVisibleNavHeight = 214;
    private const double ControlCenterNavScrollStep = 164;

    private readonly ISettingsService _settingsService = AppServices.GetRequiredService<ISettingsService>();
    private readonly IStartupService _startupService = AppServices.GetRequiredService<IStartupService>();
    private readonly IHttpService _httpService = AppServices.GetRequiredService<IHttpService>();
    private readonly ILogService _logService = AppServices.GetRequiredService<ILogService>();
    private readonly IRiskConfirmationStore _riskStore = AppServices.GetRequiredService<IRiskConfirmationStore>();
    private readonly AppPaths _paths = AppServices.GetRequiredService<AppPaths>();
    private readonly IRemoteMediaCatalogService _remoteMediaCatalogService = AppServices.GetRequiredService<IRemoteMediaCatalogService>();
    private readonly ToolCatalog _catalog = AppServices.GetRequiredService<ToolCatalog>();
    private readonly ISystemMetricsService _metricsService = AppServices.GetRequiredService<ISystemMetricsService>();

    private readonly Grid _settingsLayoutGrid = new() { ColumnSpacing = 18, RowSpacing = 18 };
    private readonly StackPanel _settingsNavStack = new() { Spacing = 6 };
    private readonly Border _settingsNavPaddingHost = new() { Padding = new Thickness(0, 0, 12, 0) };
    private readonly AccessibilitySettings _accessibility = new();
    private readonly TranslateTransform _settingsNavCueTransform = new();
    private readonly FontIcon _settingsNavCueIcon = new();
    private readonly Button _settingsNavCueButton = new();
    private readonly ScrollViewer _settingsNavScroller = new()
    {
        HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled,
        VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
        HorizontalScrollMode = ScrollMode.Disabled,
        VerticalScrollMode = ScrollMode.Enabled,
        MaxHeight = ControlCenterVisibleNavHeight,
        Padding = new Thickness(0)
    };
    private readonly ContentControl _settingsPageHost = new() { HorizontalContentAlignment = HorizontalAlignment.Stretch };
    private readonly Dictionary<string, StackPanel> _settingsPages = [];
    private readonly Dictionary<string, Button> _settingsPageButtons = [];
    private readonly Grid _sectionsGrid = new() { ColumnSpacing = 16, RowSpacing = 16 };
    private readonly List<FrameworkElement> _sectionCards = [];
    private readonly List<Border> _materialCards = [];
    private readonly DispatcherTimer _metricsTimer = new() { Interval = TimeSpan.FromSeconds(2) };
    private Storyboard? _settingsNavCueStoryboard;
    private bool _settingsNavCuePointsUp;
    private readonly ToggleSwitch _animationSwitch = new();
    private readonly ToggleSwitch _restoreSwitch = new();
    private readonly ToggleSwitch _autoStartSwitch = new();
    private readonly ToggleSwitch _proxySwitch = new();
    private readonly ToggleSwitch _updateSwitch = new();
    private readonly ToggleSwitch _hardwareAccelerationSwitch = new();
    private readonly ToggleSwitch _pluginSwitch = new();
    private readonly ToggleSwitch _toolboxCompactSwitch = new();
    private readonly ToggleSwitch _toolboxRecentFirstSwitch = new();
    private readonly ToggleSwitch _hardwareLogoSwitch = new();
    private readonly ToggleSwitch _riskConfirmationSwitch = new();
    private readonly ToggleSwitch _feedbackLogsSwitch = new();
    private readonly ToggleSwitch _feedbackToolStatusSwitch = new();
    private readonly ToggleSwitch _feedbackSystemSwitch = new();

    private TextBlock _themeSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _windowBackdropSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _topBarMaterialSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _settingsMaterialSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _fontSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _languageSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _homeSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _closeSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _proxySummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _timeoutSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _retentionSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _toolDisplayModeSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _toolboxScopeSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _pluginRootSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _feedbackContactSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _feedbackDefaultsSummary = ModernUi.Text("", 14, FontWeights.SemiBold);
    private TextBlock _controlProcessorStatus = ModernUi.Text("", 13, FontWeights.SemiBold);
    private TextBlock _controlUptimeStatus = ModernUi.Text("", 13, FontWeights.SemiBold);
    private TextBlock _processorStatus = ModernUi.Text("", 13, FontWeights.SemiBold);
    private TextBlock _memoryStatus = ModernUi.Text("", 13, FontWeights.SemiBold);
    private TextBlock _uptimeStatus = ModernUi.Text("", 13, FontWeights.SemiBold);
    private TextBlock _systemDriveStatus = ModernUi.Text("", 13, FontWeights.SemiBold);
    private TextBlock _processCpuStatus = ModernUi.Text("", 13, FontWeights.SemiBold);
    private TextBlock _processRuntimeStatus = ModernUi.Text("", 13, FontWeights.SemiBold);
    private TextBlock _processThreadStatus = ModernUi.Text("", 13, FontWeights.SemiBold);
    private TextBlock _runtimeStatus = ModernUi.Text("", 13, FontWeights.SemiBold);
    private TextBlock _lastRefreshStatus = ModernUi.Text("", 13, FontWeights.SemiBold);
    private readonly MetricStripControl _cpuStrip = new(AppLocalizer.T("CPU 占用", "CPU usage"), "\uE950");
    private readonly MetricStripControl _memoryStrip = new(AppLocalizer.T("运行内存", "Memory usage"), "\uE8D4");
    private readonly MetricChartControl _systemCpuChart = new(
        AppLocalizer.T("CPU 实时占用", "CPU live usage"),
        AppLocalizer.T("等待下一次采样", "Waiting for the next sample"),
        "\uE950");
    private readonly MetricChartControl _systemMemoryChart = new(
        AppLocalizer.T("运行内存实时占用", "Memory live usage"),
        AppLocalizer.T("等待内存状态", "Waiting for memory status"),
        "\uE8D4");
    private readonly MetricChartControl _processMemoryChart = new(
        AppLocalizer.T("应用内存", "App memory"),
        AppLocalizer.T("工作集 / 托管内存", "Working set / managed memory"),
        "\uE8D4");
    private readonly MetricChartControl _systemDiskChart = new(
        AppLocalizer.T("系统盘占用", "System drive usage"),
        AppLocalizer.T("等待磁盘状态", "Waiting for drive status"),
        "\uE958");
    private Border? _systemRealtimeCard;

    private AppSettings _settings = new();
    private bool _loaded;
    private bool _syncingAutoStartSwitch;
    private string _activeSettingsPage = "appearance";

    public SettingsPage()
    {
        ConfigureSettingsNavScrollCue();
        Background = ModernUi.AppBackground;
        Content = BuildContent();
        Loaded += SettingsPage_Loaded;
        Unloaded += (_, _) =>
        {
            _metricsTimer.Stop();
            StopSettingsNavCueAnimation();
        };
        SizeChanged += (_, _) => ArrangeSections();
        _metricsTimer.Tick += (_, _) => RefreshControlCenterStatus();
        _settingsNavScroller.ViewChanged += (_, _) => UpdateSettingsNavScrollCue();
        _settingsNavScroller.SizeChanged += (_, _) => UpdateSettingsNavScrollCue();
        _settingsNavScroller.Loaded += (_, _) => UpdateSettingsNavScrollCue();
        _settingsNavStack.SizeChanged += (_, _) => UpdateSettingsNavScrollCue();
    }

    private async void SettingsPage_Loaded(object sender, RoutedEventArgs e)
    {
        try
        {
            await ReloadAsync();
            RefreshControlCenterStatus();
            _metricsTimer.Start();
        }
        catch (Exception exception)
        {
            CrashLog.Write(exception);
            ToastService.Show(AppLocalizer.T("设置页加载失败", "Unable to load settings"), ToastKind.Error);
        }
    }

    private UIElement BuildContent()
    {
        _settingsLayoutGrid.Children.Clear();
        _settingsLayoutGrid.ColumnDefinitions.Clear();
        _settingsLayoutGrid.RowDefinitions.Clear();

        var root = new StackPanel
        {
            Padding = new Thickness(24, 22, 36, 28),
            Spacing = 18
        };
        root.Children.Add(BuildHero());
        var controlCenter = BuildControlCenter();
        _settingsLayoutGrid.Children.Add(controlCenter);
        Grid.SetColumn(_settingsPageHost, 1);
        _settingsLayoutGrid.Children.Add(_settingsPageHost);
        root.Children.Add(_settingsLayoutGrid);
        BuildSections();
        ArrangeSections();
        return new ScrollViewer
        {
            VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
            HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled,
            Padding = new Thickness(0, 0, 8, 0),
            Content = root
        };
    }

    private Border BuildHero()
    {
        var grid = new Grid { ColumnSpacing = 18, RowSpacing = 12 };
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        grid.ColumnDefinitions.Add(new ColumnDefinition());
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        grid.Children.Add(ModernUi.IconTile("\uE713", 64, ModernUi.AccentSoft, ModernUi.Accent, 28));

        var title = new StackPanel
        {
            Spacing = 5,
            VerticalAlignment = VerticalAlignment.Center,
            Children =
            {
                ModernUi.Text(AppLocalizer.T("设置", "Settings"), 24, FontWeights.SemiBold),
                ModernUi.Text(AppLocalizer.T("显示、网络、工具箱、日志和桌面行为都在这里集中管理。", "Display, network, toolbox, logs, and desktop behavior live here."), 14, foreground: ModernUi.TextSecondary, maxLines: 2)
            }
        };
        Grid.SetColumn(title, 1);
        grid.Children.Add(title);

        var chips = new StackPanel
        {
            Orientation = Orientation.Horizontal,
            Spacing = 8,
            VerticalAlignment = VerticalAlignment.Center,
            Children =
            {
                ModernUi.Chip(AppLocalizer.T("工具", "Tools"), _catalog.Modules.Count.ToString(), "\uE90F", selected: true),
                ModernUi.Chip(AppLocalizer.T("日志", "Logs"), "SQLite", "\uE9F9"),
                ModernUi.Chip(AppLocalizer.T("语言", "Language"), AppLocalizer.T("中 / 英", "ZH / EN"), "\uE774")
            }
        };
        Grid.SetColumn(chips, 2);
        grid.Children.Add(chips);
        grid.SizeChanged += (_, e) =>
        {
            var narrow = e.NewSize.Width < 880;
            grid.ColumnDefinitions.Clear();
            grid.RowDefinitions.Clear();
            grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
            grid.ColumnDefinitions.Add(new ColumnDefinition());
            if (narrow)
            {
                grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
                grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
                Grid.SetColumn(chips, 1);
                Grid.SetRow(chips, 1);
            }
            else
            {
                grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
                Grid.SetColumn(chips, 2);
                Grid.SetRow(chips, 0);
            }
        };
        return ModernUi.Card(grid, new Thickness(18), radius: 8);
    }

    private Border BuildControlCenter()
    {
        _settingsNavStack.Children.Clear();
        if (_settingsNavPaddingHost.Child is null)
        {
            _settingsNavPaddingHost.Child = _settingsNavStack;
        }

        _settingsNavScroller.Content = _settingsNavPaddingHost;
        RefreshControlCenterStatus();
        var stack = new StackPanel
        {
            Spacing = 14,
            Children =
            {
                new StackPanel
                {
                    Spacing = 3,
                    Children =
                    {
                        ModernUi.Text(AppLocalizer.T("控制中心", "Control center"), 18, FontWeights.SemiBold),
                        ModernUi.Text(AppLocalizer.T("选择一个分页管理设置，列表保留 5 个入口高度。", "Choose a page to manage settings; the list keeps five entries visible."), 12, foreground: ModernUi.TextSecondary, maxLines: 2)
                    }
                },
                new StackPanel
                {
                    Spacing = 2,
                    Children =
                    {
                        _settingsNavScroller,
                        _settingsNavCueButton
                    }
                },
                new Border
                {
                    Height = 1,
                    Background = ModernUi.Stroke,
                    Margin = new Thickness(0, 4, 0, 0)
                },
                new StackPanel
                {
                    Spacing = 10,
                    Children =
                    {
                        _cpuStrip,
                        _memoryStrip,
                        BuildControlStatusLine("\uE950", AppLocalizer.T("处理器", "Processor"), _controlProcessorStatus),
                        BuildControlStatusLine("\uE823", AppLocalizer.T("运行", "Uptime"), _controlUptimeStatus)
                    }
                }
            }
        };

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

    private void ConfigureSettingsNavScrollCue()
    {
        _settingsNavCueIcon.Glyph = "\uE70D";
        _settingsNavCueIcon.FontSize = 13;
        _settingsNavCueIcon.Foreground = ModernUi.Accent;
        _settingsNavCueIcon.Opacity = 0.92;
        _settingsNavCueIcon.RenderTransform = _settingsNavCueTransform;
        _settingsNavCueIcon.RenderTransformOrigin = new Windows.Foundation.Point(0.5, 0.5);

        var content = new Grid
        {
            ColumnSpacing = 8,
            HorizontalAlignment = HorizontalAlignment.Stretch,
            VerticalAlignment = VerticalAlignment.Center
        };
        content.ColumnDefinitions.Add(new ColumnDefinition());
        content.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        content.ColumnDefinitions.Add(new ColumnDefinition());

        content.Children.Add(new Border
        {
            Height = 1,
            Background = ModernUi.Stroke,
            VerticalAlignment = VerticalAlignment.Center
        });

        var iconHost = new Border
        {
            Width = 34,
            Height = 18,
            CornerRadius = new CornerRadius(6),
            Background = ModernUi.SurfaceAlt,
            BorderBrush = ModernUi.Stroke,
            BorderThickness = new Thickness(1),
            Child = _settingsNavCueIcon
        };
        Grid.SetColumn(iconHost, 1);
        content.Children.Add(iconHost);

        var rightLine = new Border
        {
            Height = 1,
            Background = ModernUi.Stroke,
            VerticalAlignment = VerticalAlignment.Center
        };
        Grid.SetColumn(rightLine, 2);
        content.Children.Add(rightLine);

        _settingsNavCueButton.Height = 28;
        _settingsNavCueButton.MinHeight = 28;
        _settingsNavCueButton.Padding = new Thickness(0);
        _settingsNavCueButton.Margin = new Thickness(0, 0, 12, 0);
        _settingsNavCueButton.HorizontalAlignment = HorizontalAlignment.Stretch;
        _settingsNavCueButton.HorizontalContentAlignment = HorizontalAlignment.Stretch;
        _settingsNavCueButton.CornerRadius = new CornerRadius(6);
        _settingsNavCueButton.Background = ModernUi.Brush("#00FFFFFF");
        _settingsNavCueButton.BorderBrush = ModernUi.Brush("#00FFFFFF");
        _settingsNavCueButton.BorderThickness = new Thickness(1);
        _settingsNavCueButton.Content = content;
        _settingsNavCueButton.Visibility = Visibility.Collapsed;
        _settingsNavCueButton.Click += (_, _) => ScrollSettingsNavByCue();
        ToolTipService.SetToolTip(_settingsNavCueButton, AppLocalizer.T("查看更多设置分页", "Show more settings pages"));
        AutomationProperties.SetName(_settingsNavCueButton, AppLocalizer.T("查看更多设置分页", "Show more settings pages"));
    }

    private void ScrollSettingsNavByCue()
    {
        if (_settingsNavScroller.ScrollableHeight <= 1)
        {
            return;
        }

        var targetOffset = IsSettingsNavAtBottom()
            ? 0
            : Math.Min(_settingsNavScroller.ScrollableHeight, _settingsNavScroller.VerticalOffset + ControlCenterNavScrollStep);
        var disableAnimation = !_settingsService.Current.AnimationsEnabled || _accessibility.HighContrast;
        _settingsNavScroller.ChangeView(null, targetOffset, null, disableAnimation);
    }

    private void UpdateSettingsNavScrollCue()
    {
        var hasOverflow = _settingsNavScroller.ScrollableHeight > 1;
        _settingsNavCueButton.Visibility = hasOverflow ? Visibility.Visible : Visibility.Collapsed;
        if (!hasOverflow)
        {
            StopSettingsNavCueAnimation();
            return;
        }

        var atBottom = IsSettingsNavAtBottom();
        _settingsNavCueIcon.Glyph = atBottom ? "\uE70E" : "\uE70D";
        _settingsNavCueIcon.Foreground = atBottom ? ModernUi.TextSecondary : ModernUi.Accent;
        var cueText = atBottom
            ? AppLocalizer.T("返回控制中心顶部", "Back to the top of control center")
            : AppLocalizer.T("查看更多设置分页", "Show more settings pages");
        ToolTipService.SetToolTip(_settingsNavCueButton, cueText);
        AutomationProperties.SetName(_settingsNavCueButton, cueText);

        if (!_settingsService.Current.AnimationsEnabled || _accessibility.HighContrast)
        {
            StopSettingsNavCueAnimation();
            return;
        }

        StartSettingsNavCueAnimation(atBottom);
    }

    private bool IsSettingsNavAtBottom()
    {
        return _settingsNavScroller.VerticalOffset >= _settingsNavScroller.ScrollableHeight - 1;
    }

    private void StartSettingsNavCueAnimation(bool pointsUp)
    {
        if (_settingsNavCueStoryboard is not null && _settingsNavCuePointsUp == pointsUp)
        {
            return;
        }

        StopSettingsNavCueAnimation();
        _settingsNavCuePointsUp = pointsUp;
        _settingsNavCueStoryboard = new Storyboard();

        var move = new DoubleAnimation
        {
            From = 0,
            To = pointsUp ? -3 : 3,
            AutoReverse = true,
            Duration = new Duration(TimeSpan.FromMilliseconds(900)),
            RepeatBehavior = RepeatBehavior.Forever,
            EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut }
        };
        Storyboard.SetTarget(move, _settingsNavCueTransform);
        Storyboard.SetTargetProperty(move, "Y");
        _settingsNavCueStoryboard.Children.Add(move);

        var pulse = new DoubleAnimation
        {
            From = 0.72,
            To = 1,
            AutoReverse = true,
            Duration = new Duration(TimeSpan.FromMilliseconds(900)),
            RepeatBehavior = RepeatBehavior.Forever,
            EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut }
        };
        Storyboard.SetTarget(pulse, _settingsNavCueIcon);
        Storyboard.SetTargetProperty(pulse, "Opacity");
        _settingsNavCueStoryboard.Children.Add(pulse);
        _settingsNavCueStoryboard.Begin();
    }

    private void StopSettingsNavCueAnimation()
    {
        _settingsNavCueStoryboard?.Stop();
        _settingsNavCueStoryboard = null;
        _settingsNavCueTransform.Y = 0;
        _settingsNavCueIcon.Opacity = 0.92;
    }

    private static UIElement BuildControlStatusLine(string glyph, string title, TextBlock value)
    {
        var grid = new Grid { ColumnSpacing = 10 };
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        grid.ColumnDefinitions.Add(new ColumnDefinition());
        grid.Children.Add(ModernUi.IconTile(glyph, 30, ModernUi.SurfaceAlt, ModernUi.TextSecondary, 13));
        var text = new StackPanel
        {
            Spacing = 0,
            VerticalAlignment = VerticalAlignment.Center,
            Children =
            {
                ModernUi.Text(title, 12, FontWeights.SemiBold, ModernUi.TextSecondary, maxLines: 1),
                value
            }
        };
        Grid.SetColumn(text, 1);
        grid.Children.Add(text);
        return grid;
    }

    private void AddSettingsPage(string key, string title, string subtitle, string glyph, params UIElement[] sections)
    {
        var content = new StackPanel
        {
            Spacing = 16,
            Children =
            {
                new StackPanel
                {
                    Spacing = 4,
                    Children =
                    {
                        ModernUi.Text(title, 24, FontWeights.SemiBold, maxLines: 1),
                        ModernUi.Text(subtitle, 13, foreground: ModernUi.TextSecondary, maxLines: 2)
                    }
                }
            }
        };
        foreach (var section in sections)
        {
            content.Children.Add(section);
        }

        _settingsPages[key] = content;
        var button = CreateSettingsPageButton(key, title, glyph);
        _settingsPageButtons[key] = button;
        _settingsNavStack.Children.Add(button);
    }

    private Button CreateSettingsPageButton(string key, string title, string glyph)
    {
        var grid = new Grid { ColumnSpacing = 8, MinHeight = 28 };
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        grid.ColumnDefinitions.Add(new ColumnDefinition());
        grid.Children.Add(ModernUi.IconTile(glyph, 28, ModernUi.SurfaceAlt, ModernUi.TextSecondary, 12));
        var label = ModernUi.Text(title, 13, FontWeights.SemiBold, maxLines: 1);
        Grid.SetColumn(label, 1);
        grid.Children.Add(label);

        var button = new Button
        {
            HorizontalAlignment = HorizontalAlignment.Stretch,
            HorizontalContentAlignment = HorizontalAlignment.Stretch,
            Height = 38,
            MinHeight = 38,
            Padding = new Thickness(7, 4, 7, 4),
            CornerRadius = new CornerRadius(8),
            Background = ModernUi.Brush("#00FFFFFF"),
            BorderBrush = ModernUi.Brush("#00FFFFFF"),
            BorderThickness = new Thickness(1),
            Content = grid,
            Tag = key
        };
        button.Click += (_, _) => ShowSettingsPage(key);
        AutomationProperties.SetName(button, title);
        return button;
    }

    private void ShowSettingsPage(string key)
    {
        if (!_settingsPages.TryGetValue(key, out var page))
        {
            return;
        }

        _activeSettingsPage = key;
        _settingsPageHost.Content = page;
        UpdateSettingsPageButtons();
    }

    private void UpdateSettingsPageButtons()
    {
        foreach (var pair in _settingsPageButtons)
        {
            var selected = string.Equals(pair.Key, _activeSettingsPage, StringComparison.OrdinalIgnoreCase);
            pair.Value.Background = selected ? ModernUi.AccentSoft : ModernUi.Brush("#00FFFFFF");
            pair.Value.BorderBrush = selected ? ModernUi.Accent : ModernUi.Brush("#00FFFFFF");
            if (pair.Value.Content is Grid grid && grid.Children.FirstOrDefault() is Border iconTile)
            {
                iconTile.Background = selected ? ModernUi.AccentSoft : ModernUi.SurfaceAlt;
                if (iconTile.Child is FontIcon icon)
                {
                    icon.Foreground = selected ? ModernUi.Accent : ModernUi.TextSecondary;
                }
            }
        }
    }

    private void RefreshControlCenterStatus()
    {
        var metrics = _metricsService.Capture();
        var processorText = AppLocalizer.T($"{metrics.ProcessorCount} 核心", $"{metrics.ProcessorCount} cores");
        _controlProcessorStatus.Text = processorText;
        _processorStatus.Text = processorText;
        _memoryStatus.Text = metrics.TotalMemoryBytes is ulong total && metrics.UsedMemoryBytes is ulong used
            ? $"{FormatBytes(used)} / {FormatBytes(total)}"
            : FormatBytes(metrics.WorkingSetBytes);
        var uptime = TimeSpan.FromMilliseconds(Environment.TickCount64);
        var uptimeText = uptime.TotalDays >= 1
            ? $"{(int)uptime.TotalDays}d {uptime:hh\\:mm}"
            : uptime.ToString("hh\\:mm\\:ss");
        _controlUptimeStatus.Text = uptimeText;
        _uptimeStatus.Text = uptimeText;
        _processCpuStatus.Text = metrics.ProcessCpuUsagePercent is double processCpu
            ? $"{processCpu:0.0}%"
            : AppLocalizer.T("采样中", "Sampling");
        _processRuntimeStatus.Text = FormatDuration(metrics.ProcessUptime);
        _processThreadStatus.Text = AppLocalizer.T(
            $"{metrics.ProcessThreadCount} 线程 / {metrics.ProcessHandleCount} 句柄",
            $"{metrics.ProcessThreadCount} threads / {metrics.ProcessHandleCount} handles");
        _runtimeStatus.Text = $"{(metrics.Is64BitProcess ? "64-bit" : "32-bit")} · {metrics.RuntimeDescription}";
        _systemDriveStatus.Text = metrics.SystemDriveUsagePercent is double drivePercent &&
            metrics.SystemDriveUsedBytes is ulong driveUsed &&
            metrics.SystemDriveTotalBytes is ulong driveTotal
            ? $"{drivePercent:0}% · {FormatBytes(driveUsed)} / {FormatBytes(driveTotal)}"
            : AppLocalizer.T("暂不可用", "Unavailable");
        var cpuText = metrics.CpuUsagePercent is double cpuPercent
            ? $"{cpuPercent:0}%"
            : AppLocalizer.T("采样中", "Sampling");
        _cpuStrip.Update(metrics.CpuUsagePercent, cpuText);

        var memoryText = metrics.MemoryUsagePercent is double memoryPercent &&
            metrics.TotalMemoryBytes is ulong memoryTotal &&
            metrics.UsedMemoryBytes is ulong memoryUsed
            ? $"{memoryPercent:0}% · {FormatBytes(memoryUsed)} / {FormatBytes(memoryTotal)}"
            : AppLocalizer.T("暂不可用", "Unavailable");
        _memoryStrip.Update(metrics.MemoryUsagePercent, memoryText);

        var captured = metrics.CapturedAt.ToLocalTime().ToString("HH:mm:ss");
        _systemCpuChart.Update(
            metrics.CpuUsagePercent,
            cpuText,
            AppLocalizer.T($"{metrics.ProcessorCount} 核心 · 更新 {captured}", $"{metrics.ProcessorCount} cores · Updated {captured}"));
        _systemMemoryChart.Update(
            metrics.MemoryUsagePercent,
            memoryText,
            metrics.AvailableMemoryBytes is ulong available
                ? AppLocalizer.T($"可用 {FormatBytes(available)} · 更新 {captured}", $"Available {FormatBytes(available)} · Updated {captured}")
                : AppLocalizer.T($"更新 {captured}", $"Updated {captured}"));
        _processMemoryChart.Update(
            metrics.TotalMemoryBytes is ulong processTotal && processTotal > 0 ? Math.Clamp(metrics.WorkingSetBytes / (double)processTotal * 100, 0, 100) : null,
            FormatBytes(metrics.WorkingSetBytes),
            AppLocalizer.T($"托管内存 {FormatBytes(metrics.ManagedMemoryBytes)} · 更新 {captured}", $"Managed {FormatBytes(metrics.ManagedMemoryBytes)} · Updated {captured}"));
        var diskText = metrics.SystemDriveUsagePercent is double systemDrivePercent
            ? $"{systemDrivePercent:0}%"
            : AppLocalizer.T("暂不可用", "Unavailable");
        _systemDiskChart.Update(
            metrics.SystemDriveUsagePercent,
            diskText,
            metrics.SystemDriveAvailableBytes is ulong driveAvailable
                ? AppLocalizer.T($"可用 {FormatBytes(driveAvailable)} · 更新 {captured}", $"Available {FormatBytes(driveAvailable)} · Updated {captured}")
                : AppLocalizer.T($"更新 {captured}", $"Updated {captured}"));
        _lastRefreshStatus.Text = captured;
    }

    private static string FormatBytes(long bytes)
    {
        return FormatBytes((double)Math.Max(0, bytes));
    }

    private static string FormatBytes(ulong bytes)
    {
        return FormatBytes((double)bytes);
    }

    private static string FormatBytes(double bytes)
    {
        string[] units = ["B", "KB", "MB", "GB", "TB"];
        double value = Math.Max(0, bytes);
        var unit = 0;
        while (value >= 1024 && unit < units.Length - 1)
        {
            value /= 1024;
            unit++;
        }

        return $"{value:0.#} {units[unit]}";
    }

    private static string FormatDuration(TimeSpan duration)
    {
        if (duration <= TimeSpan.Zero)
        {
            return "--";
        }

        return duration.TotalDays >= 1
            ? $"{(int)duration.TotalDays}d {duration:hh\\:mm}"
            : duration.ToString("hh\\:mm\\:ss");
    }

    private void BuildSections()
    {
        BuildPagedSections();
        if (_settingsPages.Count > 0)
        {
            return;
        }

        _sectionsGrid.Children.Clear();
        _sectionsGrid.ColumnDefinitions.Clear();
        _sectionsGrid.RowDefinitions.Clear();
        _sectionCards.Clear();
        _materialCards.Clear();

        var sections = new[]
        {
            BuildSection(AppLocalizer.T("外观与交互", "Appearance"), "\uE713", [
                BuildActionRow("\uE706", AppLocalizer.T("主题模式", "Theme"), _themeSummary, ShowThemeDialogAsync),
                BuildActionRow("\uE790", AppLocalizer.T("窗口背景材质", "Window backdrop"), _windowBackdropSummary, ShowWindowBackdropDialogAsync),
                BuildActionRow("\uE7F4", AppLocalizer.T("顶部栏材质", "Top bar material"), _topBarMaterialSummary, ShowTopBarMaterialDialogAsync),
                BuildActionRow("\uE771", AppLocalizer.T("内容区域材质", "Content material"), _settingsMaterialSummary, ShowSettingsPanelMaterialDialogAsync),
                BuildActionRow("\uE8D2", AppLocalizer.T("字体大小", "Font size"), _fontSummary, ShowFontDialogAsync),
                BuildActionRow("\uE774", AppLocalizer.T("语言", "Language"), _languageSummary, ShowLanguageDialogAsync),
                BuildToggleRow("\uE7F4", AppLocalizer.T("界面动效", "Animations"), AppLocalizer.T("页面切换、展开和按钮反馈动效。", "Page transitions, expansion, and button feedback."), _animationSwitch),
                BuildToggleRow("\uE7F8", AppLocalizer.T("支持硬件加速", "Hardware acceleration"), AppLocalizer.T("为 WebView2 与 3D 内容启用 GPU 加速，关闭后会禁用 WebView2 GPU 渲染。", "Enable GPU acceleration for WebView2 and 3D content. Turning it off disables WebView2 GPU rendering."), _hardwareAccelerationSwitch)
            ]),
            BuildSection(AppLocalizer.T("桌面行为", "Desktop"), "\uE7F4", [
                BuildToggleRow("\uE739", AppLocalizer.T("恢复上次窗口状态", "Restore window state"), AppLocalizer.T("启动时恢复窗口位置、大小和最大化状态。", "Restore position, size, and maximized state on launch."), _restoreSwitch),
                BuildActionRow("\uE8BB", AppLocalizer.T("关闭按钮行为", "Close button"), _closeSummary, ShowCloseBehaviorDialogAsync),
                BuildToggleRow("\uE7B9", AppLocalizer.T("开机自启", "Start with Windows"), AppLocalizer.T("登录 Windows 后自动启动。", "Launch after signing in to Windows."), _autoStartSwitch)
            ]),
            BuildSection(AppLocalizer.T("网络与来源", "Network"), "\uE774", [
                BuildToggleRow("\uE774", AppLocalizer.T("启用代理", "Use proxy"), AppLocalizer.T("用于更新、联网工具和远程数据获取。", "Used for updates, online tools, and remote data."), _proxySwitch),
                BuildActionRow("\uE8AB", AppLocalizer.T("代理模式", "Proxy mode"), _proxySummary, ShowProxyDialogAsync),
                BuildActionRow("\uE916", AppLocalizer.T("测试超时", "Timeout"), _timeoutSummary, ShowTimeoutDialogAsync)
            ]),
            BuildSection(AppLocalizer.T("维护", "Maintenance"), "\uE90F", [
                BuildActionRow("\uE895", AppLocalizer.T("清理远程配置缓存", "Clear remote cache"), ModernUi.Text(AppLocalizer.T("删除本地缓存的远程配置。", "Delete cached remote configuration files."), 13, foreground: ModernUi.TextSecondary), ClearRemoteCacheAsync),
                BuildActionRow("\uE823", AppLocalizer.T("清理最近使用", "Clear recent tools"), ModernUi.Text(AppLocalizer.T("移除首页最近访问工具。", "Remove tools from the Home recent list."), 13, foreground: ModernUi.TextSecondary), ClearRecentAsync),
                BuildActionRow("\uE9F9", AppLocalizer.T("日志保留数量", "Log retention"), _retentionSummary, ShowLogRetentionDialogAsync),
                BuildToggleRow("\uE7F4", AppLocalizer.T("更新通知", "Update notifications"), AppLocalizer.T("检查到新版本时显示提醒。", "Show a notification when an update is available."), _updateSwitch)
            ]),
            BuildSection(AppLocalizer.T("反馈", "Feedback"), "\uE724", [
                BuildActionRow("\uE77B", AppLocalizer.T("默认联系方式", "Default contact"), _feedbackContactSummary, ShowFeedbackContactDialogAsync),
                BuildActionRow("\uE8D4", AppLocalizer.T("默认类型与严重程度", "Default type and severity"), _feedbackDefaultsSummary, ShowFeedbackDefaultsDialogAsync),
                BuildToggleRow("\uE9F9", AppLocalizer.T("默认包含当天日志", "Include today's logs by default"), AppLocalizer.T("新建反馈时默认勾选当天日志，反馈包仍会脱敏。", "Preselect today's logs for new feedback. Packages are still sanitized."), _feedbackLogsSwitch),
                BuildToggleRow("\uE90F", AppLocalizer.T("默认包含工具运行状态", "Include tool status by default"), AppLocalizer.T("新建反馈时默认加入工具目录和运行状态摘要。", "Preselect tool catalog and runtime status summary."), _feedbackToolStatusSwitch),
                BuildToggleRow("\uE946", AppLocalizer.T("默认包含系统摘要", "Include system summary by default"), AppLocalizer.T("新建反馈时默认加入设备与运行时摘要。", "Preselect device and runtime summary."), _feedbackSystemSwitch),
                BuildActionRow("\uE838", AppLocalizer.T("打开反馈包目录", "Open feedback package folder"), ModernUi.Text(AppLocalizer.T("查看本地保留的反馈 zip。", "View locally retained feedback zip files."), 13, foreground: ModernUi.TextSecondary), OpenFeedbackFolderAsync)
            ]),
            BuildSection(AppLocalizer.T("插件系统", "Plugin system"), "\uECAA", [
                BuildToggleRow("\uECAA", AppLocalizer.T("启用插件系统", "Enable plugin system"), AppLocalizer.T("关闭时不加载插件工具，也不显示插件页面入口。", "When disabled, plugin tools are not loaded and the plugin page entry is hidden."), _pluginSwitch),
                BuildActionRow("\uE838", AppLocalizer.T("插件根目录", "Plugin root"), _pluginRootSummary, ChoosePluginRootAsync),
                BuildActionRow("\uE777", AppLocalizer.T("恢复默认插件目录", "Restore default plugin folder"), ModernUi.Text(AppLocalizer.T("使用用户数据目录下的 Plugins 文件夹。", "Use the Plugins folder under user data."), 13, foreground: ModernUi.TextSecondary), ResetPluginRootAsync),
                BuildActionRow("\uE8A7", AppLocalizer.T("打开插件目录", "Open plugin folder"), ModernUi.Text(AppLocalizer.T("在资源管理器中打开当前插件根目录。", "Open the current plugin root in File Explorer."), 13, foreground: ModernUi.TextSecondary), OpenPluginRootAsync)
            ]),
            BuildSection(AppLocalizer.T("首页", "Home"), "\uE80F", [
                BuildActionRow("\uE80F", AppLocalizer.T("首页内容", "Home content"), _homeSummary, ShowHomePageModeDialogAsync)
            ]),
            BuildSection(AppLocalizer.T("工具箱与安全", "Toolbox and safety"), "\uE90F", [
                BuildActionRow("\uE8A7", AppLocalizer.T("工具箱布局", "Toolbox layout"), _toolDisplayModeSummary, ShowToolDisplayModeDialogAsync),
                BuildActionRow("\uE71B", AppLocalizer.T("默认工具范围", "Default toolbox scope"), _toolboxScopeSummary, ShowToolboxScopeDialogAsync),
                BuildToggleRow("\uE8A7", AppLocalizer.T("紧凑卡片", "Compact cards"), AppLocalizer.T("工具较多时使用更紧凑的参考项目风格卡片。", "Use denser reference-style cards when the toolbox has many tools."), _toolboxCompactSwitch),
                BuildToggleRow("\uE81C", AppLocalizer.T("最近使用优先", "Recent tools first"), AppLocalizer.T("在每个筛选范围内优先显示最近打开的工具。", "Show recently opened tools before ordinary tools inside each filter."), _toolboxRecentFirstSwitch),
                BuildToggleRow("\uE950", AppLocalizer.T("硬件品牌 Logo", "Hardware brand logo"), AppLocalizer.T("在支持的硬件视图中显示检测到的硬件品牌标识。", "Show detected hardware brand marks in supported hardware views."), _hardwareLogoSwitch),
                BuildToggleRow("\uE7BA", AppLocalizer.T("风险确认", "Risk confirmation"), AppLocalizer.T("管理员运行、注册表、Hosts、证书、Defender、清理、删除和未知 EXE 启动前再次确认。", "Ask again before admin runs, registry, Hosts, certificates, Defender, cleanup, deletion, and unknown EXE launch."), _riskConfirmationSwitch),
                BuildActionRow("\uE777", AppLocalizer.T("重置风险确认", "Reset risk confirmations"), ModernUi.Text(AppLocalizer.T("清除已记住的风险工具确认。", "Forget remembered confirmations for risk tools."), 13, foreground: ModernUi.TextSecondary), ResetRiskConfirmationsAsync)
            ]),
            BuildProxyDiagnostic(),
            BuildAppInfo()
        };

        foreach (var section in sections)
        {
            _sectionCards.Add(section);
        }

        ArrangeSections();
    }

    private void BuildPagedSections()
    {
        _settingsPages.Clear();
        _settingsPageButtons.Clear();
        _settingsNavStack.Children.Clear();
        _materialCards.Clear();

        AddSettingsPage("appearance", AppLocalizer.T("外观", "Appearance"), AppLocalizer.T("主题、材质、字体、语言和动效。", "Theme, materials, font, language, and motion."), "\uE713",
            BuildSection(AppLocalizer.T("外观与交互", "Appearance"), "\uE713", [
                BuildActionRow("\uE706", AppLocalizer.T("主题模式", "Theme"), _themeSummary, ShowThemeDialogAsync),
                BuildActionRow("\uE790", AppLocalizer.T("窗口背景材质", "Window backdrop"), _windowBackdropSummary, ShowWindowBackdropDialogAsync),
                BuildActionRow("\uE7F4", AppLocalizer.T("顶部栏材质", "Top bar material"), _topBarMaterialSummary, ShowTopBarMaterialDialogAsync),
                BuildActionRow("\uE771", AppLocalizer.T("内容区域材质", "Content material"), _settingsMaterialSummary, ShowSettingsPanelMaterialDialogAsync),
                BuildActionRow("\uE8D2", AppLocalizer.T("字体大小", "Font size"), _fontSummary, ShowFontDialogAsync),
                BuildActionRow("\uE774", AppLocalizer.T("语言", "Language"), _languageSummary, ShowLanguageDialogAsync),
                BuildToggleRow("\uE7F4", AppLocalizer.T("界面动效", "Animations"), AppLocalizer.T("页面切换、展开和按钮反馈动效。", "Page transitions, expansion, and button feedback."), _animationSwitch),
                BuildToggleRow("\uE7F8", AppLocalizer.T("硬件加速", "Hardware acceleration"), AppLocalizer.T("为 WebView2 与 3D 内容启用 GPU 渲染。", "Enable GPU rendering for WebView2 and 3D content."), _hardwareAccelerationSwitch)
            ]));

        AddSettingsPage("system", AppLocalizer.T("系统概况", "System overview"), AppLocalizer.T("实时查看 CPU、内存、系统盘、运行时和应用进程占用。", "View live CPU, memory, system drive, runtime, and app process usage."), "\uE950",
            BuildSystemOverview());

        AddSettingsPage("desktop", AppLocalizer.T("桌面", "Desktop"), AppLocalizer.T("窗口、关闭按钮和开机行为。", "Window, close button, and startup behavior."), "\uE7F4",
            BuildSection(AppLocalizer.T("桌面行为", "Desktop"), "\uE7F4", [
                BuildToggleRow("\uE739", AppLocalizer.T("恢复上次窗口状态", "Restore window state"), AppLocalizer.T("启动时恢复窗口位置、大小和最大化状态。", "Restore position, size, and maximized state on launch."), _restoreSwitch),
                BuildActionRow("\uE8BB", AppLocalizer.T("关闭按钮行为", "Close button"), _closeSummary, ShowCloseBehaviorDialogAsync),
                BuildToggleRow("\uE7B9", AppLocalizer.T("开机自启", "Start with Windows"), AppLocalizer.T("登录 Windows 后自动启动。", "Launch after signing in to Windows."), _autoStartSwitch)
            ]));

        AddSettingsPage("network", AppLocalizer.T("网络", "Network"), AppLocalizer.T("代理、超时和连接诊断。", "Proxy, timeout, and connectivity diagnostics."), "\uE774",
            BuildSection(AppLocalizer.T("网络与来源", "Network"), "\uE774", [
                BuildToggleRow("\uE774", AppLocalizer.T("启用代理", "Use proxy"), AppLocalizer.T("用于更新、联网工具和远程数据获取。", "Used for updates, online tools, and remote data."), _proxySwitch),
                BuildActionRow("\uE8AB", AppLocalizer.T("代理模式", "Proxy mode"), _proxySummary, ShowProxyDialogAsync),
                BuildActionRow("\uE916", AppLocalizer.T("测试超时", "Timeout"), _timeoutSummary, ShowTimeoutDialogAsync)
            ]),
            BuildProxyDiagnostic());

        AddSettingsPage("maintenance", AppLocalizer.T("维护", "Maintenance"), AppLocalizer.T("缓存、最近使用和日志策略。", "Cache, recent tools, and log policy."), "\uE90F",
            BuildSection(AppLocalizer.T("维护", "Maintenance"), "\uE90F", [
                BuildActionRow("\uE895", AppLocalizer.T("清理远程配置缓存", "Clear remote cache"), ModernUi.Text(AppLocalizer.T("删除本地缓存的远程配置。", "Delete cached remote configuration files."), 13, foreground: ModernUi.TextSecondary), ClearRemoteCacheAsync),
                BuildActionRow("\uE823", AppLocalizer.T("清理最近使用", "Clear recent tools"), ModernUi.Text(AppLocalizer.T("移除首页最近访问工具。", "Remove tools from the Home recent list."), 13, foreground: ModernUi.TextSecondary), ClearRecentAsync),
                BuildActionRow("\uE9F9", AppLocalizer.T("日志保留数量", "Log retention"), _retentionSummary, ShowLogRetentionDialogAsync),
                BuildToggleRow("\uE7F4", AppLocalizer.T("更新通知", "Update notifications"), AppLocalizer.T("检查到新版本时显示提醒。", "Show a notification when an update is available."), _updateSwitch)
            ]));

        AddSettingsPage("feedback", AppLocalizer.T("反馈", "Feedback"), AppLocalizer.T("默认联系信息和反馈包内容。", "Default contact and feedback package contents."), "\uE724",
            BuildSection(AppLocalizer.T("反馈", "Feedback"), "\uE724", [
                BuildActionRow("\uE77B", AppLocalizer.T("默认联系方式", "Default contact"), _feedbackContactSummary, ShowFeedbackContactDialogAsync),
                BuildActionRow("\uE8D4", AppLocalizer.T("默认类型与严重程度", "Default type and severity"), _feedbackDefaultsSummary, ShowFeedbackDefaultsDialogAsync),
                BuildToggleRow("\uE9F9", AppLocalizer.T("默认包含当天日志", "Include today's logs by default"), AppLocalizer.T("新建反馈时预选当天日志。", "Preselect today's logs for new feedback."), _feedbackLogsSwitch),
                BuildToggleRow("\uE90F", AppLocalizer.T("默认包含工具运行状态", "Include tool status by default"), AppLocalizer.T("新建反馈时加入工具目录和运行状态摘要。", "Preselect tool catalog and runtime status summary."), _feedbackToolStatusSwitch),
                BuildToggleRow("\uE946", AppLocalizer.T("默认包含系统摘要", "Include system summary by default"), AppLocalizer.T("新建反馈时加入设备与运行时摘要。", "Preselect device and runtime summary."), _feedbackSystemSwitch),
                BuildActionRow("\uE838", AppLocalizer.T("打开反馈包目录", "Open feedback package folder"), ModernUi.Text(AppLocalizer.T("查看本地保留的反馈 zip。", "View locally retained feedback zip files."), 13, foreground: ModernUi.TextSecondary), OpenFeedbackFolderAsync)
            ]));

        AddSettingsPage("plugins", AppLocalizer.T("插件", "Plugins"), AppLocalizer.T("插件系统开关和根目录。", "Plugin system switch and root folder."), "\uECAA",
            BuildSection(AppLocalizer.T("插件系统", "Plugin system"), "\uECAA", [
                BuildToggleRow("\uECAA", AppLocalizer.T("启用插件系统", "Enable plugin system"), AppLocalizer.T("关闭时不加载插件工具，也不显示插件页入口。", "When disabled, plugin tools are not loaded and the plugin page entry is hidden."), _pluginSwitch),
                BuildActionRow("\uE838", AppLocalizer.T("插件根目录", "Plugin root"), _pluginRootSummary, ChoosePluginRootAsync),
                BuildActionRow("\uE777", AppLocalizer.T("恢复默认插件目录", "Restore default plugin folder"), ModernUi.Text(AppLocalizer.T("使用用户数据目录下的 Plugins 文件夹。", "Use the Plugins folder under user data."), 13, foreground: ModernUi.TextSecondary), ResetPluginRootAsync),
                BuildActionRow("\uE8A7", AppLocalizer.T("打开插件目录", "Open plugin folder"), ModernUi.Text(AppLocalizer.T("在资源管理器中打开当前插件根目录。", "Open the current plugin root in File Explorer."), 13, foreground: ModernUi.TextSecondary), OpenPluginRootAsync)
            ]));

        AddSettingsPage("home", AppLocalizer.T("首页", "Home"), AppLocalizer.T("首页内容和默认工作台。", "Home content and default dashboard."), "\uE80F",
            BuildSection(AppLocalizer.T("首页", "Home"), "\uE80F", [
                BuildActionRow("\uE80F", AppLocalizer.T("首页内容", "Home content"), _homeSummary, ShowHomePageModeDialogAsync)
            ]));

        AddSettingsPage("toolbox", AppLocalizer.T("工具箱与安全", "Toolbox and safety"), AppLocalizer.T("工具显示、默认范围和风险确认。", "Tool display, default scope, and risk confirmations."), "\uE90F",
            BuildSection(AppLocalizer.T("工具箱与安全", "Toolbox and safety"), "\uE90F", [
                BuildActionRow("\uE8A7", AppLocalizer.T("工具箱布局", "Toolbox layout"), _toolDisplayModeSummary, ShowToolDisplayModeDialogAsync),
                BuildActionRow("\uE71B", AppLocalizer.T("默认工具范围", "Default toolbox scope"), _toolboxScopeSummary, ShowToolboxScopeDialogAsync),
                BuildToggleRow("\uE8A7", AppLocalizer.T("紧凑卡片", "Compact cards"), AppLocalizer.T("工具较多时使用更紧凑的卡片。", "Use denser cards when the toolbox has many tools."), _toolboxCompactSwitch),
                BuildToggleRow("\uE81C", AppLocalizer.T("最近使用优先", "Recent tools first"), AppLocalizer.T("每个筛选范围内优先显示最近打开的工具。", "Show recently opened tools before ordinary tools inside each filter."), _toolboxRecentFirstSwitch),
                BuildToggleRow("\uE950", AppLocalizer.T("硬件品牌 Logo", "Hardware brand logo"), AppLocalizer.T("在支持的硬件视图中显示检测到的品牌标识。", "Show detected hardware brand marks in supported hardware views."), _hardwareLogoSwitch),
                BuildToggleRow("\uE7BA", AppLocalizer.T("风险确认", "Risk confirmation"), AppLocalizer.T("高风险操作启动前再次确认。", "Ask again before high-risk operations."), _riskConfirmationSwitch),
                BuildActionRow("\uE777", AppLocalizer.T("重置风险确认", "Reset risk confirmations"), ModernUi.Text(AppLocalizer.T("清除已记住的风险工具确认。", "Forget remembered confirmations for risk tools."), 13, foreground: ModernUi.TextSecondary), ResetRiskConfirmationsAsync)
            ]));

        AddSettingsPage("about", AppLocalizer.T("应用信息", "App info"), AppLocalizer.T("应用信息和本地数据概览。", "App information and local data overview."), "\uE946",
            BuildAppInfo());

        if (!_settingsPages.ContainsKey(_activeSettingsPage))
        {
            _activeSettingsPage = "appearance";
        }

        ShowSettingsPage(_activeSettingsPage);
        ArrangeSections();
        DispatcherQueue.TryEnqueue(UpdateSettingsNavScrollCue);
    }

    private Border BuildSection(string title, string glyph, IEnumerable<UIElement> rows)
    {
        var stack = new StackPanel { Spacing = 4 };
        stack.Children.Add(new StackPanel
        {
            Orientation = Orientation.Horizontal,
            Spacing = 10,
            Margin = new Thickness(0, 0, 0, 10),
            Children =
            {
                ModernUi.IconTile(glyph, 34, ModernUi.SurfaceAlt, ModernUi.Accent, 16),
                ModernUi.Text(title, 18, FontWeights.SemiBold)
            }
        });
        foreach (var row in rows)
        {
            stack.Children.Add(row);
        }

        var card = ModernUi.Card(stack, new Thickness(16), radius: 8);
        ApplySettingsPanelMaterial(card);
        _materialCards.Add(card);
        return card;
    }

    private void ApplySettingsPanelMaterial(Border card)
    {
        var dark = string.Equals(_settings.Theme, "Dark", StringComparison.OrdinalIgnoreCase);
        card.Background = ThemeService.CreateContentBrush(_settings.SettingsPanelMaterial ?? _settingsService.Current.SettingsPanelMaterial, dark);
    }

    private void ApplySettingsPanelMaterialToCards()
    {
        ApplySettingsPageBackground();
        foreach (var card in _materialCards)
        {
            ApplySettingsPanelMaterial(card);
        }
    }

    private void ApplySettingsPageBackground()
    {
        var material = (_settings.WindowBackdrop ?? _settingsService.Current.WindowBackdrop ?? "mica").Trim().ToLowerInvariant();
        Background = material is "solid" or "none"
            ? ModernUi.AppBackground
            : new SolidColorBrush(Color.FromArgb(0, 0, 0, 0));
    }

    private UIElement BuildActionRow(string glyph, string title, UIElement value, Func<Task> action)
    {
        var row = BaseRow(glyph, title, value);
        var tooltip = AppLocalizer.T($"打开 {title}", $"Open {title}");
        var button = ModernUi.IconButton("\uE974", tooltip, async () => await action());
        button.Width = 42;
        button.Height = 38;
        button.MinWidth = 42;
        button.MinHeight = 38;
        button.VerticalAlignment = VerticalAlignment.Center;
        button.HorizontalAlignment = HorizontalAlignment.Right;
        ToolTipService.SetToolTip(button, tooltip);
        AutomationProperties.SetName(button, tooltip);
        row.Children.Add(button);
        Grid.SetColumn(button, 2);
        return row;
    }

    private UIElement BuildToggleRow(string glyph, string title, string subtitle, ToggleSwitch toggle)
    {
        var row = BaseRow(glyph, title, ModernUi.Text(subtitle, 13, foreground: ModernUi.TextSecondary));
        toggle.VerticalAlignment = VerticalAlignment.Center;
        toggle.HorizontalAlignment = HorizontalAlignment.Right;
        toggle.MinWidth = 64;
        toggle.OnContent = string.Empty;
        toggle.OffContent = string.Empty;
        ToolTipService.SetToolTip(toggle, title);
        AutomationProperties.SetName(toggle, title);
        row.Children.Add(toggle);
        Grid.SetColumn(toggle, 2);
        return row;
    }

    private static Grid BaseRow(string glyph, string title, UIElement value)
    {
        var row = new Grid
        {
            MinHeight = 56,
            Padding = new Thickness(8, 8, 0, 8),
            ColumnSpacing = 12,
            HorizontalAlignment = HorizontalAlignment.Stretch
        };
        row.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        row.ColumnDefinitions.Add(new ColumnDefinition());
        row.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        row.Children.Add(ModernUi.IconTile(glyph, 34, ModernUi.SurfaceAlt, ModernUi.TextPrimary, 15));
        var text = new StackPanel
        {
            Spacing = 2,
            VerticalAlignment = VerticalAlignment.Center,
            IsHitTestVisible = false,
            Children =
            {
                ModernUi.Text(title, 15, FontWeights.SemiBold),
                value
            }
        };
        Grid.SetColumn(text, 1);
        row.Children.Add(text);
        return row;
    }

    private Border BuildProxyDiagnostic()
    {
        var button = ModernUi.PillButton(AppLocalizer.T("立即检测", "Run check"), "\uE9D9", async () => await RunProxyDiagnosticAsync(), primary: true);
        button.HorizontalAlignment = HorizontalAlignment.Right;
        return ModernUi.Card(new StackPanel
        {
            Spacing = 12,
            Children =
            {
                new Grid
                {
                    ColumnDefinitions =
                    {
                        new ColumnDefinition(),
                        new ColumnDefinition { Width = GridLength.Auto }
                    },
                    Children =
                    {
                        new StackPanel
                        {
                            Orientation = Orientation.Horizontal,
                            Spacing = 10,
                            Children =
                            {
                                ModernUi.IconTile("\uE774", 34, ModernUi.AccentSoft, ModernUi.Accent, 16),
                                ModernUi.Text(AppLocalizer.T("代理诊断", "Proxy diagnostics"), 18, FontWeights.SemiBold)
                            }
                        },
                        button
                    }
                },
                ModernUi.Text(AppLocalizer.T("检测国内、国际和更新服务连通性，只展示目标名称、HTTP 状态和延迟。", "Check domestic, international, and update connectivity. Only target name, HTTP status, and latency are shown."), 13, foreground: ModernUi.TextSecondary)
            }
        }, new Thickness(16), radius: 8);
    }

    private Border BuildAppInfo()
    {
        return ModernUi.Card(new StackPanel
        {
            Spacing = 12,
            Children =
            {
                new StackPanel
                {
                    Orientation = Orientation.Horizontal,
                    Spacing = 10,
                    Children =
                    {
                        ModernUi.IconTile("\uE946", 34, ModernUi.SurfaceAlt, ModernUi.Accent, 16),
                        ModernUi.Text(AppLocalizer.T("应用信息", "App info"), 18, FontWeights.SemiBold)
                    }
                },
                BuildInfoLine(AppLocalizer.T("工具数量", "Tools"), AppLocalizer.ToolCount(_catalog.Modules.Count)),
                BuildInfoLine(AppLocalizer.T("日志存储", "Log storage"), AppLocalizer.T("本地 SQLite 数据库", "Local SQLite database")),
                BuildInfoLine(AppLocalizer.T("运行模式", "Runtime"), "WinUI Desktop"),
                BuildInfoLine(AppLocalizer.T("配置", "Configuration"), AppLocalizer.T("本地设置 + SQLite 日志", "Local settings + SQLite logs")),
                BuildInfoLine(AppLocalizer.T("数据来源", "Data sources"), AppLocalizer.T("随包参考数据 + 远程官方配置", "Bundled reference data + remote official configs"))
            }
        }, new Thickness(16), radius: 8);
    }

    private UIElement BuildSystemOverview()
    {
        DetachFromParent(_systemCpuChart);
        DetachFromParent(_systemMemoryChart);
        DetachFromParent(_processMemoryChart);
        DetachFromParent(_systemDiskChart);
        _systemRealtimeCard ??= BuildSystemRealtimeCard();
        DetachFromParent(_systemRealtimeCard);

        var grid = new Grid { ColumnSpacing = 16, RowSpacing = 16 };
        grid.Children.Add(_systemCpuChart);
        grid.Children.Add(_systemMemoryChart);
        grid.Children.Add(_systemDiskChart);
        grid.Children.Add(_processMemoryChart);
        grid.Children.Add(_systemRealtimeCard);
        grid.SizeChanged += (_, e) => ArrangeSystemOverview(grid, e.NewSize.Width);
        ArrangeSystemOverview(grid, 900);
        return grid;
    }

    private static void ArrangeSystemOverview(Grid grid, double width)
    {
        var narrow = width > 0 && width < 760;
        grid.ColumnDefinitions.Clear();
        grid.RowDefinitions.Clear();
        grid.ColumnDefinitions.Add(new ColumnDefinition());

        if (narrow)
        {
            for (var index = 0; index < grid.Children.Count; index++)
            {
                grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
                if (grid.Children[index] is FrameworkElement element)
                {
                    Grid.SetColumn(element, 0);
                    Grid.SetRow(element, index);
                    Grid.SetColumnSpan(element, 1);
                }
            }

            return;
        }

        grid.ColumnDefinitions.Add(new ColumnDefinition());
        grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
        grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
        grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });

        if (grid.Children.Count >= 5)
        {
            var cpu = (FrameworkElement)grid.Children[0];
            var memory = (FrameworkElement)grid.Children[1];
            var disk = (FrameworkElement)grid.Children[2];
            var process = (FrameworkElement)grid.Children[3];
            var status = (FrameworkElement)grid.Children[4];

            Grid.SetColumn(cpu, 0);
            Grid.SetRow(cpu, 0);
            Grid.SetColumnSpan(cpu, 1);

            Grid.SetColumn(memory, 1);
            Grid.SetRow(memory, 0);
            Grid.SetColumnSpan(memory, 1);

            Grid.SetColumn(disk, 0);
            Grid.SetRow(disk, 1);
            Grid.SetColumnSpan(disk, 1);

            Grid.SetColumn(process, 1);
            Grid.SetRow(process, 1);
            Grid.SetColumnSpan(process, 1);

            Grid.SetColumn(status, 0);
            Grid.SetRow(status, 2);
            Grid.SetColumnSpan(status, 2);
        }
    }

    private Border BuildSystemRealtimeCard()
    {
        return ModernUi.Card(new StackPanel
        {
            Spacing = 12,
            Children =
            {
                new StackPanel
                {
                    Orientation = Orientation.Horizontal,
                    Spacing = 10,
                    Children =
                    {
                        ModernUi.IconTile("\uE9D9", 34, ModernUi.SurfaceAlt, ModernUi.Accent, 16),
                        ModernUi.Text(AppLocalizer.T("实时摘要", "Live summary"), 18, FontWeights.SemiBold)
                    }
                },
                BuildSystemMetricGrid()
            }
        }, new Thickness(16), radius: 8);
    }

    private UIElement BuildSystemMetricGrid()
    {
        var items = new[]
        {
            BuildSystemMetricLine(AppLocalizer.T("处理器", "Processor"), _processorStatus),
            BuildSystemMetricLine(AppLocalizer.T("系统内存", "System memory"), _memoryStatus),
            BuildSystemMetricLine(AppLocalizer.T("系统盘", "System drive"), _systemDriveStatus),
            BuildSystemMetricLine(AppLocalizer.T("应用 CPU", "App CPU"), _processCpuStatus),
            BuildSystemMetricLine(AppLocalizer.T("应用运行", "App uptime"), _processRuntimeStatus),
            BuildSystemMetricLine(AppLocalizer.T("线程 / 句柄", "Threads / handles"), _processThreadStatus),
            BuildSystemMetricLine(AppLocalizer.T("运行时", "Runtime"), _runtimeStatus),
            BuildSystemMetricLine(AppLocalizer.T("刷新时间", "Refresh time"), _lastRefreshStatus)
        };
        var grid = new Grid { ColumnSpacing = 12, RowSpacing = 8 };
        grid.ColumnDefinitions.Add(new ColumnDefinition());
        grid.ColumnDefinitions.Add(new ColumnDefinition());
        for (var row = 0; row < Math.Ceiling(items.Length / 2d); row++)
        {
            grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
        }

        for (var index = 0; index < items.Length; index++)
        {
            var element = items[index];
            Grid.SetColumn(element, index % 2);
            Grid.SetRow(element, index / 2);
            grid.Children.Add(element);
        }

        return grid;
    }

    private static FrameworkElement BuildSystemMetricLine(string title, TextBlock value)
    {
        value.Foreground = ModernUi.TextPrimary;
        value.TextTrimming = TextTrimming.CharacterEllipsis;
        value.MaxLines = 1;
        return new StackPanel
        {
            Spacing = 2,
            Children =
            {
                ModernUi.Text(title, 12, FontWeights.SemiBold, ModernUi.TextSecondary, maxLines: 1),
                value
            }
        };
    }

    private static UIElement BuildInfoLine(string title, string value)
    {
        var grid = new Grid { ColumnSpacing = 12 };
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(96) });
        grid.ColumnDefinitions.Add(new ColumnDefinition());
        grid.Children.Add(ModernUi.Text(title, 13, FontWeights.SemiBold, ModernUi.TextSecondary));
        var text = ModernUi.Text(value, 13, foreground: ModernUi.TextSecondary, maxLines: 1);
        Grid.SetColumn(text, 1);
        grid.Children.Add(text);
        return grid;
    }

    private async Task ReloadAsync()
    {
        _loaded = false;
        _settings = await _settingsService.LoadAsync();

        _themeSummary.Text = ThemeText(_settings.Theme);
        _windowBackdropSummary.Text = WindowBackdropText(_settings.WindowBackdrop);
        _topBarMaterialSummary.Text = TopBarMaterialText(_settings.TopBarMaterial);
        _settingsMaterialSummary.Text = SettingsPanelMaterialText(_settings.SettingsPanelMaterial);
        _fontSummary.Text = FontScaleText(_settings.FontSize);
        _languageSummary.Text = LanguageText(_settings.Language);
        _homeSummary.Text = HomePageModeText(_settings.HomePageMode);
        _closeSummary.Text = CloseText(_settings.CloseBehavior);
        _proxySummary.Text = ProxyText(_settings);
        _timeoutSummary.Text = AppLocalizer.T($"{_settings.ProxyTestTimeoutSeconds} 秒", $"{_settings.ProxyTestTimeoutSeconds} seconds");
        _retentionSummary.Text = LogRetentionText(_settings.LogRetentionCount);
        _toolDisplayModeSummary.Text = ToolDisplayModeText(_settings.ToolDisplayMode);
        _toolboxScopeSummary.Text = ToolboxScopeText(_settings.ToolboxDefaultScope);
        _pluginRootSummary.Text = CurrentPluginRoot();
        _feedbackContactSummary.Text = FeedbackContactText(_settings.FeedbackDefaultContact);
        _feedbackDefaultsSummary.Text = FeedbackDefaultsText(_settings.FeedbackDefaultType, _settings.FeedbackDefaultSeverity);
        _animationSwitch.IsOn = _settings.AnimationsEnabled;
        _restoreSwitch.IsOn = _settings.RestoreWindowPosition;
        _autoStartSwitch.IsOn = _settings.AutoStart || _startupService.IsEnabled();
        _proxySwitch.IsOn = _settings.ProxyEnabled;
        _updateSwitch.IsOn = _settings.UpdateNotification;
        _hardwareAccelerationSwitch.IsOn = _settings.HardwareAccelerationEnabled;
        _pluginSwitch.IsOn = _settings.PluginsEnabled;
        _toolboxCompactSwitch.IsOn = _settings.ToolboxCompactCards;
        _toolboxRecentFirstSwitch.IsOn = _settings.ToolboxShowRecentFirst;
        _hardwareLogoSwitch.IsOn = _settings.ShowHardwareBrandLogo;
        _riskConfirmationSwitch.IsOn = _settings.RequireRiskConfirmation;
        _feedbackLogsSwitch.IsOn = _settings.FeedbackIncludeTodayLogsByDefault;
        _feedbackToolStatusSwitch.IsOn = _settings.FeedbackIncludeToolStatusByDefault;
        _feedbackSystemSwitch.IsOn = _settings.FeedbackIncludeSystemSummaryByDefault;
        ApplySettingsPanelMaterialToCards();
        WireSwitches();
        ArrangeSections();
        _loaded = true;
    }

    private void WireSwitches()
    {
        _animationSwitch.Toggled -= AnimationSwitch_Toggled;
        _restoreSwitch.Toggled -= RestoreSwitch_Toggled;
        _autoStartSwitch.Toggled -= AutoStartSwitch_Toggled;
        _proxySwitch.Toggled -= ProxySwitch_Toggled;
        _updateSwitch.Toggled -= UpdateSwitch_Toggled;
        _hardwareAccelerationSwitch.Toggled -= HardwareAccelerationSwitch_Toggled;
        _pluginSwitch.Toggled -= PluginSwitch_Toggled;
        _toolboxCompactSwitch.Toggled -= ToolboxCompactSwitch_Toggled;
        _toolboxRecentFirstSwitch.Toggled -= ToolboxRecentFirstSwitch_Toggled;
        _hardwareLogoSwitch.Toggled -= HardwareLogoSwitch_Toggled;
        _riskConfirmationSwitch.Toggled -= RiskConfirmationSwitch_Toggled;
        _feedbackLogsSwitch.Toggled -= FeedbackLogsSwitch_Toggled;
        _feedbackToolStatusSwitch.Toggled -= FeedbackToolStatusSwitch_Toggled;
        _feedbackSystemSwitch.Toggled -= FeedbackSystemSwitch_Toggled;
        _animationSwitch.Toggled += AnimationSwitch_Toggled;
        _restoreSwitch.Toggled += RestoreSwitch_Toggled;
        _autoStartSwitch.Toggled += AutoStartSwitch_Toggled;
        _proxySwitch.Toggled += ProxySwitch_Toggled;
        _updateSwitch.Toggled += UpdateSwitch_Toggled;
        _hardwareAccelerationSwitch.Toggled += HardwareAccelerationSwitch_Toggled;
        _pluginSwitch.Toggled += PluginSwitch_Toggled;
        _toolboxCompactSwitch.Toggled += ToolboxCompactSwitch_Toggled;
        _toolboxRecentFirstSwitch.Toggled += ToolboxRecentFirstSwitch_Toggled;
        _hardwareLogoSwitch.Toggled += HardwareLogoSwitch_Toggled;
        _riskConfirmationSwitch.Toggled += RiskConfirmationSwitch_Toggled;
        _feedbackLogsSwitch.Toggled += FeedbackLogsSwitch_Toggled;
        _feedbackToolStatusSwitch.Toggled += FeedbackToolStatusSwitch_Toggled;
        _feedbackSystemSwitch.Toggled += FeedbackSystemSwitch_Toggled;
    }

    private void ArrangeSections()
    {
        if (_settingsLayoutGrid.Children.Count < 2)
        {
            return;
        }

        var controlCenter = (FrameworkElement)_settingsLayoutGrid.Children[0];
        var narrow = ActualWidth > 0 && ActualWidth < 960;
        _settingsNavStack.Orientation = narrow ? Orientation.Horizontal : Orientation.Vertical;
        _settingsNavScroller.HorizontalScrollBarVisibility = narrow ? ScrollBarVisibility.Auto : ScrollBarVisibility.Disabled;
        _settingsNavScroller.HorizontalScrollMode = narrow ? ScrollMode.Enabled : ScrollMode.Disabled;
        _settingsNavScroller.VerticalScrollBarVisibility = narrow ? ScrollBarVisibility.Disabled : ScrollBarVisibility.Auto;
        _settingsNavScroller.VerticalScrollMode = narrow ? ScrollMode.Disabled : ScrollMode.Enabled;
        _settingsNavScroller.MaxHeight = narrow ? 64 : ControlCenterVisibleNavHeight;
        _settingsNavPaddingHost.Padding = narrow ? new Thickness(0, 0, 0, 8) : new Thickness(0, 0, 12, 0);
        foreach (var button in _settingsPageButtons.Values)
        {
            button.Width = narrow ? 132 : double.NaN;
            button.MinWidth = narrow ? 118 : 0;
            button.Margin = narrow ? new Thickness(0, 0, 6, 0) : new Thickness(0);
        }

        _settingsLayoutGrid.ColumnDefinitions.Clear();
        _settingsLayoutGrid.RowDefinitions.Clear();
        if (narrow)
        {
            _settingsLayoutGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
            _settingsLayoutGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
            _settingsLayoutGrid.ColumnDefinitions.Add(new ColumnDefinition());
            controlCenter.Width = double.NaN;
            Grid.SetColumn(controlCenter, 0);
            Grid.SetRow(controlCenter, 0);
            Grid.SetColumn(_settingsPageHost, 0);
            Grid.SetRow(_settingsPageHost, 1);
            return;
        }

        _settingsLayoutGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(270) });
        _settingsLayoutGrid.ColumnDefinitions.Add(new ColumnDefinition());
        controlCenter.Width = 270;
        Grid.SetColumn(controlCenter, 0);
        Grid.SetRow(controlCenter, 0);
        Grid.SetColumn(_settingsPageHost, 1);
        Grid.SetRow(_settingsPageHost, 0);
    }

    private static void DetachFromParent(FrameworkElement element)
    {
        if (element.Parent is Panel parent)
        {
            parent.Children.Remove(element);
        }
    }

    private async Task ShowThemeDialogAsync()
    {
        var box = new ComboBox { MinWidth = 260 };
        AddComboItem(box, AppLocalizer.T("浅色", "Light"), "Light");
        AddComboItem(box, AppLocalizer.T("深色", "Dark"), "Dark");
        box.SelectedIndex = string.Equals(_settings.Theme, "Dark", StringComparison.OrdinalIgnoreCase) ? 1 : 0;
        if (await ShowPickerDialogAsync(AppLocalizer.T("主题模式", "Theme"), box) && box.SelectedItem is ComboBoxItem item)
        {
            var theme = (string)item.Tag;
            await _settingsService.UpdateAsync(settings => settings.Theme = theme);
            _settings.Theme = theme;
            _themeSummary.Text = ThemeText(theme);
            ApplySettingsPanelMaterialToCards();
            if (App.CurrentWindow is MainWindow mainWindow)
            {
                mainWindow.ApplyVisualSettings();
            }
            ToastService.Show(AppLocalizer.T("主题已应用", "Theme applied"), ToastKind.Success);
        }
    }

    private async Task ShowWindowBackdropDialogAsync()
    {
        var box = new ComboBox { MinWidth = 280 };
        AddComboItem(box, "Mica", "mica");
        AddComboItem(box, "Mica Alt", "micaAlt");
        AddComboItem(box, "Desktop Acrylic", "acrylic");
        AddComboItem(box, AppLocalizer.T("纯色背景", "Solid color"), "solid");
        SelectComboTag(box, _settings.WindowBackdrop, "mica");
        if (await ShowPickerDialogAsync(AppLocalizer.T("窗口背景材质", "Window backdrop"), box) && box.SelectedItem is ComboBoxItem item)
        {
            var value = (string)item.Tag;
            await _settingsService.UpdateAsync(settings => settings.WindowBackdrop = value);
            _settings.WindowBackdrop = value;
            _windowBackdropSummary.Text = WindowBackdropText(value);
            ApplySettingsPanelMaterialToCards();
            if (App.CurrentWindow is MainWindow mainWindow)
            {
                mainWindow.ApplyVisualSettings();
            }
            ToastService.Show(AppLocalizer.T("窗口背景材质已应用", "Window backdrop applied"), ToastKind.Success);
        }
    }

    private async Task ShowSettingsPanelMaterialDialogAsync()
    {
        var box = new ComboBox { MinWidth = 280 };
        AddComboItem(box, AppLocalizer.T("纯色内容", "Solid content"), "solid");
        AddComboItem(box, "Acrylic", "acrylic");
        AddComboItem(box, AppLocalizer.T("局部毛玻璃", "Local frosted glass"), "glass");
        SelectComboTag(box, _settings.SettingsPanelMaterial, "solid");
        if (await ShowPickerDialogAsync(AppLocalizer.T("内容区域材质", "Content material"), box) && box.SelectedItem is ComboBoxItem item)
        {
            var value = (string)item.Tag;
            await _settingsService.UpdateAsync(settings => settings.SettingsPanelMaterial = value);
            _settings.SettingsPanelMaterial = value;
            _settingsMaterialSummary.Text = SettingsPanelMaterialText(value);
            ApplySettingsPanelMaterialToCards();
            if (App.CurrentWindow is MainWindow mainWindow)
            {
                mainWindow.ApplyVisualSettings();
            }
            ToastService.Show(AppLocalizer.T("内容区域材质已应用", "Content material applied"), ToastKind.Success);
        }
    }

    private async Task ShowTopBarMaterialDialogAsync()
    {
        var box = new ComboBox { MinWidth = 280 };
        AddComboItem(box, AppLocalizer.T("继承窗口背景", "Inherit window backdrop"), "inherit");
        AddComboItem(box, "Mica", "mica");
        AddComboItem(box, "Acrylic", "acrylic");
        AddComboItem(box, AppLocalizer.T("局部毛玻璃", "Local frosted glass"), "glass");
        AddComboItem(box, AppLocalizer.T("纯色顶部栏", "Solid top bar"), "solid");
        SelectComboTag(box, _settings.TopBarMaterial, "inherit");
        if (await ShowPickerDialogAsync(AppLocalizer.T("顶部栏材质", "Top bar material"), box) && box.SelectedItem is ComboBoxItem item)
        {
            var value = (string)item.Tag;
            await _settingsService.UpdateAsync(settings => settings.TopBarMaterial = value);
            _settings.TopBarMaterial = value;
            _topBarMaterialSummary.Text = TopBarMaterialText(value);
            if (App.CurrentWindow is MainWindow mainWindow)
            {
                mainWindow.ApplyVisualSettings();
            }
            ToastService.Show(AppLocalizer.T("顶部栏材质已应用", "Top bar material applied"), ToastKind.Success);
        }
    }

    private async Task ShowFontDialogAsync()
    {
        var box = new ComboBox { MinWidth = 260 };
        AddComboItem(box, AppLocalizer.T("小", "Small"), 0.9);
        AddComboItem(box, AppLocalizer.T("标准", "Normal"), 1.0);
        AddComboItem(box, AppLocalizer.T("大", "Large"), 1.15);
        box.SelectedIndex = _settings.FontSize switch { < 0.95 => 0, > 1.08 => 2, _ => 1 };
        if (await ShowPickerDialogAsync(AppLocalizer.T("字体大小", "Font size"), box) && box.SelectedItem is ComboBoxItem item)
        {
            var scale = (double)item.Tag;
            await _settingsService.UpdateAsync(settings => settings.FontSize = scale);
            _settings.FontSize = scale;
            _fontSummary.Text = FontScaleText(scale);
            if (App.CurrentWindow is MainWindow mainWindow)
            {
                mainWindow.ApplyVisualSettings();
            }
            ToastService.Show(AppLocalizer.T("字体缩放已应用", "Font scale applied"), ToastKind.Success);
        }
    }

    private async Task ShowLanguageDialogAsync()
    {
        var box = new ComboBox { MinWidth = 260 };
        AddComboItem(box, "简体中文", "zh-CN");
        AddComboItem(box, "English", "en-US");
        box.SelectedIndex = string.Equals(_settings.Language, "en-US", StringComparison.OrdinalIgnoreCase) ? 1 : 0;
        if (await ShowPickerDialogAsync(AppLocalizer.T("界面语言", "Language"), box) && box.SelectedItem is ComboBoxItem item)
        {
            var language = (string)item.Tag;
            if (string.Equals(language, _settings.Language, StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            try
            {
                await _settingsService.UpdateAsync(settings => settings.Language = language);
                _settings.Language = language;
                _languageSummary.Text = LanguageText(language);
                await _logService.WriteAsync("Information", "settings", "界面语言已切换", $"language={language}");
                ToastService.Show(AppLocalizer.T("界面语言已应用", "Language applied"), ToastKind.Success);
            }
            catch (Exception exception)
            {
                CrashLog.Write(exception);
                ToastService.Show(AppLocalizer.T("语言切换失败", "Unable to switch language"), ToastKind.Error);
            }
        }
    }

    private async Task ShowHomePageModeDialogAsync()
    {
        var box = new ComboBox { MinWidth = 280 };
        AddComboItem(box, AppLocalizer.T("八大行星 - 太阳系", "Solar system planets"), "solar");
        AddComboItem(box, AppLocalizer.T("工具概览", "Tools overview"), "dashboard");
        box.SelectedIndex = string.Equals(_settings.HomePageMode, "dashboard", StringComparison.OrdinalIgnoreCase) ? 1 : 0;
        if (await ShowPickerDialogAsync(AppLocalizer.T("首页内容", "Home content"), box) && box.SelectedItem is ComboBoxItem item)
        {
            var mode = (string)item.Tag;
            await _settingsService.UpdateAsync(settings => settings.HomePageMode = mode);
            _settings.HomePageMode = mode;
            _homeSummary.Text = HomePageModeText(mode);
            ToastService.Show(AppLocalizer.T("首页内容已更新，返回首页后生效", "Home content updated. Return Home to see it."), ToastKind.Success);
        }
    }

    private async Task ShowToolDisplayModeDialogAsync()
    {
        var box = new ComboBox { MinWidth = 280 };
        AddComboItem(box, AppLocalizer.T("网格卡片", "Grid cards"), "grid");
        AddComboItem(box, AppLocalizer.T("紧凑列表", "Compact list"), "list");
        SelectComboTag(box, _settings.ToolDisplayMode, "grid");
        if (await ShowPickerDialogAsync(AppLocalizer.T("工具箱布局", "Toolbox layout"), box) && box.SelectedItem is ComboBoxItem item)
        {
            var mode = (string)item.Tag;
            await _settingsService.UpdateAsync(settings => settings.ToolDisplayMode = mode);
            _settings.ToolDisplayMode = mode;
            _toolDisplayModeSummary.Text = ToolDisplayModeText(mode);
            await _logService.WriteAsync("Information", "settings", "Toolbox layout changed", $"mode={mode}");
            ToastService.Show(AppLocalizer.T("工具箱布局已保存", "Toolbox layout saved"), ToastKind.Success);
        }
    }

    private async Task ShowToolboxScopeDialogAsync()
    {
        var box = new ComboBox { MinWidth = 300 };
        AddComboItem(box, AppLocalizer.T("全部工具", "All tools"), "all");
        AddComboItem(box, AppLocalizer.T("收藏", "Favorites"), "favorites");
        AddComboItem(box, AppLocalizer.T("最近使用", "Recent"), "recent");
        AddComboItem(box, AppLocalizer.T("外部工具", "External tools"), "external");
        AddComboItem(box, AppLocalizer.T("内置参考工具", "Built-in reference tools"), "builtin");
        AddComboItem(box, AppLocalizer.T("插件工具", "Plugin tools"), "plugin");
        AddComboItem(box, AppLocalizer.T("风险工具", "Risk tools"), "risk");
        SelectComboTag(box, _settings.ToolboxDefaultScope, "all");
        if (await ShowPickerDialogAsync(AppLocalizer.T("默认工具范围", "Default toolbox scope"), box) && box.SelectedItem is ComboBoxItem item)
        {
            var scope = (string)item.Tag;
            await _settingsService.UpdateAsync(settings => settings.ToolboxDefaultScope = scope);
            _settings.ToolboxDefaultScope = scope;
            _toolboxScopeSummary.Text = ToolboxScopeText(scope);
            await _logService.WriteAsync("Information", "settings", "Toolbox default scope changed", $"scope={scope}");
            ToastService.Show(AppLocalizer.T("默认工具范围已保存", "Default toolbox scope saved"), ToastKind.Success);
        }
    }

    private async Task ShowCloseBehaviorDialogAsync()
    {
        var box = new ComboBox { MinWidth = 260 };
        AddComboItem(box, AppLocalizer.T("每次询问", "Ask every time"), "ask");
        AddComboItem(box, AppLocalizer.T("最小化到托盘", "Minimize to tray"), "minimize_to_tray");
        AddComboItem(box, AppLocalizer.T("直接退出", "Exit directly"), "exit_directly");
        box.SelectedIndex = _settings.CloseBehavior switch
        {
            "minimize_to_tray" or "minimize_then_exit" => 1,
            "exit_directly" => 2,
            _ => 0
        };
        if (await ShowPickerDialogAsync(AppLocalizer.T("关闭按钮行为", "Close button"), box) && box.SelectedItem is ComboBoxItem item)
        {
            var behavior = (string)item.Tag;
            await _settingsService.UpdateAsync(settings => settings.CloseBehavior = behavior);
            _settings.CloseBehavior = behavior;
            _closeSummary.Text = CloseText(behavior);
            ToastService.Show(AppLocalizer.T("关闭行为已保存", "Close behavior saved"), ToastKind.Success);
        }
    }

    private async Task ShowProxyDialogAsync()
    {
        var mode = new ComboBox { Header = AppLocalizer.T("代理模式", "Proxy mode"), MinWidth = 260 };
        AddComboItem(mode, AppLocalizer.T("系统代理", "System proxy"), "system");
        AddComboItem(mode, AppLocalizer.T("不使用代理", "Direct"), "direct");
        AddComboItem(mode, AppLocalizer.T("自定义 HTTP 代理", "Custom HTTP proxy"), "custom");
        mode.SelectedIndex = _settings.ProxyMode switch { "direct" => 1, "custom" => 2, _ => 0 };
        var host = new TextBox { Header = AppLocalizer.T("代理主机", "Proxy host"), Text = _settings.ProxyHost, PlaceholderText = "127.0.0.1" };
        var port = new NumberBox { Header = AppLocalizer.T("端口", "Port"), Value = _settings.ProxyPort, Minimum = 1, Maximum = 65535, SpinButtonPlacementMode = NumberBoxSpinButtonPlacementMode.Compact };
        var panel = new StackPanel { Spacing = 12, Children = { mode, host, port } };
        if (await ShowPickerDialogAsync(AppLocalizer.T("网络与来源", "Network"), panel))
        {
            var selectedMode = mode.SelectedItem is ComboBoxItem item ? (string)item.Tag : "system";
            var selectedPort = (int)Math.Clamp(double.IsNaN(port.Value) ? 7890 : port.Value, 1, 65535);
            await _settingsService.UpdateAsync(settings =>
            {
                settings.ProxyMode = selectedMode;
                settings.ProxyHost = host.Text.Trim();
                settings.ProxyPort = selectedPort;
            });
            _settings.ProxyMode = selectedMode;
            _settings.ProxyHost = host.Text.Trim();
            _settings.ProxyPort = selectedPort;
            _proxySummary.Text = ProxyText(_settings);
            ToastService.Show(AppLocalizer.T("网络来源设置已保存", "Network settings saved"), ToastKind.Success);
        }
    }

    private async Task ShowTimeoutDialogAsync()
    {
        var box = new NumberBox
        {
            Header = AppLocalizer.T("测试超时（秒）", "Timeout seconds"),
            Value = _settings.ProxyTestTimeoutSeconds,
            Minimum = 3,
            Maximum = 60,
            SpinButtonPlacementMode = NumberBoxSpinButtonPlacementMode.Compact
        };
        if (await ShowPickerDialogAsync(AppLocalizer.T("测试超时", "Timeout"), box))
        {
            var value = (int)Math.Clamp(double.IsNaN(box.Value) ? 6 : box.Value, 3, 60);
            await _settingsService.UpdateAsync(settings => settings.ProxyTestTimeoutSeconds = value);
            _settings.ProxyTestTimeoutSeconds = value;
            _timeoutSummary.Text = AppLocalizer.T($"{value} 秒", $"{value} seconds");
            ToastService.Show(AppLocalizer.T("测试超时已保存", "Timeout saved"), ToastKind.Success);
        }
    }

    private async Task ShowLogRetentionDialogAsync()
    {
        var box = new NumberBox
        {
            Header = AppLocalizer.T("保留最近日志条数，0 表示全部保留", "Rows to keep. 0 means keep all."),
            Value = _settings.LogRetentionCount,
            Minimum = 0,
            Maximum = 10000,
            SpinButtonPlacementMode = NumberBoxSpinButtonPlacementMode.Compact
        };
        if (await ShowPickerDialogAsync(AppLocalizer.T("日志保留数量", "Log retention"), box))
        {
            var count = (int)Math.Clamp(double.IsNaN(box.Value) ? 0 : box.Value, 0, 10000);
            await _settingsService.UpdateAsync(settings => settings.LogRetentionCount = count);
            if (count > 0)
            {
                await _logService.CleanupAsync(count);
            }
            _settings.LogRetentionCount = count;
            _retentionSummary.Text = LogRetentionText(count);
            ToastService.Show(AppLocalizer.T("日志保留策略已应用", "Log retention applied"), ToastKind.Success);
        }
    }

    private async Task ShowFeedbackContactDialogAsync()
    {
        var box = new TextBox
        {
            Header = AppLocalizer.T("默认联系方式", "Default contact"),
            Text = _settings.FeedbackDefaultContact,
            PlaceholderText = AppLocalizer.T("可选：邮箱、QQ 或其他联系方式", "Optional: email, QQ, or another contact"),
            MinWidth = 320
        };
        if (await ShowPickerDialogAsync(AppLocalizer.T("反馈联系方式", "Feedback contact"), box))
        {
            var contact = box.Text.Trim();
            await _settingsService.UpdateAsync(settings => settings.FeedbackDefaultContact = contact);
            _settings.FeedbackDefaultContact = contact;
            _feedbackContactSummary.Text = FeedbackContactText(contact);
            ToastService.Show(AppLocalizer.T("反馈联系方式已保存", "Feedback contact saved"), ToastKind.Success);
        }
    }

    private async Task ShowFeedbackDefaultsDialogAsync()
    {
        var typeBox = new ComboBox
        {
            Header = AppLocalizer.T("默认类型", "Default type"),
            MinWidth = 280
        };
        AddComboItem(typeBox, AppLocalizer.T("问题", "Issue"), "issue");
        AddComboItem(typeBox, AppLocalizer.T("建议", "Suggestion"), "suggestion");
        AddComboItem(typeBox, AppLocalizer.T("界面反馈", "UI feedback"), "ui");
        AddComboItem(typeBox, AppLocalizer.T("其他", "Other"), "other");

        var severityBox = new ComboBox
        {
            Header = AppLocalizer.T("默认严重程度", "Default severity"),
            MinWidth = 280
        };
        AddComboItem(severityBox, AppLocalizer.T("普通", "Normal"), "normal");
        AddComboItem(severityBox, AppLocalizer.T("影响使用", "Affects usage"), "major");
        AddComboItem(severityBox, AppLocalizer.T("阻塞", "Blocking"), "blocking");

        SelectComboTag(typeBox, NormalizeFeedbackType(_settings.FeedbackDefaultType), "issue");
        SelectComboTag(severityBox, NormalizeFeedbackSeverity(_settings.FeedbackDefaultSeverity), "normal");

        var panel = new StackPanel { Spacing = 12, Children = { typeBox, severityBox } };
        if (await ShowPickerDialogAsync(AppLocalizer.T("反馈默认选项", "Feedback defaults"), panel))
        {
            var type = typeBox.SelectedItem is ComboBoxItem typeItem && typeItem.Tag is string typeTag ? typeTag : "issue";
            var severity = severityBox.SelectedItem is ComboBoxItem severityItem && severityItem.Tag is string severityTag ? severityTag : "normal";
            type = NormalizeFeedbackType(type);
            severity = NormalizeFeedbackSeverity(severity);
            await _settingsService.UpdateAsync(settings =>
            {
                settings.FeedbackDefaultType = type;
                settings.FeedbackDefaultSeverity = severity;
            });
            _settings.FeedbackDefaultType = type;
            _settings.FeedbackDefaultSeverity = severity;
            _feedbackDefaultsSummary.Text = FeedbackDefaultsText(type, severity);
            ToastService.Show(AppLocalizer.T("反馈默认选项已保存", "Feedback defaults saved"), ToastKind.Success);
        }
    }

    private async Task OpenFeedbackFolderAsync()
    {
        var folder = FeedbackPackageService.FeedbackPackagesRoot();
        Directory.CreateDirectory(folder);
        await Launcher.LaunchFolderPathAsync(folder);
    }

    private async Task ClearRemoteCacheAsync()
    {
        if (!await ConfirmAsync(AppLocalizer.T("清理远程配置缓存？", "Clear remote cache?"), AppLocalizer.T("这会删除本地缓存的远程配置，下次使用时会重新获取。", "Cached remote configuration will be deleted and fetched again next time.")))
        {
            return;
        }

        await _remoteMediaCatalogService.ClearCacheAsync();
        ToastService.Show(AppLocalizer.T("远程配置缓存已清理", "Remote cache cleared"), ToastKind.Success);
    }

    private async Task ClearRecentAsync()
    {
        if (!await ConfirmAsync(AppLocalizer.T("清理最近使用？", "Clear recent tools?"), AppLocalizer.T("首页最近访问工具记录会被清空。", "The Home recent tools list will be cleared.")))
        {
            return;
        }

        await _settingsService.UpdateAsync(settings => settings.RecentToolIds.Clear());
        _settings.RecentToolIds.Clear();
        ToastService.Show(AppLocalizer.T("最近使用记录已清理", "Recent tools cleared"), ToastKind.Success);
    }

    private async Task ResetRiskConfirmationsAsync()
    {
        if (!await ConfirmAsync(
            AppLocalizer.T("重置风险确认？", "Reset risk confirmations?"),
            AppLocalizer.T("已记住的风险工具确认将被清除。风险工具会在下次执行前重新询问。", "Remembered confirmations for risky tools will be cleared. Risk tools will ask again before execution.")))
        {
            await _logService.WriteAsync("Information", "risk", "Risk confirmation reset cancelled");
            return;
        }

        await _riskStore.ResetAsync();
        await _logService.WriteAsync("Information", "risk", "Risk confirmations reset from settings");
        ToastService.Show(AppLocalizer.T("风险确认已重置", "Risk confirmations reset"), ToastKind.Success);
    }

    private async Task RunProxyDiagnosticAsync()
    {
        var targets = new[]
        {
            ("国内 · 央视网", new Uri("https://www.cctv.com/")),
            ("国内 · 中国政府网", new Uri("https://www.gov.cn/")),
            ("国内 · 百度", new Uri("https://www.baidu.com/")),
            ("国际 · Microsoft", new Uri("https://www.microsoft.com/")),
            ("国际 · Cloudflare", new Uri("https://www.cloudflare.com/cdn-cgi/trace")),
            ("国际 · GitHub", new Uri("https://github.com/")),
            ("更新 · YMhut", new Uri("https://update.ymhut.cn/update-info.json"))
        };

        var resultPanel = new StackPanel { Spacing = 10 };
        foreach (var target in targets)
        {
            resultPanel.Children.Add(BuildDiagnosticCard(target.Item1, AppLocalizer.T("等待", "Waiting"), AppLocalizer.T("等待检测...", "Waiting for check..."), ok: true));
        }

        var dialog = new ContentDialog
        {
            Title = AppLocalizer.T("代理诊断", "Proxy diagnostics"),
            Content = new ScrollViewer
            {
                MaxHeight = 520,
                Content = new StackPanel
                {
                    Spacing = 12,
                    Children =
                    {
                        ModernUi.Text(AppLocalizer.T("正在检测国内、国际和更新服务连通性。结果只展示目标名称、HTTP 状态和延迟。", "Checking domestic, international, and update connectivity. Only target name, HTTP status, and latency are shown."), 14, foreground: ModernUi.TextSecondary),
                        resultPanel
                    }
                }
            },
            CloseButtonText = AppLocalizer.T("关闭", "Close"),
            XamlRoot = XamlRoot
        };
        var _ = dialog.ShowAsync();

        var parallelSummaries = new string[targets.Length];
        var parallelTasks = targets.Select(async (target, index) =>
        {
            resultPanel.Children[index] = BuildDiagnosticCard(target.Item1, AppLocalizer.T("检测中", "Checking"), AppLocalizer.T("正在请求目标...", "Requesting target..."), ok: true);
            try
            {
                using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(Math.Clamp(_settings.ProxyTestTimeoutSeconds, 3, 60)));
                var result = await _httpService.GetAsync(target.Item2, cts.Token);
                var ok = (int)result.StatusCode is >= 200 and < 400;
                resultPanel.Children[index] = BuildDiagnosticCard(
                    target.Item1,
                    ok ? AppLocalizer.T("正常", "OK") : AppLocalizer.T("异常", "Issue"),
                    $"HTTP {(int)result.StatusCode} / {result.Elapsed.TotalMilliseconds:0} ms",
                    ok);
                parallelSummaries[index] = $"{target.Item1}:{(int)result.StatusCode}/{result.Elapsed.TotalMilliseconds:0}ms";
            }
            catch (OperationCanceledException)
            {
                resultPanel.Children[index] = BuildDiagnosticCard(target.Item1, AppLocalizer.T("超时", "Timeout"), AppLocalizer.T("超过测试超时时间", "The request exceeded the timeout."), ok: false);
                parallelSummaries[index] = $"{target.Item1}:timeout";
            }
            catch
            {
                resultPanel.Children[index] = BuildDiagnosticCard(target.Item1, AppLocalizer.T("失败", "Failed"), AppLocalizer.T("连接失败", "Connection failed"), ok: false);
                parallelSummaries[index] = $"{target.Item1}:failed";
            }
        }).ToArray();
        await Task.WhenAll(parallelTasks);

        await _logService.WriteAsync("Information", "network", "代理诊断完成", string.Join("; ", parallelSummaries.Where(summary => !string.IsNullOrWhiteSpace(summary))));
        ToastService.Show(AppLocalizer.T("代理诊断完成", "Proxy diagnostic completed"), ToastKind.Success);
        return;
    }

#if false
        var summaries = new List<string>();
        for (var index = 0; index < targets.Length; index++)
        {
            var target = targets[index];
            try
            {
                var result = await _httpService.GetAsync(target.Item2);
                var ok = (int)result.StatusCode is >= 200 and < 400;
                resultPanel.Children[index] = BuildDiagnosticCard(
                    target.Item1,
                    ok ? AppLocalizer.T("正常", "OK") : AppLocalizer.T("异常", "Issue"),
                    $"HTTP {(int)result.StatusCode} · {result.Elapsed.TotalMilliseconds:0} ms",
                    ok);
                summaries.Add($"{target.Item1}:{(int)result.StatusCode}/{result.Elapsed.TotalMilliseconds:0}ms");
            }
            catch
            {
                resultPanel.Children[index] = BuildDiagnosticCard(target.Item1, AppLocalizer.T("失败", "Failed"), AppLocalizer.T("连接失败或超时", "Connection failed or timed out"), ok: false);
                summaries.Add($"{target.Item1}:failed");
            }
        }

        await _logService.WriteAsync("Information", "network", "代理诊断完成", string.Join("; ", summaries));
        ToastService.Show(AppLocalizer.T("代理诊断完成", "Proxy diagnostic completed"), ToastKind.Success);
    }

#endif
    private static Border BuildDiagnosticCard(string name, string status, string detail, bool ok)
    {
        var visualBrush = ok ? ModernUi.Success : ModernUi.Danger;
        if (status.Contains("等待", StringComparison.OrdinalIgnoreCase) || status.Contains("Waiting", StringComparison.OrdinalIgnoreCase))
        {
            visualBrush = ModernUi.TextSecondary;
        }
        else if (status.Contains("检测", StringComparison.OrdinalIgnoreCase) || status.Contains("Checking", StringComparison.OrdinalIgnoreCase))
        {
            visualBrush = ModernUi.Info;
        }
        else if (status.Contains("超时", StringComparison.OrdinalIgnoreCase) || status.Contains("Timeout", StringComparison.OrdinalIgnoreCase))
        {
            visualBrush = ModernUi.Bronze;
        }

        var grid = new Grid { ColumnSpacing = 12 };
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        grid.ColumnDefinitions.Add(new ColumnDefinition());
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        grid.Children.Add(new Border
        {
            Width = 9,
            Height = 9,
            CornerRadius = new CornerRadius(4.5),
            Background = visualBrush,
            VerticalAlignment = VerticalAlignment.Center
        });

        var text = new StackPanel
        {
            Spacing = 2,
            Children =
            {
                ModernUi.Text(name, 14, FontWeights.SemiBold, maxLines: 1),
                ModernUi.Text(detail, 12, foreground: ModernUi.TextSecondary, maxLines: 2)
            }
        };
        Grid.SetColumn(text, 1);
        grid.Children.Add(text);

        var badge = ModernUi.SmallBadge(status, visualBrush, ModernUi.SurfaceAlt);
        Grid.SetColumn(badge, 2);
        grid.Children.Add(badge);
        return ModernUi.Card(grid, new Thickness(10), radius: 8, background: ModernUi.SurfaceAlt);
    }

    private async void AnimationSwitch_Toggled(object sender, RoutedEventArgs e)
    {
        if (_loaded)
        {
            await _settingsService.UpdateAsync(settings => settings.AnimationsEnabled = _animationSwitch.IsOn);
        }

        UpdateSettingsNavScrollCue();
    }

    private async void RestoreSwitch_Toggled(object sender, RoutedEventArgs e)
    {
        if (_loaded)
        {
            await _settingsService.UpdateAsync(settings => settings.RestoreWindowPosition = _restoreSwitch.IsOn);
        }
    }

    private async void AutoStartSwitch_Toggled(object sender, RoutedEventArgs e)
    {
        if (!_loaded || _syncingAutoStartSwitch)
        {
            return;
        }

        try
        {
            _startupService.SetEnabled(_autoStartSwitch.IsOn);
            var enabled = _startupService.IsEnabled();
            SetAutoStartSwitch(enabled);
            await _settingsService.UpdateAsync(settings => settings.AutoStart = enabled);
            _settings.AutoStart = enabled;
            ToastService.Show(enabled ? AppLocalizer.T("开机自启已开启", "Startup enabled") : AppLocalizer.T("开机自启已关闭", "Startup disabled"), ToastKind.Success);
        }
        catch (Exception exception)
        {
            CrashLog.Write(exception);
            SetAutoStartSwitch(_settings.AutoStart);
            ToastService.Show(AppLocalizer.T("开机自启设置失败", "Startup setting failed"), ToastKind.Error);
        }
    }

    private void SetAutoStartSwitch(bool enabled)
    {
        _syncingAutoStartSwitch = true;
        try
        {
            _autoStartSwitch.IsOn = enabled;
        }
        finally
        {
            _syncingAutoStartSwitch = false;
        }
    }

    private async void ProxySwitch_Toggled(object sender, RoutedEventArgs e)
    {
        if (!_loaded)
        {
            return;
        }

        await _settingsService.UpdateAsync(settings => settings.ProxyEnabled = _proxySwitch.IsOn);
        _settings.ProxyEnabled = _proxySwitch.IsOn;
        ToastService.Show(_proxySwitch.IsOn ? AppLocalizer.T("代理已启用", "Proxy enabled") : AppLocalizer.T("代理已关闭", "Proxy disabled"), ToastKind.Success);
    }

    private async void UpdateSwitch_Toggled(object sender, RoutedEventArgs e)
    {
        if (_loaded)
        {
            await _settingsService.UpdateAsync(settings => settings.UpdateNotification = _updateSwitch.IsOn);
            _settings.UpdateNotification = _updateSwitch.IsOn;
        }
    }

    private async void HardwareAccelerationSwitch_Toggled(object sender, RoutedEventArgs e)
    {
        if (!_loaded)
        {
            return;
        }

        await _settingsService.UpdateAsync(settings => settings.HardwareAccelerationEnabled = _hardwareAccelerationSwitch.IsOn);
        _settings.HardwareAccelerationEnabled = _hardwareAccelerationSwitch.IsOn;
        ToastService.Show(
            _hardwareAccelerationSwitch.IsOn
                ? AppLocalizer.T("硬件加速已开启，重启后对新 WebView2 实例完全生效", "Hardware acceleration enabled. Restart to fully apply it to new WebView2 instances.")
                : AppLocalizer.T("硬件加速已关闭，重启后对新 WebView2 实例完全生效", "Hardware acceleration disabled. Restart to fully apply it to new WebView2 instances."),
            ToastKind.Success);
    }

    private async void PluginSwitch_Toggled(object sender, RoutedEventArgs e)
    {
        if (!_loaded)
        {
            return;
        }

        if (App.CurrentWindow is MainWindow mainWindow)
        {
            await mainWindow.SetPluginsEnabledAsync(_pluginSwitch.IsOn);
        }
        else
        {
            await _settingsService.UpdateAsync(settings => settings.PluginsEnabled = _pluginSwitch.IsOn);
        }
        _settings.PluginsEnabled = _pluginSwitch.IsOn;
        ToastService.Show(_pluginSwitch.IsOn ? "插件系统已开启" : "插件系统已关闭", ToastKind.Success);
    }

    private async void ToolboxCompactSwitch_Toggled(object sender, RoutedEventArgs e)
    {
        if (!_loaded)
        {
            return;
        }

        await _settingsService.UpdateAsync(settings => settings.ToolboxCompactCards = _toolboxCompactSwitch.IsOn);
        _settings.ToolboxCompactCards = _toolboxCompactSwitch.IsOn;
        await _logService.WriteAsync("Information", "settings", "Toolbox compact cards changed", $"enabled={_toolboxCompactSwitch.IsOn}");
    }

    private async void ToolboxRecentFirstSwitch_Toggled(object sender, RoutedEventArgs e)
    {
        if (!_loaded)
        {
            return;
        }

        await _settingsService.UpdateAsync(settings => settings.ToolboxShowRecentFirst = _toolboxRecentFirstSwitch.IsOn);
        _settings.ToolboxShowRecentFirst = _toolboxRecentFirstSwitch.IsOn;
        await _logService.WriteAsync("Information", "settings", "Toolbox recent-first changed", $"enabled={_toolboxRecentFirstSwitch.IsOn}");
    }

    private async void HardwareLogoSwitch_Toggled(object sender, RoutedEventArgs e)
    {
        if (!_loaded)
        {
            return;
        }

        await _settingsService.UpdateAsync(settings => settings.ShowHardwareBrandLogo = _hardwareLogoSwitch.IsOn);
        _settings.ShowHardwareBrandLogo = _hardwareLogoSwitch.IsOn;
        await _logService.WriteAsync("Information", "settings", "Hardware brand logo setting changed", $"enabled={_hardwareLogoSwitch.IsOn}");
    }

    private async void RiskConfirmationSwitch_Toggled(object sender, RoutedEventArgs e)
    {
        if (!_loaded)
        {
            return;
        }

        await _settingsService.UpdateAsync(settings => settings.RequireRiskConfirmation = _riskConfirmationSwitch.IsOn);
        _settings.RequireRiskConfirmation = _riskConfirmationSwitch.IsOn;
        await _logService.WriteAsync("Information", "settings", "Risk confirmation setting changed", $"enabled={_riskConfirmationSwitch.IsOn}");
        ToastService.Show(
            _riskConfirmationSwitch.IsOn
                ? AppLocalizer.T("风险确认已启用", "Risk confirmations enabled")
                : AppLocalizer.T("风险确认已关闭", "Risk confirmations disabled"),
            ToastKind.Success);
    }

    private async void FeedbackLogsSwitch_Toggled(object sender, RoutedEventArgs e)
    {
        if (!_loaded)
        {
            return;
        }

        await _settingsService.UpdateAsync(settings => settings.FeedbackIncludeTodayLogsByDefault = _feedbackLogsSwitch.IsOn);
        _settings.FeedbackIncludeTodayLogsByDefault = _feedbackLogsSwitch.IsOn;
    }

    private async void FeedbackToolStatusSwitch_Toggled(object sender, RoutedEventArgs e)
    {
        if (!_loaded)
        {
            return;
        }

        await _settingsService.UpdateAsync(settings => settings.FeedbackIncludeToolStatusByDefault = _feedbackToolStatusSwitch.IsOn);
        _settings.FeedbackIncludeToolStatusByDefault = _feedbackToolStatusSwitch.IsOn;
    }

    private async void FeedbackSystemSwitch_Toggled(object sender, RoutedEventArgs e)
    {
        if (!_loaded)
        {
            return;
        }

        await _settingsService.UpdateAsync(settings => settings.FeedbackIncludeSystemSummaryByDefault = _feedbackSystemSwitch.IsOn);
        _settings.FeedbackIncludeSystemSummaryByDefault = _feedbackSystemSwitch.IsOn;
    }

    private async Task ChoosePluginRootAsync()
    {
        if (App.CurrentWindow is null)
        {
            return;
        }

        var picker = new FolderPicker();
        InitializeWithWindow.Initialize(picker, WindowNative.GetWindowHandle(App.CurrentWindow));
        picker.FileTypeFilter.Add("*");
        var folder = await picker.PickSingleFolderAsync();
        if (folder is null)
        {
            return;
        }

        if (App.CurrentWindow is MainWindow mainWindow)
        {
            await mainWindow.SetPluginRootPathAsync(folder.Path);
        }
        else
        {
            await _settingsService.UpdateAsync(settings => settings.PluginRootPath = folder.Path);
        }
        _settings.PluginRootPath = folder.Path;
        _pluginRootSummary.Text = CurrentPluginRoot();
        Directory.CreateDirectory(CurrentPluginRoot());
        ToastService.Show("插件根目录已更新", ToastKind.Success);
    }

    private async Task ResetPluginRootAsync()
    {
        if (App.CurrentWindow is MainWindow mainWindow)
        {
            await mainWindow.SetPluginRootPathAsync(string.Empty);
        }
        else
        {
            await _settingsService.UpdateAsync(settings => settings.PluginRootPath = string.Empty);
        }
        _settings.PluginRootPath = string.Empty;
        Directory.CreateDirectory(CurrentPluginRoot());
        _pluginRootSummary.Text = CurrentPluginRoot();
        ToastService.Show("插件根目录已恢复默认", ToastKind.Success);
    }

    private async Task OpenPluginRootAsync()
    {
        var root = CurrentPluginRoot();
        Directory.CreateDirectory(root);
        await Launcher.LaunchFolderPathAsync(root);
    }

    private string CurrentPluginRoot()
    {
        return PluginRegistryService.ResolvePluginsRoot(_paths, _settings.PluginRootPath);
    }

    private async Task<bool> ShowPickerDialogAsync(string title, UIElement content)
    {
        var dialog = new ContentDialog
        {
            Title = title,
            Content = content,
            PrimaryButtonText = AppLocalizer.T("确定", "OK"),
            CloseButtonText = AppLocalizer.T("取消", "Cancel"),
            DefaultButton = ContentDialogButton.Primary,
            XamlRoot = XamlRoot
        };
        return await dialog.ShowAsync() == ContentDialogResult.Primary;
    }

    private async Task<bool> ConfirmAsync(string title, string content)
    {
        var dialog = new ContentDialog
        {
            Title = title,
            Content = content,
            PrimaryButtonText = AppLocalizer.T("确定", "OK"),
            CloseButtonText = AppLocalizer.T("取消", "Cancel"),
            DefaultButton = ContentDialogButton.Close,
            XamlRoot = XamlRoot
        };
        return await dialog.ShowAsync() == ContentDialogResult.Primary;
    }

    private static void AddComboItem(ComboBox box, string text, object tag)
    {
        box.Items.Add(new ComboBoxItem { Content = text, Tag = tag });
    }

    private static void SelectComboTag(ComboBox box, string value, string fallback)
    {
        foreach (var item in box.Items.OfType<ComboBoxItem>())
        {
            if (item.Tag is string tag && string.Equals(tag, value, StringComparison.OrdinalIgnoreCase))
            {
                box.SelectedItem = item;
                return;
            }
        }

        foreach (var item in box.Items.OfType<ComboBoxItem>())
        {
            if (item.Tag is string tag && string.Equals(tag, fallback, StringComparison.OrdinalIgnoreCase))
            {
                box.SelectedItem = item;
                return;
            }
        }
    }

    private static void SafeClearDirectory(string directory)
    {
        Directory.CreateDirectory(directory);
        foreach (var path in Directory.EnumerateFileSystemEntries(directory))
        {
            try
            {
                if (Directory.Exists(path))
                {
                    Directory.Delete(path, recursive: true);
                }
                else
                {
                    File.Delete(path);
                }
            }
            catch
            {
            }
        }
    }

    private static string ThemeText(string theme) => string.Equals(theme, "Dark", StringComparison.OrdinalIgnoreCase) ? AppLocalizer.T("深色", "Dark") : AppLocalizer.T("浅色", "Light");

    private static string WindowBackdropText(string value)
    {
        return value.Trim().ToLowerInvariant() switch
        {
            "solid" or "none" => AppLocalizer.T("纯色背景", "Solid color"),
            "micaalt" or "mica_alt" or "mica-alt" => "Mica Alt",
            "acrylic" or "desktopacrylic" or "desktop_acrylic" => "Desktop Acrylic",
            _ => "Mica"
        };
    }

    private static string SettingsPanelMaterialText(string value)
    {
        return value.Trim().ToLowerInvariant() switch
        {
            "acrylic" => "Acrylic",
            "glass" or "frosted" or "frosted_glass" => AppLocalizer.T("局部毛玻璃", "Local frosted glass"),
            _ => AppLocalizer.T("纯色内容", "Solid content")
        };
    }

    private static string TopBarMaterialText(string value)
    {
        return value.Trim().ToLowerInvariant() switch
        {
            "solid" or "none" => AppLocalizer.T("纯色顶部栏", "Solid top bar"),
            "mica" => "Mica",
            "acrylic" => "Acrylic",
            "glass" or "frosted" or "frosted_glass" => AppLocalizer.T("局部毛玻璃", "Local frosted glass"),
            _ => AppLocalizer.T("继承窗口背景", "Inherit window backdrop")
        };
    }

    private static string LanguageText(string language) => string.Equals(language, "en-US", StringComparison.OrdinalIgnoreCase) ? "English" : "简体中文";

    private static string FontScaleText(double scale) => scale switch
    {
        < 0.95 => AppLocalizer.T("小", "Small"),
        > 1.08 => AppLocalizer.T("大", "Large"),
        _ => AppLocalizer.T("标准", "Normal")
    };

    private static string HomePageModeText(string mode) => string.Equals(mode, "dashboard", StringComparison.OrdinalIgnoreCase)
        ? AppLocalizer.T("工具概览", "Tools overview")
        : AppLocalizer.T("八大行星 - 太阳系", "Solar system planets");

    private static string ToolDisplayModeText(string mode)
    {
        return string.Equals(mode, "list", StringComparison.OrdinalIgnoreCase)
            ? AppLocalizer.T("紧凑列表", "Compact list")
            : AppLocalizer.T("网格卡片", "Grid cards");
    }

    private static string ToolboxScopeText(string scope)
    {
        return scope.Trim().ToLowerInvariant() switch
        {
            "favorites" => AppLocalizer.T("收藏", "Favorites"),
            "recent" => AppLocalizer.T("最近使用", "Recent"),
            "external" => AppLocalizer.T("外部工具", "External tools"),
            "builtin" => AppLocalizer.T("内置工具", "Built-in tools"),
            "plugin" => AppLocalizer.T("插件工具", "Plugin tools"),
            "risk" => AppLocalizer.T("风险工具", "Risk tools"),
            _ => AppLocalizer.T("全部工具", "All tools")
        };
    }

    private static string CloseText(string behavior) => behavior switch
    {
        "exit_directly" => AppLocalizer.T("直接退出", "Exit directly"),
        "minimize_to_tray" or "minimize_then_exit" => AppLocalizer.T("最小化到托盘", "Minimize to tray"),
        _ => AppLocalizer.T("每次询问", "Ask every time")
    };

    private static string ProxyText(AppSettings settings)
    {
        return settings.ProxyMode switch
        {
            "direct" => AppLocalizer.T("不使用代理", "Direct"),
            "custom" => string.IsNullOrWhiteSpace(settings.ProxyHost) ? AppLocalizer.T("自定义代理未配置", "Custom proxy not configured") : $"{settings.ProxyHost}:{settings.ProxyPort}",
            _ => AppLocalizer.T("系统代理", "System proxy")
        };
    }

    private static string LogRetentionText(int count) => count <= 0
        ? AppLocalizer.T("全部保留", "Keep all")
        : AppLocalizer.T($"保留 {count} 条", $"Keep {count} rows");

    private static string FeedbackContactText(string contact) => string.IsNullOrWhiteSpace(contact)
        ? AppLocalizer.T("未设置", "Not set")
        : contact;

    private static string FeedbackDefaultsText(string type, string severity)
    {
        return $"{FeedbackTypeText(type)} / {FeedbackSeverityText(severity)}";
    }

    private static string FeedbackTypeText(string type) => NormalizeFeedbackType(type) switch
    {
        "suggestion" => AppLocalizer.T("建议", "Suggestion"),
        "ui" => AppLocalizer.T("界面反馈", "UI feedback"),
        "other" => AppLocalizer.T("其他", "Other"),
        _ => AppLocalizer.T("问题", "Issue")
    };

    private static string FeedbackSeverityText(string severity) => NormalizeFeedbackSeverity(severity) switch
    {
        "major" => AppLocalizer.T("影响使用", "Affects usage"),
        "blocking" => AppLocalizer.T("阻塞", "Blocking"),
        _ => AppLocalizer.T("普通", "Normal")
    };

    private static string NormalizeFeedbackType(string value)
    {
        return value.Trim().ToLowerInvariant() switch
        {
            "suggestion" => "suggestion",
            "ui" => "ui",
            "other" => "other",
            _ => "issue"
        };
    }

    private static string NormalizeFeedbackSeverity(string value)
    {
        return value.Trim().ToLowerInvariant() switch
        {
            "major" => "major",
            "blocking" => "blocking",
            _ => "normal"
        };
    }
}
