using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FrontOffice.Main.Utilities;
using Microsoft.AspNetCore.Components;
using MudBlazor;

namespace FrontOffice.Main.Pages.Store;

public partial class Categories : ComponentBase
{
    [Inject] private CategoryService CategoryService { get; set; } = default!;

    private bool _loading;
    private List<CategoryItem> _items = new();
    private List<TreeItemData<long>> _treeItems = new();
    private MudTreeView<long>? _treeView;
    private string _searchPhrase = string.Empty;
    private CategoryTreeItem? _selectedNode;
    private Dictionary<long, CategoryTreeItem> _nodeLookup = new();
    private long? _selectedCategoryId;

    protected override async Task OnInitializedAsync()
    {
        _loading = true;
        _items = await CategoryService.GetAllAsync();
        BuildTreeItems();
        _loading = false;
    }

    private void BuildTreeItems()
    {
        _nodeLookup = new Dictionary<long, CategoryTreeItem>();

        var categoryIds = _items.Select(item => item.Id).ToHashSet();

        var childrenLookup = _items
            .Where(item => item.ParentId.HasValue && categoryIds.Contains(item.ParentId.Value))
            .GroupBy(item => item.ParentId!.Value)
            .ToDictionary(group => group.Key, group => group.OrderBy(child => child.Title).ToList());

        var roots = _items
            .Where(item => item.ParentId is null || !categoryIds.Contains(item.ParentId.Value))
            .OrderBy(item => item.Title)
            .Select(CreateNode)
            .Cast<TreeItemData<long>>()
            .ToList();

        _treeItems = roots;
        _selectedNode = null;
        _selectedCategoryId = null;

        CategoryTreeItem CreateNode(CategoryItem category)
        {
            var node = new CategoryTreeItem(category)
            {
                Icon = category.ParentId is null ? Icons.Material.Filled.Category : Icons.Material.Outlined.Category,
                Expanded = category.ParentId is null
            };

            _nodeLookup[category.Id] = node;

            if (childrenLookup.TryGetValue(category.Id, out var children))
            {
                node.Children = children
                    .Select(CreateNode)
                    .Cast<TreeItemData<long>>()
                    .ToList();
            }

            return node;
        }
    }

    private async Task OnSearchChanged(string searchPhrase)
    {
        _searchPhrase = searchPhrase;
        if (_treeView is not null)
        {
            await _treeView.FilterAsync();
        }
    }

    private Task<bool> MatchesName(TreeItemData<long> item)
    {
        if (string.IsNullOrWhiteSpace(_searchPhrase))
        {
            return Task.FromResult(true);
        }

        return Task.FromResult(item.Text?.Contains(_searchPhrase, StringComparison.OrdinalIgnoreCase) ?? false);
    }

    private void NavigateToCategory(long categoryId)
    {
        Navigation.NavigateTo($"{RouteConstants.Store.Products}?category={categoryId}");
    }

    private Task OnSelectedValueChanged(long categoryId)
    {
        _selectedCategoryId = categoryId;
        _selectedNode = _nodeLookup.TryGetValue(categoryId, out var node) ? node : null;
        return Task.CompletedTask;
    }

    private void NavigateToSelectedCategory()
    {
        if (_selectedNode is null)
        {
            return;
        }

        NavigateToCategory(_selectedNode.Category.Id);
    }

    private sealed class CategoryTreeItem : TreeItemData<long>
    {
        public CategoryTreeItem(CategoryItem category) : base(category.Id)
        {
            Category = category;
            Text = string.IsNullOrWhiteSpace(category.Title) ? $"دسته‌بندی {category.Id}" : category.Title;
        }

        public CategoryItem Category { get; }
    }
}
