using System;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.UI.Text;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using Microsoft.Web.WebView2.Core;
using Windows.System;
using YMhut.Box.Core.Settings;
using YMhut.Box.Core.SolarSystem;
using YMhut.Box.Core.Tools;
using YMhut.Box.Core.Updates;
using YMhut.Box.WinUI.Services;

namespace YMhut.Box.WinUI.Views;

public sealed class HomePage : Page
{
    private const string GlobeHostName = "home-globe.ymhut.local";
    private static readonly TimeSpan PreciseEphemerisUiTimeout = TimeSpan.FromSeconds(20);

    private readonly ToolCatalog _catalog;
    private readonly Action<string?> _openToolbox;
    private readonly Action<IToolModule> _openTool;
    private readonly Action _openServiceStatus;
    private readonly Action _openLogs;
    private readonly WebView2EnvironmentFactory _webViewEnvironmentFactory = AppServices.GetRequiredService<WebView2EnvironmentFactory>();
    private readonly ISolarEphemerisService _solarEphemerisService = AppServices.GetRequiredService<ISolarEphemerisService>();
    private readonly ISettingsService _settingsService = AppServices.GetRequiredService<ISettingsService>();
    private readonly IAppInstallerUpdateService _updateService = AppServices.GetRequiredService<IAppInstallerUpdateService>();
    private readonly IAppVersionService _versionService = AppServices.GetRequiredService<IAppVersionService>();
    private readonly StackPanel _rootStack = new()
    {
        Padding = new Thickness(32, 28, 44, 32),
        Spacing = 22
    };
    private readonly Grid _welcomeGrid = new() { ColumnSpacing = 20, RowSpacing = 14 };
    private readonly Grid _dashboardGrid = new() { ColumnSpacing = 18, RowSpacing = 18 };
    private readonly TextBox _homeSearchBox = new()
    {
        PlaceholderText = AppLocalizer.T("搜索工具、分类或命令", "Search tools, categories, or commands"),
        BorderThickness = new Thickness(0),
        Background = ModernUi.Brush("#00FFFFFF"),
        FontSize = 16,
        VerticalAlignment = VerticalAlignment.Center
    };
    private readonly TextBlock _announcementTitle = ModernUi.Text(AppLocalizer.T("公告", "Announcement"), 14, FontWeights.SemiBold, ModernUi.TextSecondary, maxLines: 1);
    private readonly TextBlock _announcementText = ModernUi.Text(AppLocalizer.T("正在读取公告...", "Loading announcement..."), 15, FontWeights.SemiBold, ModernUi.TextPrimary, maxLines: 1);
    private readonly TextBlock _announcementMeta = ModernUi.Text(AppLocalizer.T("稍后显示", "Please wait"), 12, foreground: ModernUi.TextSecondary, maxLines: 1);
    private readonly Grid _globeHost = new();
    private readonly Border _globeFrame = new();
    private readonly WebView2 _globeView = new()
    {
        HorizontalAlignment = HorizontalAlignment.Stretch,
        VerticalAlignment = VerticalAlignment.Stretch
    };

    private bool _globeInitialized;
    private Task<SolarEphemerisPayload>? _ephemerisTask;
    private Task<SolarEphemerisPayload?>? _preciseEphemerisTask;
    private bool _solarSystemReady;
    private readonly string _ephemerisRequestId = Guid.NewGuid().ToString("N");
    private bool _initialEphemerisSent;
    private bool _preciseEphemerisStarted;
    private bool _ephemerisCompletionPosted;
    private RemoteUpdateInfo? _announcementInfo;
    private bool _announcementLoaded;

    public HomePage(
        ToolCatalog catalog,
        Action<string?> openToolbox,
        Action<IToolModule> openTool,
        Action openServiceStatus,
        Action? openLogs = null)
    {
        _catalog = catalog.Modules.Count == 0 ? new ToolCatalog() : catalog;
        _openToolbox = openToolbox;
        _openTool = openTool;
        _openServiceStatus = openServiceStatus;
        _openLogs = openLogs ?? (() => { });

        Background = ModernUi.AppBackground;
        Content = BuildContent();
        Loaded += HomePage_Loaded;
        SizeChanged += (_, _) => ArrangeHomeLayout();
        _homeSearchBox.KeyDown += HomeSearchBox_KeyDown;
    }

    private UIElement BuildContent()
    {
        _rootStack.Children.Clear();
        var dashboard = IsDashboardHome();
        if (dashboard)
        {
            _rootStack.Children.Add(BuildDashboardHero());
            _rootStack.Children.Add(BuildAnnouncementCard());
            _rootStack.Children.Add(BuildHomeSearchCard());
            _rootStack.Children.Add(BuildDashboardHomeSection());
        }
        else
        {
            _rootStack.Children.Add(BuildWelcomeSection(dashboard));
            _rootStack.Children.Add(BuildCivilizationGlobeSection());
        }

        return new ScrollViewer
        {
            VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
            HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled,
            Padding = new Thickness(0, 0, 8, 0),
            Content = _rootStack
        };
    }

