using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Blazored.Modal;
using Blazored.Modal.Services;
using Blazored.Toast.Services;
using DiplomovaPrace.Contracts.ProductCategories;
using DiplomovaPrace.Contracts.ProductCategories.ViewModels;
using DiplomovaPrace.Web.Admin.Services;
using DiplomovaPrace.Web.Admin.Shared.Common;
using DiplomovaPrace.Web.Admin.Store.ProductCategoryUseCase;
using Fluxor;
using Microsoft.AspNetCore.Components;

namespace DiplomovaPrace.Web.Admin.Pages.ProductCategories
{
	public partial class ProductCategoryList
	{
		[CascadingParameter]
		public IModalService Modal { get; set; }

		private const int ProductsPerPage = 10;

		[Inject]
		private IToastService ToastService { get; set; }

		[Inject]
		private IState<ProductCategoryState> ProductCategoryState { get; set; }

		[Inject]
		private IProductCategoryService ProductCategoryService { get; set; }

		[Inject]
		private IProductCategoryFacadeContract ProductCategoryFacadeContract { get; set; }

		private static readonly StringComparison stringComparison = StringComparison.CurrentCultureIgnoreCase;

		private List<ProductCategoryDto> productCategories = new();

		private string activeSortField = nameof(ProductCategoryDto.Name);

		private bool isAscending = true;

		private int currentPageIndex;

		private int totalPages;

		private string searchTerm;

		protected override async Task OnInitializedAsync()
		{
			await base.OnInitializedAsync().ConfigureAwait(false);
			await ProductCategoryService.RequestProductCategoriesAsync().ConfigureAwait(false);

			//GetTotalPages();
			//SortProducts();
			await LoadProductCategories();
		}

		// search
		// filter
		// sort
		// paginate
		private async Task LoadProductCategories()
		{
			//await ProductCategoryService.RequestProductCategoriesAsync().ConfigureAwait(false);
			//List<ProductCategoryDto> productCategories = ProductCategoryState.Value.ProductCategories ?? new();
			List<ProductCategoryDto> productCategories = await ProductCategoryFacadeContract.GetAllProductCategoriesAsync().ConfigureAwait(false) ?? new();

			// search
			if (productCategories.Count > 0 && !string.IsNullOrWhiteSpace(searchTerm))
			{
				productCategories = productCategories
					.Where(i => i.ID.ToString().Contains(searchTerm) ||
						i.Name.Contains(searchTerm, stringComparison) ||
						(i.Description != null && i.Description.Contains(searchTerm, stringComparison)))
					.ToList();
			}

			// sort
			if (productCategories.Count > 0 && !string.IsNullOrEmpty(activeSortField))
			{
				if (isAscending)
				{
					productCategories = productCategories.OrderBy(i => i.GetType().GetProperty(activeSortField).GetValue(i, null)).ToList();
				}
				else
				{
					productCategories = productCategories.OrderByDescending(i => i.GetType().GetProperty(activeSortField).GetValue(i, null)).ToList();
				}
			}

			// paginate
			GetTotalPages(productCategories.Count);
			this.productCategories = productCategories.Skip(currentPageIndex * ProductsPerPage).Take(ProductsPerPage).ToList();
		}

		private async Task ShowDeleteConfirmModalAsync(int productCategoryID)
		{
			ModalOptions options = new()
			{
				DisableBackgroundCancel = true,
				Animation = ModalAnimation.FadeInOut(0.25),
				HideCloseButton = true
			};
			ModalParameters parameters = new();

			parameters.Add(nameof(ProductCategoryDto.ID), productCategoryID);
			parameters.Add("ConfirmButtonText", "Smazat");
			parameters.Add("CancelButtonText", "Zrušit");

			List<ProductCategoryDto> descendants = await ProductCategoryService.GetCategoryDescendantsAsync(productCategoryID).ConfigureAwait(false);
			if (descendants.Count > 0)
			{
				// Aby fungovaly html tagy ve stringu, je třeba psát tento tvar @((MarkupString)NazevPromenne)
				parameters.Add("BodyText", $"Opravdu chcete smazat kategorii: <b>{productCategories.Find(i => i.ID == productCategoryID)?.Name}</b><br />" +
					$"a všechny její podkategorie: <b>{string.Join(", ", descendants.Select(i => i.Name))}</b>?");
			}
			else
			{
				parameters.Add("BodyText", $"Opravdu chcete smazat kategorii: <b>{productCategories.Find(i => i.ID == productCategoryID)?.Name}</b>?");
			}

			ModalResult result = await Modal.Show<ConfirmModal>("Smazání kategorie", parameters, options).Result.ConfigureAwait(false);

			if (result.Cancelled)
			{
				return;
			}

			if (await ProductCategoryService.DeleteProductCategoryAsync(productCategoryID).ConfigureAwait(false))
			{
				ToastService.ShowSuccess("Kategorie úspěšně odstraněna!", "ÚSPĚCH");
				//GetTotalPages();
				//SortProducts();
				await LoadProductCategories();
			}
			else
			{
				ToastService.ShowError("Ajajaj něco se nepovedlo!", "CHYBA");
			}
		}

		private async Task HandleSearch(ChangeEventArgs args)
		{
			searchTerm = args.Value.ToString();

			await LoadProductCategories();
		}

		private async Task HandleSort(string sortField)
		{
			if (activeSortField.Equals(sortField))
			{
				isAscending = !isAscending;
			}
			else
			{
				activeSortField = sortField;
				isAscending = true;
			}

			//SortProducts();
			await LoadProductCategories();
		}

		//private void SortProducts()
		//{
		//	if (!string.IsNullOrEmpty(activeSortField))
		//	{
		//		if (isAscending)
		//		{
		//			productCategories = ProductCategoryState.Value.ProductCategories.OrderBy(i => i.GetType().GetProperty(activeSortField).GetValue(i, null)).ToList();
		//			PaginateCategories();
		//		}
		//		else
		//		{
		//			productCategories = ProductCategoryState.Value.ProductCategories.OrderByDescending(i => i.GetType().GetProperty(activeSortField).GetValue(i, null)).ToList();
		//			PaginateCategories();
		//		}
		//	}
		//}

		private void GetTotalPages(int totalCategories)
		{
			totalPages = totalCategories / ProductsPerPage;

			if ((ProductCategoryState.Value.ProductCategories.Count % ProductsPerPage) > 0)
			{
				totalPages++;
			}

			if (totalPages <= currentPageIndex)
			{
				currentPageIndex = 0;
			}
		}

		//private void PaginateCategories()
		//{
		//	productCategories = productCategories.Skip(currentPageIndex * ProductsPerPage).Take(ProductsPerPage).ToList();
		//}

		private async Task HandlePageChange(int newPageIndex)
		{
			currentPageIndex = newPageIndex;
			//SortProducts();
			await LoadProductCategories();
		}

		private async Task HandlePageShift(int shift)
		{
			if (shift is 1)
			{
				if ((currentPageIndex + 1) < totalPages)
				{
					currentPageIndex++;
					//SortProducts();
					await LoadProductCategories();
				}
			}
			else
			{
				if ((currentPageIndex - 1) >= 0)
				{
					currentPageIndex--;
					//SortProducts();
					await LoadProductCategories();
				}
			}
		}
	}
}
