using LiteCharms.Features.MidrandBooks.AuthorBooks;
using LiteCharms.Features.MidrandBooks.Authors;
using LiteCharms.Features.MidrandBooks.Customers;
using LiteCharms.Features.MidrandBooks.Customers.Models;
using LiteCharms.Features.MidrandBooks.Orders;
using LiteCharms.Features.MidrandBooks.Payments;
using LiteCharms.Features.MidrandBooks.Payments.Models;
using LiteCharms.Features.MidrandBooks.Products;

namespace MidrandBookshop;

public sealed class HydrationService(AuthenticationStateProvider authStateProvider, CustomerService customerService,
    ProductService productService, OrderService orderService, BooksService booksService, AuthorService authorService, 
    CartService cartService)
{
    private Cart ShoppingCart => cartService.ShoppingCart;

    private AuthenticationState? AuthState { get; set; }
    private ClaimsPrincipal? User { get; set; }

    public bool CartHydrated { get; set; }

    public async Task EnsureCustomerExistsAsync(CancellationToken cancellationToken = default)
    {
        if (ShoppingCart.CustomerId > 0) return;

        AuthState = await authStateProvider.GetAuthenticationStateAsync();
        User = AuthState!.User;

        if (User?.Identity?.IsAuthenticated == false) return;

        var email = User!.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)!.Value!;

        var existingCustomer = await customerService.GetCustomerAsync(email, cancellationToken);

        if (existingCustomer.IsSuccess)
            ShoppingCart.CustomerId = existingCustomer.Value.Id;

        if (existingCustomer.IsFailed)
        {
            var name = User!.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)!.Value!;
            var lastname = User!.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)!.Value!;
            var mobile = User!.Claims.FirstOrDefault(c => c.Type == ClaimTypes.MobilePhone)!.Value!;

            var customerCreate = await customerService.CreateCustomerAsync(new CreateCustomer { Email = email }, cancellationToken);

            if (customerCreate.IsSuccess)
            {
                ShoppingCart.CustomerId = customerCreate.Value;

                if (!string.IsNullOrWhiteSpace(name))
                    await customerService.CreateCustomerContactAsync((long)ShoppingCart.CustomerId, new CreateCustomerContact
                    {
                        Email = email,
                        Name = name,
                        LastName = lastname,
                        Phone = mobile,
                        Type = LiteCharms.Features.ContactTypes.Personal
                    }, cancellationToken);
            }
        }
    }

    public async Task RehydrateCartFromPendingOrderAsync(CancellationToken cancellationToken = default)
    {
        if (User?.Identity?.IsAuthenticated == false) return;

        if (ShoppingCart.OrderId > 0 && ShoppingCart.CustomerId > 0)
        {
            cartService.CalculateTotalPrice();
            CartHydrated = true;

            return;
        }

        var orderResult = await orderService.GetPendingOrderAsync((long)ShoppingCart.CustomerId!, cancellationToken);

        if (orderResult.IsFailed) return;

        if(orderResult.Value.Id == ShoppingCart.OrderId)
        {
            cartService.CalculateTotalPrice();
            CartHydrated = true;

            return;
        }

        var orderItemsResult = await orderService.GetOrderItemsAsync((long)orderResult.Value.Id!, cancellationToken);

        ShoppingCart.OrderId = orderResult.Value.Id;

        if(orderItemsResult.IsFailed) return;

        foreach (var item in orderItemsResult.Value)
        {
            var priceFetchResult = await productService.GetProductPriceAsync(item.ProductPriceId, cancellationToken);

            if (priceFetchResult.IsFailed) continue;

            var bookFetchResult = await booksService.GetBookByProductIdAsync(priceFetchResult.Value.ProductId, cancellationToken);

            if (bookFetchResult.IsFailed) continue;

            var authorFetchResult = await authorService.GetAuthorAsync(bookFetchResult.Value.AuthorId, cancellationToken);

            if (authorFetchResult.IsFailed) continue;
            
            if(!ShoppingCart.Items.Any(i => i.Price!.Id == item.ProductPriceId))
                cartService.AddItem(priceFetchResult.Value, bookFetchResult.Value.Product!, authorFetchResult.Value);
        }

        CartHydrated = true;

        await cartService.SaveCartToStorageAsync();
    }
}
