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;
using DiplomovaPrace.Contracts.Products;
using DiplomovaPrace.Contracts.Products.ViewModels;
using DiplomovaPrace.Web.Admin.Services;
using DiplomovaPrace.Web.Admin.Shared.Common;
using DiplomovaPrace.Web.Admin.Store.ProductCategoryUseCase;
using Fluxor;
using Havit.Collections;
using Microsoft.AspNetCore.Components;

namespace DiplomovaPrace.Web.Admin.Pages.Products
{
	public partial class ProductList
	{
		private const int ProductsPerPage = 10;

		[CascadingParameter]
		public IModalService Modal { get; set; }

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

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

		[Inject]
		private IProductFacadeContract ProductFacadeContract { get; set; }

		[Inject]
		private IProductService ProductService { get; set; }

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

		private List<ProductDto> products = new();

		private ProductListQueryFilter filterModel = new() { ProductCategoryID = 0 };

		private string activeSortExpression = nameof(ProductDto.Name);

		private SortDirection sortDirection = SortDirection.Ascending;

		private int currentPageIndex;

		private int totalPages;

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

			await ProductCategoryService.RequestProductCategoriesAsync().ConfigureAwait(false);

			await LoadProductsAsync();
		}

		private async Task LoadProductsAsync()
		{
			SortItem[] sortItem = new SortItem[1] { new SortItem { Direction = sortDirection, Expression = activeSortExpression } };

			PagedQueryRequest<ProductListQueryFilter> pagedQuery = new()
			{
				Filter = filterModel,
				PageIndex = currentPageIndex,
				PageSize = ProductsPerPage,
				Sorting = sortItem
			};

			PagedQueryResult<ProductDto> data = await ProductFacadeContract.GetProductListAsync(pagedQuery).ConfigureAwait(false);
			products = data.Data;

			// calculate total pages
			GetTotalPages(data.TotalCount);
		}

		private string GetProductCategoryNameByID(int? id)
		{
			if(id is not null)
			{
				return ProductCategoryState.Value.ProductCategories.Find(i => i.ID == id)?.Name;
			}

			return string.Empty;
		}

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

			parameters.Add(nameof(ProductDto.ID), productID);
			parameters.Add("ConfirmButtonText", "Smazat");
			parameters.Add("CancelButtonText", "Zrušit");
			parameters.Add("BodyText", $"Opravdu chcete smazat produkt: <strong>{products.FirstOrDefault(i => i.ID == productID)?.Name}</strong>?");

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

			if (result.Cancelled)
			{
				return;
			}

			if (await ProductService.DeleteProductAsync(productID).ConfigureAwait(false))
			{
				var product = products.FirstOrDefault(i => i.ID == productID);
				products.Remove(product);

				ToastService.ShowSuccess("Produkt úspěšně smazán!", "POVEDLO SE");
			}
			else
			{
				ToastService.ShowError("Ajajaj! Něco se nepovedlo.", "CHYBA");
			}
		}

		private async Task HandleFilterByAsync(int? categoryId)
		{
			filterModel.ProductCategoryID = categoryId != null ? categoryId : 0;
			currentPageIndex = 0;

			await LoadProductsAsync().ConfigureAwait(false);
		}

		private async Task HandleSortAsync(string sortExpression)
		{
			if (products.Count > 1 || totalPages > 1)
			{
				if (activeSortExpression.Equals(sortExpression))
				{
					sortDirection = (sortDirection == SortDirection.Ascending) ? SortDirection.Descending : SortDirection.Ascending;
				}
				else
				{
					activeSortExpression = sortExpression;
					sortDirection = SortDirection.Ascending;
				}

				await LoadProductsAsync().ConfigureAwait(false);
			}
		}

		private async Task HandleSearchAsync(ChangeEventArgs e)
		{
			filterModel.SearchString = e.Value.ToString();

			await LoadProductsAsync().ConfigureAwait(false);
		}

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

			if ((productsCount % ProductsPerPage) > 0)
			{
				totalPages++;
			}

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

		private async Task HandlePageChangeAsync(int newPageIndex)
		{
			if (newPageIndex != currentPageIndex)
			{
				currentPageIndex = newPageIndex;

				await LoadProductsAsync().ConfigureAwait(false);
			}
		}

		private async Task HandlePageShiftAsync(int shift)
		{
			if (shift == 1)
			{
				if ((currentPageIndex + 1) < totalPages)
				{
					currentPageIndex++;
					await LoadProductsAsync().ConfigureAwait(false);
				}
			}
			else
			{
				if ((currentPageIndex - 1) >= 0)
				{
					currentPageIndex--;
					await LoadProductsAsync().ConfigureAwait(false);
				}
			}
		}
	}
}