using Blazored.LocalStorage;
using drinkMe.Client.Models;
using drinkMe.Client.Services.Interfaces;
using drinkMe.Shared;
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;

namespace drinkMe.Client.Pages
{
	public partial class Index : ComponentBase
	{
		[Inject] ILocalStorageService LocalStorage { get; set; }
		[Inject] IPriceService PriceService { get; set; }
		[Inject] IDataService DataService { get; set; }
		protected List<DrinkViewModel> AvailableDrinks { get; set; } = new List<DrinkViewModel>();
		protected List<DiscountCodeViewModel> DiscountCodes { get; set; } = new List<DiscountCodeViewModel>();
		protected List<DrinkViewModel> CartDrinks { get; set; } = new List<DrinkViewModel>();
		protected string GetDrinksError { get; set; }
		protected string InvalidDiscountCodeError { get; set; }
		protected DiscountForm DiscountForm { get; set; } = new DiscountForm();
		protected float TotalPrice { get; set; }

		protected override async Task OnInitializedAsync()
		{
			var getDrinksResult = await DataService.GetDrinks();
			if (!getDrinksResult.IsValid)
			{
				GetDrinksError = getDrinksResult.ErrorMessage;
				return;
			}
			AvailableDrinks = (List<DrinkViewModel>)getDrinksResult.Data;
			DiscountCodes = await LocalStorage.GetItemAsync<List<DiscountCodeViewModel>>(nameof(DiscountCodes)) ?? new List<DiscountCodeViewModel>();
			CartDrinks = await LocalStorage.GetItemAsync<List<DrinkViewModel>>(nameof(CartDrinks)) ?? new List<DrinkViewModel>();
			if (CartDrinks.Count > 0)
			{
				TotalPrice = PriceService.GetTotalPrice(DiscountCodes, CartDrinks);
				AvailableDrinks.ForEach(ad => ad.IsInTheCart = CartDrinks.Any(cd => cd.Id == ad.Id));
			}
		}

		protected async Task AddQuantity(DrinkViewModel drink)
		{
			drink.Quantity = drink.Quantity is > 0 and < 20 ? ++drink.Quantity : drink.Quantity;
			await LocalStorage.SetItemAsync(nameof(CartDrinks), CartDrinks);
			TotalPrice = PriceService.GetTotalPrice(DiscountCodes, CartDrinks);
		}

		protected async Task SubtractQuantity(DrinkViewModel drink)
		{
			if (drink.Quantity - 1 == 0)
			{
				var availableDrink = AvailableDrinks.First(ad => ad.Id == drink.Id);
				availableDrink.IsInTheCart = false;
				CartDrinks.Remove(drink);
				await LocalStorage.SetItemAsync(nameof(CartDrinks), CartDrinks);
				return;
			}

			drink.Quantity = drink.Quantity is > 1 and < 21 ? --drink.Quantity : drink.Quantity;
			await LocalStorage.SetItemAsync(nameof(CartDrinks), CartDrinks);
			TotalPrice = PriceService.GetTotalPrice(DiscountCodes, CartDrinks);
		}

		protected async Task AddToCart(DrinkViewModel drink)
		{
			drink.IsInTheCart = true;
			CartDrinks.Add(drink);
			await LocalStorage.SetItemAsync(nameof(CartDrinks), CartDrinks);
			TotalPrice = PriceService.GetTotalPrice(DiscountCodes, CartDrinks);
		}

		protected async Task TryAddDiscount()
		{
			InvalidDiscountCodeError = default;

			if (DiscountCodes.Any(dc => dc.Code == DiscountForm.DiscountCode))
			{
				InvalidDiscountCodeError = "Discount code already added.";
				return;
			}

			var validationResult = await DataService.IsValidDiscountCode(DiscountForm.DiscountCode);
			if (!validationResult.IsValid)
			{
				InvalidDiscountCodeError = validationResult.ErrorMessage;
				return;
			}

			var discount = validationResult.Data as DiscountCodeViewModel;

			DiscountCodes.Add(discount);
			await LocalStorage.SetItemAsync(nameof(DiscountCodes), DiscountCodes);
			TotalPrice = PriceService.GetTotalPrice(DiscountCodes, CartDrinks);
		}

		protected void OnChangeDiscountCode(ChangeEventArgs changeEvent)
		{
			InvalidDiscountCodeError = default;
			DiscountForm.DiscountCode = (string)changeEvent.Value;
		}
	}
}
