using System;
using System.Threading.Tasks;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Animation;
using Windows.Foundation;
using Tornado3_2026Election.Domain;
using Tornado3_2026Election.ViewModels;

namespace Tornado3_2026Election.Controls;

public sealed partial class ChannelSchedulePanel : UserControl
{
    public static readonly DependencyProperty ViewModelProperty =
        DependencyProperty.Register(
            nameof(ViewModel),
            typeof(ChannelScheduleViewModel),
            typeof(ChannelSchedulePanel),
            new PropertyMetadata(null));

    public ChannelSchedulePanel()
    {
        InitializeComponent();
    }

    public ChannelScheduleViewModel? ViewModel
    {
        get => (ChannelScheduleViewModel?)GetValue(ViewModelProperty);
        set => SetValue(ViewModelProperty, value);
    }

    private void PromoteToNextButton_Click(object sender, RoutedEventArgs e)
    {
        var item = GetItem(sender);
        var command = ViewModel?.PromoteToNextCommand;
        if (item is null || command is null || !command.CanExecute(item))
        {
            return;
        }

        command.Execute(item);
    }

    private void MoveUpButton_Click(object sender, RoutedEventArgs e)
    {
        _ = AnimateSwapAsync(sender, moveUp: true);
    }

    private void MoveDownButton_Click(object sender, RoutedEventArgs e)
    {
        _ = AnimateSwapAsync(sender, moveUp: false);
    }

    private void RemoveItemButton_Click(object sender, RoutedEventArgs e)
    {
        var item = GetItem(sender);
        var command = ViewModel?.RemoveItemCommand;
        if (item is null || command is null || !command.CanExecute(item))
        {
            return;
        }

        command.Execute(item);
    }

    private void IncreaseDurationButton_Click(object sender, RoutedEventArgs e)
    {
        GetItem(sender)?.StepDraftDuration(1d);
    }

    private void DecreaseDurationButton_Click(object sender, RoutedEventArgs e)
    {
        GetItem(sender)?.StepDraftDuration(-1d);
    }

    private void ApplyDurationButton_Click(object sender, RoutedEventArgs e)
    {
        var item = GetItem(sender);
        if (item is null)
        {
            return;
        }

        item.ApplyDraftDuration();
        ViewModel?.RefreshSummary();
    }

    private static ChannelScheduleItem? GetItem(object sender)
    {
        return (sender as FrameworkElement)?.DataContext as ChannelScheduleItem;
    }

    private async Task AnimateSwapAsync(object sender, bool moveUp)
    {
        if (ViewModel is null)
        {
            return;
        }

        var item = GetItem(sender);
        if (item is null)
        {
            return;
        }

        var currentIndex = ViewModel.Queue.IndexOf(item);
        var targetIndex = currentIndex + (moveUp ? -1 : 1);
        if (currentIndex < 0 || targetIndex < 0 || targetIndex >= ViewModel.Queue.Count)
        {
            return;
        }

        var swappedItem = ViewModel.Queue[targetIndex];
        var movingContainer = QueueListView.ContainerFromItem(item) as ListViewItem;
        var swappedContainer = QueueListView.ContainerFromItem(swappedItem) as ListViewItem;
        var movingTop = movingContainer is null ? (double?)null : GetTop(movingContainer);
        var swappedTop = swappedContainer is null ? (double?)null : GetTop(swappedContainer);

        var command = moveUp ? ViewModel.MoveUpCommand : ViewModel.MoveDownCommand;
        if (!command.CanExecute(item))
        {
            return;
        }

        command.Execute(item);

        await Task.Yield();
        QueueListView.UpdateLayout();

        if (movingTop.HasValue)
        {
            AnimateToCurrentPosition(QueueListView.ContainerFromItem(item) as ListViewItem, movingTop.Value);
        }

        if (swappedTop.HasValue)
        {
            AnimateToCurrentPosition(QueueListView.ContainerFromItem(swappedItem) as ListViewItem, swappedTop.Value);
        }
    }

    private double GetTop(FrameworkElement element)
    {
        return element.TransformToVisual(QueueListView).TransformPoint(new Point(0, 0)).Y;
    }

    private void AnimateToCurrentPosition(ListViewItem? container, double previousTop)
    {
        if (container is null)
        {
            return;
        }

        var currentTop = GetTop(container);
        var delta = previousTop - currentTop;
        if (Math.Abs(delta) < 0.5)
        {
            return;
        }

        var transform = container.RenderTransform as TranslateTransform;
        if (transform is null)
        {
            transform = new TranslateTransform();
            container.RenderTransform = transform;
        }

        transform.Y = delta;

        var animation = new DoubleAnimation
        {
            To = 0,
            Duration = new Duration(TimeSpan.FromMilliseconds(180)),
            EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut }
        };

        var storyboard = new Storyboard();
        storyboard.Children.Add(animation);
        Storyboard.SetTarget(animation, transform);
        Storyboard.SetTargetProperty(animation, nameof(TranslateTransform.Y));
        storyboard.Begin();
    }
}
