using Microsoft.UI.Text;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Media;
using YMhut.Box.Core.Settings;
using YMhut.Box.WinUI.Services;

namespace YMhut.Box.WinUI.Controls;

public sealed class WeatherCapsuleControl : UserControl
{
    private readonly ITitleWeatherService _weatherService;
    private readonly ISettingsService _settingsService = AppServices.GetRequiredService<ISettingsService>();
    private readonly Button _button;
    private readonly AnimatedWeatherIconControl _weatherIcon;
    private readonly ProgressRing _loadingRing;
    private readonly TextBlock _locationText;
    private readonly TextBlock _tempText;
    private readonly TextBlock _conditionText;
    private readonly Flyout _flyout;

    private TitleWeatherSnapshot _snapshot = TitleWeatherSnapshot.Loading;
    private TitleWeatherSnapshot? _lastAvailableSnapshot;
    private int _loadVersion;

    public WeatherCapsuleControl(ITitleWeatherService weatherService)
    {
        _weatherService = weatherService;
        HorizontalAlignment = HorizontalAlignment.Right;
        VerticalAlignment = VerticalAlignment.Center;

        _weatherIcon = new AnimatedWeatherIconControl(20)
        {
            HorizontalAlignment = HorizontalAlignment.Center,
            VerticalAlignment = VerticalAlignment.Center
        };
        _loadingRing = new ProgressRing
        {
            Width = 18,
            Height = 18,
            IsActive = true,
            Visibility = Visibility.Collapsed
        };
        _locationText = ModernUi.Text(_snapshot.Location, 12, FontWeights.SemiBold, ModernUi.TextSecondary, maxLines: 1);
        _conditionText = ModernUi.Text(_snapshot.Condition, 10.5, foreground: ModernUi.TextSecondary, maxLines: 1);
        _tempText = ModernUi.Text(_snapshot.TemperatureText, 15, FontWeights.SemiBold, ModernUi.TextPrimary, maxLines: 1);
        ConfigureCompactLine(_locationText, 14);
        ConfigureCompactLine(_conditionText, 13);
        ConfigureCompactLine(_tempText, 18);

        var visual = new Grid
        {
            ColumnSpacing = 9,
            VerticalAlignment = VerticalAlignment.Center,
            ColumnDefinitions =
            {
                new ColumnDefinition { Width = GridLength.Auto },
                new ColumnDefinition(),
                new ColumnDefinition { Width = GridLength.Auto }
            }
        };
        var iconHost = new Grid { Width = 22, Height = 22, Children = { _weatherIcon, _loadingRing } };
        visual.Children.Add(iconHost);
        var text = new Grid
        {
            MinWidth = 76,
            MaxWidth = 130,
            VerticalAlignment = VerticalAlignment.Center,
            RowDefinitions =
            {
                new RowDefinition { Height = GridLength.Auto },
                new RowDefinition { Height = GridLength.Auto }
            }
        };
        text.Children.Add(_locationText);
        Grid.SetRow(_conditionText, 1);
        text.Children.Add(_conditionText);
        Grid.SetColumn(text, 1);
        visual.Children.Add(text);
        Grid.SetColumn(_tempText, 2);
        visual.Children.Add(_tempText);

        _flyout = new Flyout { Placement = FlyoutPlacementMode.BottomEdgeAlignedRight };
        _flyout.Opening += (_, _) => _flyout.Content = BuildFlyoutContent();

        _button = new Button
        {
            Height = 38,
            MinWidth = 168,
            MaxWidth = 242,
            Margin = new Thickness(0, 4, 0, 4),
            Padding = new Thickness(12, 4, 12, 4),
            CornerRadius = new CornerRadius(19),
            Background = ModernUi.Surface,
            BorderBrush = ModernUi.Stroke,
            BorderThickness = new Thickness(1),
            Content = visual,
            Flyout = _flyout
        };
        AutomationProperties.SetName(_button, AppLocalizer.T("天气", "Weather"));
        ToolTipService.SetToolTip(_button, AppLocalizer.T("查看天气详情", "Show weather details"));
        Content = _button;
        ApplySnapshot(_snapshot);
    }

    public async Task LoadAsync(CancellationToken cancellationToken = default)
    {
        await RefreshAsync(cancellationToken).ConfigureAwait(false);
    }

    public async Task RefreshAsync(CancellationToken cancellationToken = default)
    {
        var loadVersion = Interlocked.Increment(ref _loadVersion);
        DispatcherQueue.TryEnqueue(() => ApplySnapshot(TitleWeatherSnapshot.Loading, loadingOverlay: true));
        var snapshot = await _weatherService.GetCurrentAsync(cancellationToken).ConfigureAwait(false);
        if (loadVersion != _loadVersion)
        {
            return;
        }

        DispatcherQueue.TryEnqueue(() => ApplySnapshot(snapshot));
    }

    public void RefreshLanguage()
    {
        ApplySnapshot(_snapshot);
    }

