using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Sonex.Client.Controls.Filters;
using Sonex.Client.Dialogs;
using Sonex.Client.Helpers;
using Sonex.Client.Views;
using Sonex.Data.Records;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace Sonex.Client.Pages.Warehouse;

public sealed partial class Products : Page
{
    private CancellationTokenSource? _loadProductsCts;
    private IView? _detailsCommandView;
    private bool _isUnloaded;

    public Products()
    {
        InitializeComponent();

        DetailsTabView.ItemType = typeof(ProductRecord);
        DataGrid.ItemsType = typeof(ProductRecord);
        RootFilter.SetColumns(BuildProductFilterColumns(), BuildProductDefaultFilters());
        RootFilter.FilterChanged += RootFilter_FilterChanged;
        Unloaded += Products_Unloaded;
        UpdateDetailsCommands();
    }

    private async void DataGrid_RefreshRequested(object? sender, EventArgs e)
    {
        await LoadProducts();
    }

    private async void RootFilter_FilterChanged(object? sender, EventArgs e)
    {
        if (_isUnloaded)
        {
            return;
        }

        await LoadProducts();
    }

    private void DetailsTabView_SelectionChanged(object? sender, EventArgs e)
    {
        UpdateDetailsCommands();
    }

    private IView? CurrentDetailsView => DetailsTabView.SelectedItem?.View;

    private void DetailsAddButton_Click(object sender, RoutedEventArgs e)
    {
        var view = CurrentDetailsView;
        if (view?.CanAdd != true)
        {
            return;
        }

        view.Add();
        UpdateDetailsCommands();
    }

    private void DetailsDeleteButton_Click(object sender, RoutedEventArgs e)
    {
        var view = CurrentDetailsView;
        if (view?.CanDelete != true)
        {
            return;
        }

        view.Delete();
        UpdateDetailsCommands();
    }

    private void DetailsSaveButton_Click(object sender, RoutedEventArgs e)
    {
        var view = CurrentDetailsView;
        if (view?.CanSave != true)
        {
            return;
        }

        view.Save();
        UpdateDetailsCommands();
    }

    private void DetailsCancelButton_Click(object sender, RoutedEventArgs e)
    {
        var view = CurrentDetailsView;
        if (view?.HasChanges != true)
        {
            return;
        }

        view.Reload();
        UpdateDetailsCommands();
    }

    private void UpdateDetailsCommands()
    {
        var view = CurrentDetailsView;
        if (!ReferenceEquals(_detailsCommandView, view))
        {
            if (_detailsCommandView != null)
            {
                _detailsCommandView.StateChanged -= DetailsView_StateChanged;
            }

            _detailsCommandView = view;

            if (_detailsCommandView != null)
            {
                _detailsCommandView.StateChanged += DetailsView_StateChanged;
            }
        }

        DetailsAddButton.IsEnabled = view?.CanAdd == true;
        DetailsDeleteButton.IsEnabled = view?.CanDelete == true;
        DetailsSaveButton.IsEnabled = view?.CanSave == true;
        DetailsCancelButton.IsEnabled = view?.HasChanges == true;
    }

    private void DetailsView_StateChanged(object? sender, EventArgs e)
    {
        UpdateDetailsCommands();
    }

    private async Task LoadProducts()
    {
        _isUnloaded = false;
        _loadProductsCts?.Cancel();
        _loadProductsCts?.Dispose();
        _loadProductsCts = new CancellationTokenSource();
        var ct = _loadProductsCts.Token;

        DataGrid.LoadingRing = true;
        DataGrid.ItemsType = typeof(ProductRecord);

        try
        {
            var filter = RootFilter.BuildSql();
            var result = await ProductRecord.GetAll(
                1000000,
                filter.WhereSql,
                filter.Parameters,
                ct);

            if (ct.IsCancellationRequested || _isUnloaded)
            {
                return;
            }
            await this.ShowMessageAsync(result);

            Debug.WriteLine(result.ErrorData ?? "no error");
            DataGrid.ItemsSource = result.Items;
        }
        finally
        {
            if (!ct.IsCancellationRequested && !_isUnloaded)
            {
                DataGrid.LoadingRing = false;
            }
        }
    }

    private void Products_Unloaded(object sender, RoutedEventArgs e)
    {
        _isUnloaded = true;
        _loadProductsCts?.Cancel();
        _loadProductsCts?.Dispose();
        _loadProductsCts = null;

        DataGrid.LoadingRing = false;
        DataGrid.ItemsSource = null;
        DataGrid.ItemsType = null;
        DetailsTabView.Load(null);
        UpdateDetailsCommands();
    }

    private void DataGrid_OnChangeActiveRow(object sender, Controls.DataGridView.DataGridView.DataGridStateChangedEventArgs e)
    {
        try
        {
            if (e.Row is ProductRecord row)
            {
                
                DetailsTabView.Load(row);
            }
            else
            {
                DetailsTabView.Load(null);
            }
        }
        finally
        {
            UpdateDetailsCommands();
        }
    }

    private static IReadOnlyList<SqlFilterColumn> BuildProductFilterColumns()
    {
        return
        [
            new("Article Number", "artnr", typeof(string)),
            new("Article Name", "article_name", typeof(string)),
            new("SU EAN", "su_eans", typeof(string)),
            new("Category", "category", typeof(string)),
            new("Sales Class", "sales_class", typeof(string)),
            new("DC Group", "dc_group", typeof(string)),
            new("Web Cluster", "web_cluster", typeof(string)),
            new("Web Sales Class", "web_sales_class", typeof(string)),
            new("Web Sales Share", "web_sales_share", typeof(double?)),
            new("Price NL", "price_nl", typeof(decimal?)),
            new("Price DE", "price_de", typeof(decimal?)),
            new("Price HC", "price_hc", typeof(decimal?)),
            new("Archival", "archival", typeof(bool)),
            new("Packsize", "packsize", typeof(bool)),
            new("Ship Unit", "ship_unit", typeof(bool)),
            new("BK", "bk", typeof(bool?)),
            new("DPD", "dpd", typeof(bool?)),
            new("Last Received", "last_received", typeof(DateTime?)),
            new("Dimensions Checked", "article_dimensions_checked", typeof(DateTime?))
        ];
    }

    private static IReadOnlyList<SqlFilterDefaultRule> BuildProductDefaultFilters()
    {
        return
        [
            new("artnr", SqlFilterComparison.Contains),
            new("article_name", SqlFilterComparison.Contains),
            new("su_eans", SqlFilterComparison.Contains)
        ];
    }
}
