using CMSMicroservice.Protobuf.Protos.Products;
using CMSMicroservice.Protobuf.Protos.Category;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using MudBlazor;

namespace BackOffice.Pages.Category;

public partial class CategoryProductsDragDropPage
{
    [Parameter] public long? CategoryId { get; set; }

    [Inject] public ProductsContract.ProductsContractClient ProductsContract { get; set; } = default!;
    [Inject] public CategoryContract.CategoryContractClient CategoryContract { get; set; } = default!;

    private long? _selectedCategoryId;
    private bool _isLoading;
    private bool _isSaving;
    private string? _categoryTitle;
    private List<CategoryProductItem> _products = new();
    private long? _draggingProductId;

    private List<CategoryProductItem> SelectedProducts => _products.Where(p => p.Selected).ToList();
    private List<CategoryProductItem> UnselectedProducts => _products.Where(p => !p.Selected).ToList();

    protected override async Task OnInitializedAsync()
    {
        if (CategoryId.HasValue && CategoryId.Value > 0)
        {
            _selectedCategoryId = CategoryId.Value;
            await LoadCategoryAndProducts(CategoryId.Value);
        }
    }

    private async Task OnCategoryChanged(long? categoryId)
    {
        _selectedCategoryId = categoryId;
        _products.Clear();

        if (categoryId.HasValue)
        {
            await LoadCategoryAndProducts(categoryId.Value);
        }
    }

    private async Task LoadCategoryAndProducts(long categoryId)
    {
        await LoadCategoryTitle(categoryId);
        await LoadProducts(categoryId);
    }

    private async Task LoadCategoryTitle(long categoryId)
    {
        try
        {
            var response = await CategoryContract.GetCategoryAsync(new GetCategoryRequest
            {
                Id = categoryId
            });

            _categoryTitle = response?.Title ?? $"شناسه {categoryId}";
        }
        catch
        {
            _categoryTitle = null;
        }
    }

    private async Task LoadProducts(long categoryId)
    {
        _isLoading = true;
        StateHasChanged();

        try
        {
            var response = await ProductsContract.GetProductsForCategoryAsync(new GetProductsForCategoryRequest
            {
                CategoryId = categoryId
            });

            _products = response?.Items?.ToList() ?? new List<CategoryProductItem>();
        }
        catch
        {
            Snackbar.Add("در بازیابی محصولات دسته خطایی رخ داد.", Severity.Error);
        }
        finally
        {
            _isLoading = false;
            StateHasChanged();
        }
    }

    private void OnDragStart(long productId)
    {
        _draggingProductId = productId;
    }

    private void OnDragOver(DragEventArgs args)
    {
        // allow drop
    }

    private void ToggleProduct(long productId)
    {
        var item = _products.FirstOrDefault(p => p.Id == productId);
        if (item == null)
            return;

        item.Selected = !item.Selected;
    }

    private void HandleDrop(bool targetSelected)
    {
        if (_draggingProductId == null)
            return;

        var item = _products.FirstOrDefault(p => p.Id == _draggingProductId.Value);
        if (item == null)
            return;

        item.Selected = targetSelected;

        _draggingProductId = null;
        StateHasChanged();
    }

    private void OnDropOnSelected(DragEventArgs args) => HandleDrop(true);

    private void OnDropOnUnselected(DragEventArgs args) => HandleDrop(false);

    private async Task SaveProducts()
    {
        if (!_selectedCategoryId.HasValue)
            return;

        _isSaving = true;
        StateHasChanged();

        try
        {
            var request = new UpdateCategoryProductsRequest
            {
                CategoryId = _selectedCategoryId.Value
            };

            request.ProductIds.AddRange(
                _products.Where(p => p.Selected).Select(p => p.Id));

            await ProductsContract.UpdateCategoryProductsAsync(request);

            Snackbar.Add("محصولات دسته با موفقیت به‌روزرسانی شد.", Severity.Success);
        }
        catch
        {
            Snackbar.Add("در ذخیره‌سازی محصولات دسته خطایی رخ داد.", Severity.Error);
        }
        finally
        {
            _isSaving = false;
            StateHasChanged();
        }
    }
}