    private Border BuildDashboardHero()
    {
        _welcomeGrid.Children.Clear();
        _welcomeGrid.ColumnDefinitions.Clear();
        _welcomeGrid.RowDefinitions.Clear();

        var updateButton = ModernUi.PillButton(AppLocalizer.T("更新日志", "Updates"), "\uE8D4", async () => await ShowUpdateNotesDialogAsync());
        updateButton.VerticalAlignment = VerticalAlignment.Center;

        _welcomeGrid.Children.Add(new StackPanel
        {
            Spacing = 8,
            Children =
            {
                ModernUi.Text(GetGreeting(), 30, FontWeights.SemiBold, maxLines: 2),
                ModernUi.Text(
                    AppLocalizer.T(
                        "清爽的工具工作台，公告、搜索、最近使用和运行状态都集中在这里。",
                        "A clean tools dashboard with announcements, search, recent entries, and runtime status in one place."),
                    16,
                    foreground: ModernUi.TextSecondary,
                    maxLines: 2)
            }
        });

        var dashboardStats = new StackPanel
        {
            Orientation = Orientation.Horizontal,
            Spacing = 10,
            VerticalAlignment = VerticalAlignment.Center,
            Children =
            {
                ModernUi.Chip(AppLocalizer.T("工具", "Tools"), $"{_catalog.Modules.Count}", "\uE90F", selected: true),
                ModernUi.Chip(AppLocalizer.T("分类", "Categories"), $"{_catalog.Modules.Select(module => module.Metadata.Category).Distinct().Count()}", "\uE8EC"),
                ModernUi.Chip(AppLocalizer.T("本地可用", "Local"), $"{_catalog.Modules.Count(module => module.Metadata.OfflineCapable)}", "\uE8D4"),
                updateButton
            }
        };
        Grid.SetColumn(dashboardStats, 1);
        _welcomeGrid.Children.Add(dashboardStats);

        var dashboardCard = ModernUi.Card(_welcomeGrid, new Thickness(24), radius: 8);
        dashboardCard.SizeChanged += (_, _) => ArrangeHomeLayout();
        return dashboardCard;
    }

    private UIElement BuildAnnouncementCard()
    {
        var grid = new Grid { ColumnSpacing = 14 };
        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("\uE789", 38, ModernUi.AccentSoft, ModernUi.Accent, 17));

        var text = new StackPanel
        {
            Spacing = 2,
            VerticalAlignment = VerticalAlignment.Center,
            Children =
            {
                _announcementTitle,
                _announcementText,
                _announcementMeta
            }
        };
        Grid.SetColumn(text, 1);
        grid.Children.Add(text);

        var action = new StackPanel
        {
            Orientation = Orientation.Horizontal,
            Spacing = 6,
            VerticalAlignment = VerticalAlignment.Center,
            Children =
            {
                ModernUi.Text(AppLocalizer.T("查看完整公告", "View full"), 13, FontWeights.SemiBold, ModernUi.Accent, maxLines: 1),
                new FontIcon { Glyph = "\uE8A7", FontSize = 13, Foreground = ModernUi.Accent }
            }
        };
        Grid.SetColumn(action, 2);
        grid.Children.Add(action);

