using DateTimeConverterCL;
using CMSMicroservice.Protobuf.Protos.UserCarts;
using Google.Protobuf.WellKnownTypes;
using Blazored.LocalStorage;

namespace FrontOffice.Main.Utilities;

public record CartItem(long cartId,long ProductId, string Title, string ImageUrl, long UnitPrice, int Quantity)
{
    public long LineTotal => UnitPrice * Quantity;
    public long DiscountValue => (Discount*(UnitPrice * Quantity))/100;
    public int Discount { get; init; }
    public string Created { get; init; } = string.Empty;
    public string Description { get; init; } = string.Empty;
}

public class CartService
{
    private readonly UserCartsContract.UserCartsContractClient _client;
    private readonly ILocalStorageService _localStorage;
    private readonly List<CartItem> _items = new();
    private const string TokenStorageKey = "auth:token";
    private bool _isInitialized;
    
    public event Action? OnChange;

    public CartService(CMSMicroservice.Protobuf.Protos.UserCarts.UserCartsContract.UserCartsContractClient client, ILocalStorageService localStorage)
    {
        _client = client;
        _localStorage = localStorage;
        // لود سبد خرید به صورت lazy انجام میشه - نه در constructor
    }

    public IReadOnlyList<CartItem> Items => _items.AsReadOnly();
    public long Total => _items.Sum(i => i.LineTotal);
    public long TotalDiscount => _items.Sum(i => i.DiscountValue);
    public int Count => _items.Sum(i => i.Quantity);

    public async Task Add(Product product, int quantity = 1)
    {
        if (quantity <= 0) return;
        
        // اطمینان از لود شدن سبد خرید
        await EnsureInitializedAsync();
        
        // چک لاگین بودن کاربر
        if (!await IsAuthenticatedAsync()) return;
        
        var existing = _items.FirstOrDefault(i => i.ProductId == product.Id);
        int newQuantity;

        if (existing is null)
        {
            newQuantity = quantity;
            _items.Add(new CartItem(0,product.Id, product.Title, product.ImageUrl, product.Price, newQuantity)
            {
                Discount = product.Discount,
                Created = DateTime.Now.MiladiToJalali(),
                Description = product.Description
            });
        }
        else
        {
            var idx = _items.IndexOf(existing);
            newQuantity = existing.Quantity + quantity;
            _items[idx] = existing with { Quantity = newQuantity };
        }
        Notify();

        try
        {
            if (existing is null)
            {
                await _client.AddNewUserCartForCustomerAsync(new AddNewUserCartForCustomerRequest
                {
                    ProductId = product.Id,
                    Count = newQuantity
                });
               await LoadFromServerAsync();
            }
            else
            {
                await _client.UpdateUserCartForCustomerAsync(new UpdateUserCartForCustomerRequest
                {
                    CartItemId = existing.cartId,
                    Count = newQuantity
                });
            }
        }
        catch
        {
            // Best-effort sync with backend; keep local state on failure
        }
    }

    public async Task UpdateQuantity(long productId, int quantity)
    {
        // چک لاگین بودن کاربر
        if (!await IsAuthenticatedAsync()) return;
        
        var existing = _items.FirstOrDefault(i => i.ProductId == productId);
        if (existing is null) return;
        if (quantity <= 0)
        {
            await Remove(existing.cartId);
            return;
        }
        var idx = _items.IndexOf(existing);
        _items[idx] = existing with { Quantity = quantity };
        Notify();

        try
        {
            await _client.UpdateUserCartForCustomerAsync(new UpdateUserCartForCustomerRequest
            {
                CartItemId = existing.cartId,
                Count = quantity
            });
        }
        catch
        {
            // Best-effort sync with backend; keep local state on failure
        }
    }

    public async Task Remove(long cartId)
    {
        // چک لاگین بودن کاربر
        if (!await IsAuthenticatedAsync()) return;
        
        _items.RemoveAll(i => i.cartId == cartId);
        Notify();

        try
        {
            // Use dedicated remove endpoint
            await _client.RemoveUserCartForCustomerAsync(new RemoveUserCartForCustomerRequest
            {
                CartItemId = cartId
            });
        }
        catch
        {
            // Best-effort sync with backend; keep local state on failure
        }
    }

    public async Task Clear()
    {
        // چک لاگین بودن کاربر
        if (!await IsAuthenticatedAsync()) return;
        
        var productIds = _items.Select(i => i.ProductId).ToList();
        _items.Clear();
        Notify();

        try
        {
            foreach (var item in productIds)
            {
                await _client.RemoveUserCartForCustomerAsync(new RemoveUserCartForCustomerRequest
                {
                    CartItemId = item
                });
            }
        }
        catch
        {
            // Best-effort sync with backend; keep local state on failure
        }
    }

    private void Notify() => OnChange?.Invoke();

    /// <summary>
    /// بررسی اینکه کاربر لاگین کرده یا نه
    /// </summary>
    private async Task<bool> IsAuthenticatedAsync()
    {
        try
        {
            var token = await _localStorage.GetItemAsync<string>(TokenStorageKey);
            return !string.IsNullOrWhiteSpace(token);
        }
        catch
        {
            return false;
        }
    }

    /// <summary>
    /// اطمینان از لود شدن سبد خرید - فقط اگر کاربر لاگین کرده باشد
    /// </summary>
    public async Task EnsureInitializedAsync()
    {
        if (_isInitialized) return;
        
        if (await IsAuthenticatedAsync())
        {
            await LoadFromServerAsync();
        }
        _isInitialized = true;
    }

    private async Task LoadFromServerAsync()
    {
        // ابتدا چک کن که کاربر لاگین کرده
        if (!await IsAuthenticatedAsync())
        {
            return;
        }
        
        try
        {
            var response = await _client.GetCustomerCartAsync(new GetUserCartForCustomerRequest());
            _items.Clear();
            foreach (var model in response.Models)
            {
                var item = new CartItem(
                    cartId:model.Id,
                    ProductId: model.ProductId,
                    Title: model.ProductTitle ?? string.Empty,
                    ImageUrl: model.ProductThumbnailPath,
                    UnitPrice: model.ProductPrice,
                    Quantity: model.Count > 0 ? model.Count : 1)
                {
                    Discount = model.ProductDiscount,
                    Created = model.Created.ToDateTime().MiladiToJalali(),
                    Description = model.ProductShortInfomation
                };
                _items.Add(item);
            }
            Notify();
        }
        catch
        {
            // If backend is unreachable or user is unauthenticated, fall back to local-only cart.
        }
    }
}
