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.Shapes;
using Windows.Foundation;

namespace YMhut.Box.WinUI.Controls;

public sealed class MetricStripControl : UserControl
{
    private const int MaxSamples = 30;

    private readonly TextBlock _valueText;
    private readonly ProgressBar _bar;
    private readonly Canvas _trendCanvas = new() { Width = 58, Height = 18 };
    private readonly Polyline _trendLine = new()
    {
        Stroke = ModernUi.Accent,
        StrokeThickness = 1.5
    };
    private readonly Queue<double> _samples = new();

    public MetricStripControl(string title, string glyph)
    {
        var icon = ModernUi.IconTile(glyph, 28, ModernUi.SurfaceAlt, ModernUi.TextSecondary, 12);
        _valueText = ModernUi.Text("--", 13, FontWeights.SemiBold, maxLines: 1);
        _valueText.TextAlignment = TextAlignment.Right;
        _bar = new ProgressBar
        {
            Minimum = 0,
            Maximum = 100,
            Height = 4,
            IsIndeterminate = false,
            Foreground = ModernUi.Accent,
            Background = ModernUi.SurfaceAlt
        };

        _trendCanvas.SizeChanged += (_, _) => RedrawTrend();

        var header = new Grid { ColumnSpacing = 8 };
        header.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        header.ColumnDefinitions.Add(new ColumnDefinition());
        header.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        header.Children.Add(icon);

        var titleText = ModernUi.Text(title, 12, FontWeights.SemiBold, ModernUi.TextSecondary, maxLines: 1);
        Grid.SetColumn(titleText, 1);
        header.Children.Add(titleText);
        Grid.SetColumn(_valueText, 2);
        header.Children.Add(_valueText);

        var bottom = new Grid { ColumnSpacing = 8 };
        bottom.ColumnDefinitions.Add(new ColumnDefinition());
        bottom.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        bottom.Children.Add(_bar);
        Grid.SetColumn(_trendCanvas, 1);
        bottom.Children.Add(_trendCanvas);

        Content = new StackPanel
        {
            Spacing = 5,
            Children =
            {
                header,
                bottom
            }
        };
        AutomationProperties.SetName(this, title);
    }

    public void Update(double? percent, string valueText)
    {
        _valueText.Text = valueText;
        if (percent is double value)
        {
            var clamped = Math.Clamp(value, 0, 100);
            _bar.IsIndeterminate = false;
            _bar.Value = clamped;
            _samples.Enqueue(clamped);
            while (_samples.Count > MaxSamples)
            {
                _samples.Dequeue();
            }
        }
        else
        {
            _bar.Value = 0;
        }

        RedrawTrend();
    }

    private void RedrawTrend()
    {
        var width = _trendCanvas.ActualWidth > 0 ? _trendCanvas.ActualWidth : _trendCanvas.Width;
        var height = _trendCanvas.ActualHeight > 0 ? _trendCanvas.ActualHeight : _trendCanvas.Height;
        _trendCanvas.Children.Clear();
        DrawTrendGrid(width, height);
        var values = _samples.ToArray();
        var points = new PointCollection();
        if (values.Length == 0 || width <= 0 || height <= 0)
        {
            _trendLine.Points = points;
            _trendCanvas.Children.Add(_trendLine);
            return;
        }

        for (var index = 0; index < values.Length; index++)
        {
            var x = values.Length == 1 ? width : index * width / (values.Length - 1);
            var y = height - (values[index] / 100 * height);
            points.Add(new Point(x, Math.Clamp(y, 1, height - 1)));
        }

        _trendLine.Points = points;
        _trendLine.Stroke = ModernUi.Accent;
        _trendCanvas.Children.Add(_trendLine);
    }

    private void DrawTrendGrid(double width, double height)
    {
        if (width <= 0 || height <= 0)
        {
            return;
        }

        var gridBrush = ModernUi.TextSecondary;
        foreach (var fraction in new[] { 0.25, 0.5, 0.75 })
        {
            var y = height * fraction;
            _trendCanvas.Children.Add(new Line
            {
                X1 = 0,
                X2 = width,
                Y1 = y,
                Y2 = y,
                Stroke = gridBrush,
                StrokeThickness = 1,
                Opacity = 0.18
            });
        }

        foreach (var fraction in new[] { 0.33, 0.66 })
        {
            var x = width * fraction;
            _trendCanvas.Children.Add(new Line
            {
                X1 = x,
                X2 = x,
                Y1 = 0,
                Y2 = height,
                Stroke = gridBrush,
                StrokeThickness = 1,
                Opacity = 0.12
            });
        }
    }
}