        var button = new Button
        {
            HorizontalAlignment = HorizontalAlignment.Stretch,
            HorizontalContentAlignment = HorizontalAlignment.Stretch,
            Padding = new Thickness(0),
            CornerRadius = new CornerRadius(8),
            Background = ModernUi.Surface,
            BorderBrush = ModernUi.Stroke,
            BorderThickness = new Thickness(1),
            Content = new Border { Padding = new Thickness(16, 12, 16, 12), Child = grid }
        };
        button.Click += async (_, _) => await ShowAnnouncementDialogAsync();
        ToolTipService.SetToolTip(button, AppLocalizer.T("查看完整公告", "View full announcement"));
        return button;
    }

    private UIElement BuildHomeSearchCard()
    {
        var searchButton = ModernUi.PillButton(AppLocalizer.T("搜索", "Search"), "\uE721", RunHomeSearch, primary: true);
        searchButton.MinWidth = 108;

        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 FontIcon { Glyph = "\uE721", FontSize = 19, Foreground = ModernUi.TextSecondary, VerticalAlignment = VerticalAlignment.Center });
        Grid.SetColumn(_homeSearchBox, 1);
        grid.Children.Add(_homeSearchBox);
        Grid.SetColumn(searchButton, 2);
        grid.Children.Add(searchButton);

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

    private void HomeSearchBox_KeyDown(object sender, KeyRoutedEventArgs e)
    {
        if (e.Key == VirtualKey.Enter)
        {
            RunHomeSearch();
            e.Handled = true;
        }
    }

    private void RunHomeSearch()
    {
        var query = _homeSearchBox.Text?.Trim();
        _openToolbox(string.IsNullOrWhiteSpace(query) ? null : query);
    }

    private async Task LoadAnnouncementAsync()
    {
        if (_announcementLoaded)
        {
            return;
        }

        _announcementLoaded = true;
        try
        {
            _announcementInfo = await _updateService.GetUpdateInfoAsync();
            ApplyAnnouncement(_announcementInfo);
        }
        catch (Exception exception)
        {
            _announcementTitle.Text = AppLocalizer.T("公告", "Announcement");
            _announcementText.Text = AppLocalizer.T("公告加载失败，点击查看本地提示。", "Announcement failed to load. Click for local notes.");
            _announcementMeta.Text = AppLocalizer.SanitizeSensitiveText(exception.Message, 120);
        }
    }

    private void ApplyAnnouncement(RemoteUpdateInfo? info)
    {
        if (info is null)
        {
            _announcementTitle.Text = AppLocalizer.T("公告", "Announcement");
            _announcementText.Text = AppLocalizer.T("欢迎使用 YMhut Box，新版首页已切换为清爽工作台。", "Welcome to YMhut Box. The home page now opens as a clean dashboard.");
            _announcementMeta.Text = AppLocalizer.T("本地公告", "Local announcement");
            return;
        }

        var current = _versionService.GetCurrent().Version;
        var relation = info.CompareToCurrent(current);
        _announcementTitle.Text = AnnouncementTitle(info, relation);
        _announcementText.Text = AnnouncementSummary(info, current, relation);
        _announcementMeta.Text = AnnouncementMeta(info, current, relation, includeTime: false);
    }

    private async Task ShowAnnouncementDialogAsync()
    {
        await EnsureAnnouncementLoadedAsync();
        var info = _announcementInfo;
        var current = _versionService.GetCurrent().Version;
        var relation = info is null ? 0 : info.CompareToCurrent(current);
        var title = info is null
            ? AppLocalizer.T("完整公告", "Full announcement")
            : AnnouncementTitle(info, relation);
        var content = info is null
            ? AppLocalizer.T("欢迎使用 YMhut Box。新版 WinUI 首页已对齐旧版的公告、搜索和工具工作台体验。", "Welcome to YMhut Box. The WinUI home page now aligns with the classic announcement, search, and dashboard experience.")
            : CombineAnnouncement(info, current, relation);
        var meta = info is null
            ? AppLocalizer.T("本地公告", "Local announcement")
            : AnnouncementMeta(info, current, relation, includeTime: true);

        var dialog = new ContentDialog
        {
            Title = title,
            Content = ModernUi.GutterScroll(MarkdownRenderHelper.Render(content, meta), 520),
            CloseButtonText = AppLocalizer.T("关闭", "Close"),
            XamlRoot = XamlRoot
        };
        await dialog.ShowAsync();
    }

    private async Task ShowUpdateNotesDialogAsync()
    {
        await EnsureAnnouncementLoadedAsync();
        var notes = _announcementInfo is null || string.IsNullOrWhiteSpace(_announcementInfo.DisplayReleaseNotes)
            ? AppLocalizer.T("暂无远程更新日志。", "No remote update notes are available.")
            : _announcementInfo.DisplayReleaseNotes;
        var dialog = new ContentDialog
        {
            Title = AppLocalizer.T("更新日志", "Update notes"),
            Content = ModernUi.GutterScroll(
                MarkdownRenderHelper.Render(
                    notes,
                    _announcementInfo is null ? null : AnnouncementMeta(
                        _announcementInfo,
                        _versionService.GetCurrent().Version,
                        _announcementInfo.CompareToCurrent(_versionService.GetCurrent().Version),
                        includeTime: false)),
                560),
            CloseButtonText = AppLocalizer.T("关闭", "Close"),
            XamlRoot = XamlRoot
        };
        await dialog.ShowAsync();
    }

    private async Task EnsureAnnouncementLoadedAsync()
    {
        if (!_announcementLoaded)
        {
            await LoadAnnouncementAsync();
        }
    }

    private static string FirstAnnouncementLine(RemoteUpdateInfo info)
    {
        var value = FirstNonEmpty(info.DisplayMessage, info.DisplayReleaseNotes, AppLocalizer.T("点击查看完整公告。", "Click to view the full announcement."));
        return value.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries).FirstOrDefault()?.Trim() ?? value.Trim();
    }

    private static string CombineAnnouncement(RemoteUpdateInfo info, string currentVersion, int relation)
    {
        return string.Join(Environment.NewLine + Environment.NewLine, new[]
        {
            relation > 0 ? null : AnnouncementSummary(info, currentVersion, relation),
            info.DisplayMessage,
            info.DisplayReleaseNotes,
            info.PublishedAt is null ? null : AppLocalizer.T($"发布时间：{info.PublishedAt.Value:yyyy-MM-dd HH:mm}", $"Published: {info.PublishedAt.Value:yyyy-MM-dd HH:mm}")
        }.Where(value => !string.IsNullOrWhiteSpace(value)));
    }

    private static string AnnouncementTitle(RemoteUpdateInfo info, int relation)
    {
        if (relation > 0)
        {
            return string.IsNullOrWhiteSpace(info.Title)
                ? AppLocalizer.T("发现新版本", "New version available")
                : info.Title;
        }

        return relation == 0
            ? AppLocalizer.T("当前版本公告", "Current version announcement")
            : AppLocalizer.T("公告", "Announcement");
    }

    private static string AnnouncementSummary(RemoteUpdateInfo info, string currentVersion, int relation)
    {
        return relation switch
        {
            > 0 => FirstAnnouncementLine(info),
            0 => AppLocalizer.T(
                $"当前客户端版本 {currentVersion} 与服务端版本 {info.DisplayVersion} 一致。",
                $"Current client version {currentVersion} matches server version {info.DisplayVersion}."),
            _ => AppLocalizer.T(
                $"当前客户端版本 {currentVersion} 高于服务端公告版本 {info.DisplayVersion}。",
                $"Current client version {currentVersion} is newer than server announcement version {info.DisplayVersion}.")
        };
    }

    private static string AnnouncementMeta(RemoteUpdateInfo info, string currentVersion, int relation, bool includeTime)
    {
        var status = relation switch
        {
            > 0 => AppLocalizer.T("可更新", "Update available"),
            0 => AppLocalizer.T("当前版本", "Current version"),
            _ => AppLocalizer.T("本地版本较新", "Local version newer")
        };
        var version = AppLocalizer.T($"服务端 {info.DisplayVersion} / 本地 {currentVersion}", $"Server {info.DisplayVersion} / Local {currentVersion}");
        var published = info.PublishedAt is null
            ? string.Empty
            : includeTime
                ? $" · {info.PublishedAt.Value:yyyy-MM-dd HH:mm}"
                : $" · {info.PublishedAt.Value:yyyy-MM-dd}";
        return $"{status} · {version}{published}";
    }

    private static string FirstNonEmpty(params string?[] values)
    {
        return values.FirstOrDefault(value => !string.IsNullOrWhiteSpace(value)) ?? string.Empty;
    }

    private Border BuildWelcomeSection(bool dashboard)
    {
        _welcomeGrid.Children.Clear();
        _welcomeGrid.ColumnDefinitions.Clear();
        _welcomeGrid.RowDefinitions.Clear();

        if (dashboard)
        {
            _welcomeGrid.Children.Add(new StackPanel
            {
                Spacing = 8,
                Children =
                {
                    ModernUi.Text(GetGreeting(), 30, FontWeights.SemiBold, maxLines: 2),
                    ModernUi.Text(
                        AppLocalizer.T(
                            "工具概览首页会集中显示最近访问、分类入口和运行状态；可在设置中随时切回八大行星太阳系。",
                            "The tools overview keeps recent tools, category entry points, and runtime status together. You can switch back to the solar system in Settings."),
                        16,
                        foreground: ModernUi.TextSecondary)
                }
            });

            var dashboardStats = new StackPanel
            {
                Orientation = Orientation.Horizontal,
                Spacing = 10,
                VerticalAlignment = VerticalAlignment.Center,
                Children =
                {
                    ModernUi.Chip(AppLocalizer.T("工具", "Tools"), $"{_catalog.Modules.Count}", "\uE90F", selected: true),
                    ModernUi.Chip(AppLocalizer.T("分类", "Categories"), $"{_catalog.Modules.Select(module => module.Metadata.Category).Distinct().Count()}", "\uE8EC"),
                    ModernUi.Chip(AppLocalizer.T("本地可用", "Local"), $"{_catalog.Modules.Count(module => module.Metadata.OfflineCapable)}", "\uE8D4")
                }
            };
            Grid.SetColumn(dashboardStats, 1);
            _welcomeGrid.Children.Add(dashboardStats);

            var dashboardCard = ModernUi.Card(_welcomeGrid, new Thickness(24), radius: 8);
            dashboardCard.SizeChanged += (_, _) => ArrangeHomeLayout();
            return dashboardCard;
        }

        _welcomeGrid.Children.Add(new StackPanel
        {
            Spacing = 8,
            Children =
            {
                ModernUi.Text(GetGreeting(), 30, FontWeights.SemiBold, maxLines: 2),
                ModernUi.Text(
                    AppLocalizer.T(
                        "首页底部已切换为八大行星-太阳系，可点击行星查看资料，点击地球进入世界文明古国。",
                        "The home page now highlights an interactive solar system. Select planets for details or Earth for ancient civilizations."),
                    16,
                    foreground: ModernUi.TextSecondary)
            }
        });

        var stats = new StackPanel
        {
            Orientation = Orientation.Horizontal,
            Spacing = 10,
            VerticalAlignment = VerticalAlignment.Center,
            Children =
            {
                ModernUi.Chip(AppLocalizer.T("工具", "Tools"), $"{_catalog.Modules.Count}", "\uE90F", selected: true),
                ModernUi.Chip(AppLocalizer.T("分类", "Categories"), $"{_catalog.Modules.Select(module => module.Metadata.Category).Distinct().Count()}", "\uE8EC"),
                ModernUi.Chip(AppLocalizer.T("本地可用", "Local"), $"{_catalog.Modules.Count(module => module.Metadata.OfflineCapable)}", "\uE8D4")
            }
        };
        Grid.SetColumn(stats, 1);
        _welcomeGrid.Children.Add(stats);

        var card = ModernUi.Card(_welcomeGrid, new Thickness(24), radius: 8);
        card.SizeChanged += (_, _) => ArrangeHomeLayout();
        return card;
    }

    private UIElement BuildCivilizationGlobeSection()
    {
        _globeHost.Children.Clear();
        _globeHost.Background = ModernUi.Brush("#05070A");
        _globeHost.Children.Add(_globeView);

        _globeFrame.Padding = new Thickness(0);
        _globeFrame.MinHeight = 560;
        _globeFrame.Height = 620;
        _globeFrame.CornerRadius = new CornerRadius(8);
        _globeFrame.Background = ModernUi.Brush("#05070A");
        _globeFrame.BorderBrush = ModernUi.Stroke;
        _globeFrame.BorderThickness = new Thickness(1);
        _globeFrame.Child = _globeHost;

        return _globeFrame;
    }

    private UIElement BuildDashboardHomeSection()
    {
        _dashboardGrid.Children.Clear();
        _dashboardGrid.ColumnDefinitions.Clear();
        _dashboardGrid.RowDefinitions.Clear();

        _dashboardGrid.Children.Add(BuildRecentToolsCard());
        _dashboardGrid.Children.Add(BuildStartCard());
        _dashboardGrid.Children.Add(BuildRunStatusCard());
        ArrangeDashboardLayout();
        return _dashboardGrid;
    }

    private Border BuildRecentToolsCard()
    {
        var list = new StackPanel { Spacing = 8 };
        var modules = ResolveHomeTools().ToArray();
        foreach (var module in modules)
        {
            list.Children.Add(BuildToolShortcutButton(module));
        }

        if (modules.Length == 0)
        {
            list.Children.Add(ModernUi.Text(
                AppLocalizer.T("暂无最近访问工具。打开工具箱后，这里会自动记录常用入口。", "No recent tools yet. Open Toolbox and your frequent entries will appear here."),
                13,
                foreground: ModernUi.TextSecondary));
        }

        return ModernUi.Card(new StackPanel
        {
            Spacing = 14,
            Children =
            {
                BuildDashboardHeader(
                    AppLocalizer.T("最近访问", "Recent tools"),
                    AppLocalizer.T("常用工具会保留在这里，方便直接继续。", "Your frequent tools stay here for quick continuation."),
                    ModernUi.PillButton(AppLocalizer.T("工具箱", "Toolbox"), "\uE8A7", () => _openToolbox(null))),
                list
            }
        }, new Thickness(18), radius: 8);
    }

    private Border BuildStartCard()
    {
        var categories = new StackPanel { Spacing = 8 };
        foreach (var category in new[]
        {
            ToolCategory.Dev,
            ToolCategory.Network,
            ToolCategory.Security,
            ToolCategory.Data,
            ToolCategory.Calculator,
            ToolCategory.Text
        })
        {
            categories.Children.Add(BuildCategoryShortcutButton(category));
        }

        return ModernUi.Card(new StackPanel
        {
            Spacing = 14,
            Children =
            {
                BuildDashboardHeader(
                    AppLocalizer.T("开始使用", "Start"),
                    AppLocalizer.T("按任务类型进入工具箱。", "Jump into Toolbox by task type."),
                    null),
                categories
            }
        }, new Thickness(18), radius: 8);
    }

    private Border BuildRunStatusCard()
    {
        return ModernUi.Card(new StackPanel
        {
            Spacing = 14,
            Children =
            {
                BuildDashboardHeader(
                    AppLocalizer.T("运行状态", "Runtime status"),
                    AppLocalizer.T("本地运行、网络和渲染能力摘要。", "Local runtime, network, and rendering summary."),
                    ModernUi.PillButton(AppLocalizer.T("查看", "Open"), "\uE8A7", _openServiceStatus)),
                BuildStatusLine(AppLocalizer.T("首页模式", "Home mode"), AppLocalizer.T("工具概览", "Tools overview"), "\uE80F"),
                BuildStatusLine(AppLocalizer.T("太阳系首页", "Solar system home"), AppLocalizer.T("已保留，可在设置切回", "Preserved; switch back in Settings"), "\uE9D9"),
                BuildStatusLine(AppLocalizer.T("GPU / WebView2", "GPU / WebView2"), _settingsService.Current.HardwareAccelerationEnabled ? AppLocalizer.T("优先硬件加速", "Hardware preferred") : AppLocalizer.T("硬件加速关闭", "Hardware acceleration off"), "\uE7F8"),
                BuildStatusLine(AppLocalizer.T("本地工具", "Local tools"), $"{_catalog.Modules.Count(module => module.Metadata.OfflineCapable)} / {_catalog.Modules.Count}", "\uE8D4")
            }
        }, new Thickness(18), radius: 8);
    }

    private Grid BuildDashboardHeader(string title, string subtitle, FrameworkElement? action)
    {
        var header = new Grid { ColumnSpacing = 12 };
        header.ColumnDefinitions.Add(new ColumnDefinition());
        if (action is not null)
        {
            header.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        }

        header.Children.Add(new StackPanel
        {
            Spacing = 3,
            Children =
            {
                ModernUi.Text(title, 20, FontWeights.SemiBold, maxLines: 1),
                ModernUi.Text(subtitle, 13, foreground: ModernUi.TextSecondary, maxLines: 2)
            }
        });

        if (action is not null)
        {
            Grid.SetColumn(action, 1);
            header.Children.Add(action);
        }

        return header;
    }

    private Button BuildToolShortcutButton(IToolModule module)
    {
        var grid = new Grid { ColumnSpacing = 12, MinHeight = 54 };
        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(module.Metadata.IconGlyph, 40, ModernUi.Surface, ModernUi.Accent, 18));

        var title = new StackPanel
        {
            Spacing = 1,
            VerticalAlignment = VerticalAlignment.Center,
            Children =
            {
                ModernUi.Text(ToolText.Name(module), 15, FontWeights.SemiBold, maxLines: 1),
                ModernUi.Text($"{ToolText.CategoryLabel(module.Metadata.Category)} · {ModernUi.Ellipsize(ToolText.Description(module), 54)}", 12, foreground: ModernUi.TextSecondary, maxLines: 1)
            }
        };
        Grid.SetColumn(title, 1);
        grid.Children.Add(title);

        var arrow = new FontIcon { Glyph = "\uE8A7", FontSize = 13, Foreground = ModernUi.TextSecondary, VerticalAlignment = VerticalAlignment.Center };
        Grid.SetColumn(arrow, 2);
        grid.Children.Add(arrow);

        var button = new Button
        {
            HorizontalAlignment = HorizontalAlignment.Stretch,
            HorizontalContentAlignment = HorizontalAlignment.Stretch,
            Padding = new Thickness(10),
            CornerRadius = new CornerRadius(8),
            Background = ModernUi.SurfaceAlt,
            BorderBrush = ModernUi.Stroke,
            BorderThickness = new Thickness(1),
            Content = grid
        };
        ToolTipService.SetToolTip(button, $"{ToolText.Name(module)}\n{ToolText.Description(module)}");
        button.Click += (_, _) => _openTool(module);
        return button;
    }

    private Button BuildCategoryShortcutButton(ToolCategory category)
    {
        var count = _catalog.Modules.Count(module => module.Metadata.Category == category);
        var label = ToolText.CategoryLabel(category);
        var grid = new Grid { ColumnSpacing = 12, MinHeight = 44 };
        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(ToolText.CategoryGlyph(category), 36, ModernUi.Surface, ModernUi.Accent, 16));

        var text = new StackPanel
        {
            Spacing = 1,
            VerticalAlignment = VerticalAlignment.Center,
            Children =
            {
                ModernUi.Text(label, 14, FontWeights.SemiBold, maxLines: 1),
                ModernUi.Text(ToolText.CategoryHint(category), 12, foreground: ModernUi.TextSecondary, maxLines: 1)
            }
        };
        Grid.SetColumn(text, 1);
        grid.Children.Add(text);

        var badge = ModernUi.SmallBadge(count.ToString());
        badge.VerticalAlignment = VerticalAlignment.Center;
        Grid.SetColumn(badge, 2);
        grid.Children.Add(badge);

        var button = new Button
        {
            HorizontalAlignment = HorizontalAlignment.Stretch,
            HorizontalContentAlignment = HorizontalAlignment.Stretch,
            Padding = new Thickness(10, 8, 10, 8),
            CornerRadius = new CornerRadius(8),
            Background = ModernUi.SurfaceAlt,
            BorderBrush = ModernUi.Stroke,
            BorderThickness = new Thickness(1),
            Content = grid
        };
        ToolTipService.SetToolTip(button, label);
        button.Click += (_, _) => _openToolbox(label);
        return button;
    }

    private UIElement BuildStatusLine(string label, string value, string glyph)
    {
        var grid = new Grid { ColumnSpacing = 10, MinHeight = 38 };
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        grid.ColumnDefinitions.Add(new ColumnDefinition());
        grid.Children.Add(ModernUi.IconTile(glyph, 32, ModernUi.SurfaceAlt, ModernUi.TextSecondary, 14));

        var text = new StackPanel
        {
            Spacing = 1,
            VerticalAlignment = VerticalAlignment.Center,
            Children =
            {
                ModernUi.Text(label, 13, FontWeights.SemiBold, maxLines: 1),
                ModernUi.Text(value, 12, foreground: ModernUi.TextSecondary, maxLines: 1)
            }
        };
        Grid.SetColumn(text, 1);
        grid.Children.Add(text);
        return grid;
    }

    private IEnumerable<IToolModule> ResolveHomeTools()
    {
        var selected = new List<IToolModule>();
        foreach (var id in _settingsService.Current.RecentToolIds)
        {
            AddHomeTool(selected, _catalog.GetById(id));
        }

        foreach (var id in new[]
        {
            "safe_browser",
            "json_formatter",
            "compression_codec",
            "html_js_playground",
            "movie_box_office",
            "history_today",
            "url_inspector",
            "calculator_tool"
        })
        {
            AddHomeTool(selected, _catalog.GetById(id));
        }

        foreach (var module in _catalog.Modules)
        {
            AddHomeTool(selected, module);
            if (selected.Count >= 6)
            {
                break;
            }
        }

        return selected.Take(6);
    }

    private static void AddHomeTool(List<IToolModule> selected, IToolModule? module)
    {
        if (module is null || selected.Any(candidate => string.Equals(candidate.Id, module.Id, StringComparison.OrdinalIgnoreCase)))
        {
            return;
        }

        selected.Add(module);
    }

    private bool IsDashboardHome()
    {
        return string.Equals(_settingsService.Current.HomePageMode, "dashboard", StringComparison.OrdinalIgnoreCase);
    }

    private async void HomePage_Loaded(object sender, RoutedEventArgs e)
    {
        ArrangeHomeLayout();

        if (IsDashboardHome())
        {
            await LoadAnnouncementAsync();
            return;
        }

        if (_globeInitialized)
        {
            return;
        }

        _globeInitialized = true;
        await InitializeGlobeAsync();
    }

    private async Task InitializeGlobeAsync()
    {
        try
        {
            var resourceFolder = Path.Combine(AppContext.BaseDirectory, "Assets", "home-globe");
            if (!Directory.Exists(resourceFolder))
            {
                throw new DirectoryNotFoundException(resourceFolder);
            }

            var environment = await _webViewEnvironmentFactory.CreateAsync("HomeGlobe");
            await _globeView.EnsureCoreWebView2Async(environment);
            _globeView.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false;
            _globeView.CoreWebView2.Settings.AreDevToolsEnabled = false;
            _globeView.CoreWebView2.Settings.AreHostObjectsAllowed = false;
            _globeView.CoreWebView2.Settings.IsStatusBarEnabled = false;
            _globeView.CoreWebView2.Settings.IsZoomControlEnabled = false;
            _globeView.CoreWebView2.SetVirtualHostNameToFolderMapping(
                GlobeHostName,
                resourceFolder,
                CoreWebView2HostResourceAccessKind.Allow);
            _ephemerisTask = _solarEphemerisService.GetCurrentAsync();
            _preciseEphemerisTask = _solarEphemerisService.GetPreciseCurrentAsync();
            _globeView.CoreWebView2.NavigationCompleted += GlobeView_NavigationCompleted;
            _globeView.CoreWebView2.WebMessageReceived += GlobeView_WebMessageReceived;
            _globeView.Source = new Uri($"https://{GlobeHostName}/solar-system-home.html");
        }
        catch (Exception exception)
        {
            ShowGlobeError(exception);
        }
    }

    private async void GlobeView_NavigationCompleted(CoreWebView2 sender, CoreWebView2NavigationCompletedEventArgs args)
    {
        if (!args.IsSuccess)
        {
            return;
        }

        _solarSystemReady = true;
        SendSolarSystemSettings(sender);
        await SendEphemerisAsync(sender);
    }

    private async void GlobeView_WebMessageReceived(CoreWebView2 sender, CoreWebView2WebMessageReceivedEventArgs args)
    {
        try
        {
            using var document = JsonDocument.Parse(args.WebMessageAsJson);
            if (document.RootElement.TryGetProperty("type", out var type) &&
                string.Equals(type.GetString(), "ephemeris:ready", StringComparison.OrdinalIgnoreCase))
            {
                _solarSystemReady = true;
                SendSolarSystemSettings(sender);
                await SendEphemerisAsync(sender);
            }
        }
        catch
        {
        }
    }

    private async Task SendEphemerisAsync(CoreWebView2 webView)
    {
        if (!_solarSystemReady || _initialEphemerisSent)
        {
            return;
        }

        try
        {
            var task = _ephemerisTask ??= _solarEphemerisService.GetCurrentAsync();
            var payload = await task;
            if (_initialEphemerisSent)
            {
                return;
            }

            _initialEphemerisSent = true;
            var json = JsonSerializer.Serialize(CreateEphemerisSyncMessage(payload, "initial"), new JsonSerializerOptions(JsonSerializerDefaults.Web));
            webView.PostWebMessageAsJson(json);

            _ = SendPreciseEphemerisWhenReadyAsync(webView);
        }
        catch
        {
        }
    }

    private async Task SendPreciseEphemerisWhenReadyAsync(CoreWebView2 webView)
    {
        if (!_solarSystemReady || _preciseEphemerisStarted)
        {
            return;
        }

        _preciseEphemerisStarted = true;
        try
        {
            var task = _preciseEphemerisTask ??= _solarEphemerisService.GetPreciseCurrentAsync();
            var completed = await Task.WhenAny(task, Task.Delay(PreciseEphemerisUiTimeout));
            if (completed != task)
            {
                PostEphemerisCompletion(webView, "timeout", preciseAvailable: false);
                return;
            }

            var payload = await task;
            if (payload is null)
            {
                PostEphemerisCompletion(webView, "unavailable", preciseAvailable: false);
                return;
            }

            var json = JsonSerializer.Serialize(CreateEphemerisSyncMessage(payload, "precise"), new JsonSerializerOptions(JsonSerializerDefaults.Web));
            webView.PostWebMessageAsJson(json);
            PostEphemerisCompletion(webView, "success", preciseAvailable: true, payload.Source);
        }
        catch
        {
            PostEphemerisCompletion(webView, "failed", preciseAvailable: false);
        }
    }

    private object CreateEphemerisSyncMessage(SolarEphemerisPayload payload, string phase)
    {
        return new
        {
            type = "ephemeris:sync",
            requestId = _ephemerisRequestId,
            phase,
            source = payload.Source,
            epochUtc = payload.EpochUtc,
            planets = payload.Planets
        };
    }

    private void PostEphemerisCompletion(CoreWebView2 webView, string status, bool preciseAvailable, string? source = null)
    {
        if (_ephemerisCompletionPosted)
        {
            return;
        }

        _ephemerisCompletionPosted = true;
        try
        {
            var completion = new
            {
                type = "ephemeris:complete",
                requestId = _ephemerisRequestId,
                status,
                preciseAvailable,
                source,
                completedUtc = DateTimeOffset.UtcNow
            };
            var json = JsonSerializer.Serialize(completion, new JsonSerializerOptions(JsonSerializerDefaults.Web));
            webView.PostWebMessageAsJson(json);
        }
        catch
        {
        }
    }

    private void SendSolarSystemSettings(CoreWebView2 webView)
    {
        try
        {
            var settings = new
            {
                type = "solar:settings",
                animationsEnabled = _settingsService.Current.AnimationsEnabled,
                hardwareAccelerationEnabled = _settingsService.Current.HardwareAccelerationEnabled
            };
            var json = JsonSerializer.Serialize(settings, new JsonSerializerOptions(JsonSerializerDefaults.Web));
            webView.PostWebMessageAsJson(json);
        }
        catch
        {
        }
    }

    private void ShowGlobeError(Exception exception)
    {
        _globeHost.Children.Clear();
        _globeHost.Background = ModernUi.Surface;
        _globeHost.Children.Add(new StackPanel
        {
            Padding = new Thickness(28),
            Spacing = 10,
            VerticalAlignment = VerticalAlignment.Center,
            HorizontalAlignment = HorizontalAlignment.Center,
            Children =
            {
                ModernUi.IconTile("\uE7BA", 54, ModernUi.AccentSoft, ModernUi.Accent, 24),
                ModernUi.Text(AppLocalizer.T("3D 太阳系加载失败", "3D solar system failed to load"), 22, FontWeights.SemiBold),
                ModernUi.Text(
                    AppLocalizer.SanitizeSensitiveText(exception.Message, 180),
                    13,
                    foreground: ModernUi.TextSecondary,
                    maxLines: 3)
            }
        });
    }

    private void ArrangeDashboardLayout()
    {
        if (_dashboardGrid.Children.Count < 3)
        {
            return;
        }

        var width = ActualWidth > 0 ? ActualWidth : _dashboardGrid.ActualWidth;
        var narrow = width < 980;
        _dashboardGrid.ColumnDefinitions.Clear();
        _dashboardGrid.RowDefinitions.Clear();
        _dashboardGrid.ColumnDefinitions.Add(new ColumnDefinition());

        if (narrow)
        {
            for (var i = 0; i < 3; i++)
            {
                _dashboardGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
            }

            for (var i = 0; i < _dashboardGrid.Children.Count; i++)
            {
                var element = (FrameworkElement)_dashboardGrid.Children[i];
                Grid.SetColumn(element, 0);
                Grid.SetRow(element, i);
                Grid.SetRowSpan(element, 1);
            }

            return;
        }

        _dashboardGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0.78, GridUnitType.Star) });
        _dashboardGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
        _dashboardGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });

        var recent = (FrameworkElement)_dashboardGrid.Children[0];
        var start = (FrameworkElement)_dashboardGrid.Children[1];
        var status = (FrameworkElement)_dashboardGrid.Children[2];

        Grid.SetColumn(recent, 0);
        Grid.SetRow(recent, 0);
        Grid.SetRowSpan(recent, 2);

        Grid.SetColumn(start, 1);
        Grid.SetRow(start, 0);
        Grid.SetRowSpan(start, 1);

        Grid.SetColumn(status, 1);
        Grid.SetRow(status, 1);
        Grid.SetRowSpan(status, 1);
    }

    private void ArrangeHomeLayout()
    {
        ArrangeWelcomeLayout();

        if (IsDashboardHome())
        {
            ArrangeDashboardLayout();
            return;
        }

        var availableWidth = Math.Max(ActualWidth - 64, 320);
        var targetHeight = availableWidth * 0.56;

        if (ActualWidth < 760)
        {
            targetHeight = Math.Max(620, availableWidth * 1.25);
        }
        else if (ActualWidth < 1080)
        {
            targetHeight = Math.Max(590, availableWidth * 0.68);
        }
        else
        {
            targetHeight = Math.Max(560, availableWidth * 0.52);
        }

        var maxHeight = ActualWidth < 760 ? 760 : 740;
        _globeFrame.Height = Math.Min(Math.Max(targetHeight, 560), maxHeight);
    }

    private void ArrangeWelcomeLayout()
    {
        if (_welcomeGrid.Children.Count < 2)
        {
            return;
        }

        var stats = _welcomeGrid.Children[1] as FrameworkElement;
        var welcomeNarrow = ActualWidth < 980;

        _welcomeGrid.ColumnDefinitions.Clear();
        _welcomeGrid.RowDefinitions.Clear();
        _welcomeGrid.ColumnDefinitions.Add(new ColumnDefinition());
        if (welcomeNarrow)
        {
            _welcomeGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
            _welcomeGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
            Grid.SetColumn(stats, 0);
            Grid.SetRow(stats, 1);
        }
        else
        {
            _welcomeGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
            Grid.SetColumn(stats, 1);
            Grid.SetRow(stats, 0);
        }
    }

    private static string GetGreeting()
    {
        var hour = DateTime.Now.Hour;
        return AppLocalizer.IsEnglish
            ? hour switch
            {
                < 2 => "Late night, welcome back",
                < 4 => "Quiet hours, welcome back",
                < 6 => "Early morning, welcome back",
                < 8 => "Good morning, welcome back",
                < 10 => "Fresh morning, welcome back",
                < 12 => "Almost noon, welcome back",
                < 14 => "Good noon, welcome back",
                < 16 => "Good afternoon, welcome back",
                < 18 => "Late afternoon, welcome back",
                < 20 => "Good evening, welcome back",
                < 22 => "Evening focus, welcome back",
                _ => "Good evening, welcome back"
            }
            : hour switch
            {
                < 2 => "夜深了，欢迎回来",
                < 4 => "夜色正静，欢迎回来",
                < 6 => "清晨好，欢迎回来",
                < 8 => "早上好，欢迎回来",
                < 10 => "上午好，欢迎回来",
                < 12 => "临近中午，欢迎回来",
                < 14 => "中午好，欢迎回来",
                < 16 => "下午好，欢迎回来",
                < 18 => "傍晚好，欢迎回来",
                < 20 => "晚上好，欢迎回来",
                < 22 => "夜间专注，欢迎回来",
                _ => "夜深了，欢迎回来"
            };
    }
}
