namespace Netina.AdminPanel.PWA.Pages;

public class CategoriesPageViewModel(
    NavigationManager navigationManager,
    ISnackbar snackbar,
    IUserUtility userUtility,
    IRestWrapper restWrapper,
    IDialogService dialogService)
    : BaseViewModel<ObservableCollection<ProductCategorySDto>>(userUtility)
{
    private readonly NavigationManager _navigationManager = navigationManager;
    private readonly IUserUtility _userUtility = userUtility;

    public string Search = string.Empty;

    public override async Task InitializeAsync()
    {
        try
        {
            IsProcessing = true;
            PageDto.Clear();
            var dto = await restWrapper.ProductCategoryRestApi.ReadAll(true);
            dto.ForEach(d => PageDto.Add(d));

        }
        catch (ApiException ex)
        {
            var exe = await ex.GetContentAsAsync<ApiResult>();
            snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
        }
        catch (Exception e)
        {
            snackbar.Add(e.Message, Severity.Error);
        }
        finally
        {

            IsProcessing = false;
        }
        await base.InitializeAsync();
    }


    public async Task AddProductCategoryClicked()
    {
        DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
        var dialogResult = await dialogService.ShowAsync<ProductCategoryActionDialogBox>("افزودن دسته جدید", maxWidth);
        var result = await dialogResult.Result;
        if (!result.Canceled && result.Data is bool and true)
        {
            await InitializeAsync();
        }
    }

    public async Task EditProductCategoryClicked(ProductCategorySDto category)
    {
        DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
        var parameters = new DialogParameters<ProductCategoryActionDialogBox>();
        parameters.Add(x => x.Category, category);
        var dialogResult = await dialogService.ShowAsync<ProductCategoryActionDialogBox>($"ویرایش دسته {category.Name}", parameters, maxWidth);
        var result = await dialogResult.Result;
        if (!result.Canceled && result.Data is bool and true)
        {
            await InitializeAsync();
        }
    }

    public async Task DeleteProductCategoryAsync(Guid selectedCategoryId)
    {
        var reference = await dialogService.ShowQuestionDialog($"آیا از حذف دسته بندی اطمینان دارید ?");
        var result = await reference.Result;
        if (!result.Canceled)
        {

            try
            {

                IsProcessing = true;
                var token = await _userUtility.GetBearerTokenAsync();
                await restWrapper.CrudDtoApiRest<ProductCategory, ProductCategorySDto, Guid>(Address.ProductCategoryController)
                    .Delete(selectedCategoryId, token);
                snackbar.Add("حذف دسته بندی با موفقیت انجام شد", Severity.Success);
                await InitializeAsync();

            }
            catch (ApiException ex)
            {
                var exe = await ex.GetContentAsAsync<ApiResult>();
                snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
            }
            catch (Exception e)
            {
                snackbar.Add(e.Message, Severity.Error);
            }
            finally
            {

                IsProcessing = false;
            }
        }
    }

    public async Task SearchAsync()
    {
        try
        {
            if (Search.IsNullOrEmpty())
                throw new AppException("دسته بندی برای جست جو وارد نشده است");
            IsProcessing = true;
            PageDto.Clear();
            var dto = await restWrapper.ProductCategoryRestApi.ReadAll(Search);
            dto.ForEach(d => PageDto.Add(d));
        }
        catch (ApiException ex)
        {
            var exe = await ex.GetContentAsAsync<ApiResult>();
            snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
        }
        catch (Exception e)
        {
            snackbar.Add(e.Message, Severity.Error);
        }
        finally
        {

            IsProcessing = false;
        }
    }

    public List<ProductCategorySDto> SelectedCategories = new();
    public void SelectCategory(ProductCategorySDto category)
    {
        var selected = SelectedCategories.FirstOrDefault(c => c.Id == category.Id);
        if (selected != null)
        {
            UnSelectCategory(selected);
            return;
        }
        var parent = FindParent(category.ParentId, PageDto.ToList());
        if (parent != null)
            category.Index = parent.Index + 1;
        category.IsSelected = true;

        var currentSelectedIndex = SelectedCategories.FirstOrDefault(c => c.Index == category.Index);
        if (currentSelectedIndex != null)
            UnSelectCategory(currentSelectedIndex);

        SelectedCategories.Add(category);
    }

    public bool OriginalCategoryVisibility = false;
    public bool ChangeOriginalCategoryVisibility() => OriginalCategoryVisibility = !OriginalCategoryVisibility;
    public void AddFastProductCategory(string categoryName, Guid? parentId = null)
    {
        if (categoryName.IsNullOrEmpty())
            return;
        ProductCategorySDto category = new ProductCategorySDto { Name = categoryName, IsMain = true };
        if (parentId != null)
        {
            category.IsMain = false;
            category.ParentId = parentId.Value;

        }

        var command = new CreateProductCategoryCommand(category.Name, category.Description, category.IsMain, category.ParentId, new(), new Dictionary<string, string>(), new Dictionary<string, string>());

        Task.Run(async () =>
        {
            var token = await _userUtility.GetBearerTokenAsync();
            if (token == null)
                return;
            var response = await restWrapper.CrudApiRest<ProductCategory, Guid>(Address.ProductCategoryController)
                .Create(command, token);
            category.Id = response;
        });
        if (parentId == null)
        {
            category.IsMain = true;
            PageDto.Add(category);
        }
        else
        {
            var parent = FindParent(parentId.Value, PageDto.ToList());
            if (parent != null)
            {
                category.Index = parent.Index + 1;
                parent.Children.Add(category);
            }
        }

        categoryName = string.Empty;
    }


    private void UnSelectCategory(ProductCategorySDto category)
    {
        category.IsSelected = false;
        foreach (var selected in SelectedCategories.Where(c => c.ParentId == category.Id).ToList())
            UnSelectCategory(selected);

        SelectedCategories.Remove(category);
    }
    private ProductCategorySDto? FindParent(Guid parentId, List<ProductCategorySDto> categories)
    {
        var parent = categories.FirstOrDefault(c => c.Id == parentId);
        if (parent != null)
            return parent;
        foreach (var category in categories)
        {
            var founded = FindParent(parentId, category.Children);
            if (founded != null)
                return founded;
        }

        return null;
    }
}