    private void ApplySnapshot(TitleWeatherSnapshot snapshot, bool loadingOverlay = false)
    {
        var displaySnapshot = loadingOverlay && _lastAvailableSnapshot is not null
            ? _lastAvailableSnapshot
            : snapshot;
        _snapshot = displaySnapshot;
        if (displaySnapshot.IsAvailable)
        {
            _lastAvailableSnapshot = displaySnapshot;
        }

        var loading = loadingOverlay || ReferenceEquals(snapshot, TitleWeatherSnapshot.Loading);
        _loadingRing.IsActive = loading;
        _loadingRing.Visibility = loading ? Visibility.Visible : Visibility.Collapsed;
        _loadingRing.Opacity = loading ? 0.78 : 0;
        _weatherIcon.Visibility = Visibility.Visible;
        _weatherIcon.Opacity = loading ? 0.62 : 1;
        _weatherIcon.Update(displaySnapshot, _settingsService.Current.AnimationsEnabled);
        _locationText.Text = displaySnapshot.Location;
        _conditionText.Text = displaySnapshot.Condition;
        _tempText.Text = displaySnapshot.TemperatureText;
        _button.Background = displaySnapshot.IsAvailable ? ModernUi.Surface : ModernUi.SurfaceAlt;
        _button.BorderBrush = displaySnapshot.IsAvailable ? ModernUi.Stroke : ModernUi.StrokeStrong;
        ToolTipService.SetToolTip(_button, loading ? AppLocalizer.T("天气正在刷新", "Weather is refreshing") : BuildTooltip(displaySnapshot));
        AutomationProperties.SetName(_button, loading ? AppLocalizer.T("天气正在刷新", "Weather is refreshing") : BuildTooltip(displaySnapshot));
    }

    private string BuildTooltip(TitleWeatherSnapshot snapshot)
    {
        return snapshot.IsAvailable
            ? $"{snapshot.Location} {snapshot.Condition} {snapshot.TemperatureText}"
            : AppLocalizer.T("天气暂不可用，点击重试", "Weather unavailable. Click to retry.");
    }

    private UIElement BuildFlyoutContent()
    {
        var snapshot = _snapshot;
        var refresh = ModernUi.PillButton(AppLocalizer.T("刷新", "Refresh"), "\uE72C", async () => await RefreshAsync(), primary: true);
        refresh.HorizontalAlignment = HorizontalAlignment.Right;
        Grid.SetColumn(refresh, 2);

        return new StackPanel
        {
            Width = 280,
            Padding = new Thickness(4),
            Spacing = 12,
            Children =
            {
                new Grid
                {
                    ColumnSpacing = 12,
                    ColumnDefinitions =
                    {
                        new ColumnDefinition { Width = GridLength.Auto },
                        new ColumnDefinition(),
                        new ColumnDefinition { Width = GridLength.Auto }
                    },
                    Children =
                    {
                        BuildFlyoutIcon(snapshot),
                        BuildTitleBlock(snapshot),
                        refresh
                    }
                },
                BuildDetailLine(AppLocalizer.T("体感", "Feels like"), snapshot.FeelsLikeText, "\uE706"),
                BuildDetailLine(AppLocalizer.T("湿度", "Humidity"), snapshot.HumidityText, "\uE81F"),
                BuildDetailLine(AppLocalizer.T("风速", "Wind"), snapshot.WindText, "\uE9CA"),
                BuildDetailLine(AppLocalizer.T("今日温度", "Today"), snapshot.RangeText, "\uE787"),
                BuildDetailLine(AppLocalizer.T("更新时间", "Updated"), snapshot.UpdatedText, "\uE823"),
                snapshot.ErrorMessage is null
                    ? new Border { Height = 0 }
                    : ModernUi.Card(
                        ModernUi.Text(snapshot.ErrorMessage, 12, foreground: ModernUi.TextSecondary, maxLines: 3),
                        new Thickness(10),
                        radius: 8,
                        background: ModernUi.SurfaceAlt)
            }
        };
    }

    private static StackPanel BuildTitleBlock(TitleWeatherSnapshot snapshot)
    {
        var panel = new StackPanel
        {
            Spacing = 1,
            VerticalAlignment = VerticalAlignment.Center,
            Children =
            {
                ModernUi.Text(snapshot.Location, 17, FontWeights.SemiBold, maxLines: 1),
                ModernUi.Text($"{snapshot.Condition} · {snapshot.TemperatureText} · {snapshot.QueryLevel}", 13, foreground: ModernUi.TextSecondary, maxLines: 1)
            }
        };
        Grid.SetColumn(panel, 1);
        return panel;
    }

    private UIElement BuildFlyoutIcon(TitleWeatherSnapshot snapshot)
    {
        var icon = new AnimatedWeatherIconControl(44);
        icon.Update(snapshot, _settingsService.Current.AnimationsEnabled);
        return new Border
        {
            Width = 52,
            Height = 52,
            CornerRadius = new CornerRadius(8),
            Background = ModernUi.AccentSoft,
            BorderBrush = ModernUi.Stroke,
            BorderThickness = new Thickness(1),
            Child = icon
        };
    }

    private static void ConfigureCompactLine(TextBlock text, double lineHeight)
    {
        text.TextWrapping = TextWrapping.NoWrap;
        text.TextTrimming = TextTrimming.CharacterEllipsis;
        text.LineHeight = lineHeight;
        text.VerticalAlignment = VerticalAlignment.Center;
    }

    private static UIElement BuildDetailLine(string label, string value, string glyph)
    {
        var grid = new Grid { ColumnSpacing = 10 };
        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(glyph, 30, ModernUi.SurfaceAlt, ModernUi.TextSecondary, 13));

        var title = ModernUi.Text(label, 13, FontWeights.SemiBold, ModernUi.TextSecondary, maxLines: 1);
        Grid.SetColumn(title, 1);
        grid.Children.Add(title);

        var text = ModernUi.Text(value, 13, FontWeights.SemiBold, ModernUi.TextPrimary, maxLines: 1);
        Grid.SetColumn(text, 2);
        grid.Children.Add(text);
        return grid;
    }
}
