using CMSMicroservice.Protobuf.Protos.DiscountShoppingCart;
using CMSMicroservice.WebApi.Common.Services;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Application.DiscountShopCQ.Commands.AddToCart;
using CMSMicroservice.Application.DiscountShopCQ.Commands.RemoveFromCart;
using CMSMicroservice.Application.DiscountShopCQ.Commands.UpdateCartItemCount;
using CMSMicroservice.Application.DiscountShopCQ.Commands.ClearCart;
using CMSMicroservice.Application.DiscountShopCQ.Queries.GetUserCart;
using Grpc.Core;
using Mapster;
using MediatR;

namespace CMSMicroservice.WebApi.Services;

public class DiscountShoppingCartService : DiscountShoppingCartContract.DiscountShoppingCartContractBase
{
    private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS;
    private readonly ISender _sender;
    private readonly ICurrentUserService _currentUserService;

    public DiscountShoppingCartService(
        IDispatchRequestToCQRS dispatchRequestToCQRS,
        ISender sender,
        ICurrentUserService currentUserService)
    {
        _dispatchRequestToCQRS = dispatchRequestToCQRS;
        _sender = sender;
        _currentUserService = currentUserService;
    }

    private long GetCurrentUserId()
    {
        if (long.TryParse(_currentUserService.UserId, out var uid) && uid > 0)
            return uid;
        throw new RpcException(new Status(StatusCode.Unauthenticated, "کاربر احراز هویت نشده است"));
    }

    public override async Task<AddToCartResponse> AddToCart(AddToCartRequest request, ServerCallContext context)
    {
        var command = new AddToCartCommand
        {
            UserId = GetCurrentUserId(),
            ProductId = request.ProductId,
            Count = request.Count
        };
        var result = await _sender.Send(command, context.CancellationToken);
        return result.Adapt<AddToCartResponse>();
    }

    public override async Task<RemoveFromCartResponse> RemoveFromCart(RemoveFromCartRequest request, ServerCallContext context)
    {
        var command = new RemoveFromCartCommand
        {
            UserId = GetCurrentUserId(),
            ProductId = request.ProductId
        };
        var result = await _sender.Send(command, context.CancellationToken);
        return result.Adapt<RemoveFromCartResponse>();
    }

    public override async Task<UpdateCartItemCountResponse> UpdateCartItemCount(UpdateCartItemCountRequest request, ServerCallContext context)
    {
        var command = new UpdateCartItemCountCommand
        {
            UserId = GetCurrentUserId(),
            ProductId = request.ProductId,
            NewCount = request.NewCount
        };
        var result = await _sender.Send(command, context.CancellationToken);
        return result.Adapt<UpdateCartItemCountResponse>();
    }

    public override async Task<GetUserCartResponse> GetUserCart(GetUserCartRequest request, ServerCallContext context)
    {
        var query = new GetUserCartQuery { UserId = GetCurrentUserId() };
        var cart = await _sender.Send(query, context.CancellationToken);

        var response = new GetUserCartResponse
        {
            TotalPrice = cart.TotalAmount,
            TotalDiscountAmount = cart.MaxDiscountAmount,
            FinalPrice = cart.MinPayableAmount
        };

        foreach (var item in cart.Items)
        {
            response.Items.Add(new CMSMicroservice.Protobuf.Protos.DiscountShoppingCart.CartItemDto
            {
                ProductId = item.ProductId,
                ProductTitle = item.ProductTitle ?? string.Empty,
                ProductImagePath = item.ProductImagePath ?? string.Empty,
                UnitPrice = item.UnitPrice,
                MaxDiscountPercent = item.MaxDiscountPercent,
                Count = item.Count,
                TotalPrice = item.SubTotal,
                DiscountAmount = item.MaxDiscountAmount,
                FinalPrice = item.MinPayable,
                ProductRemainingCount = item.RemainingStock
            });
        }

        return response;
    }

    public override async Task<Empty> ClearCart(ClearCartRequest request, ServerCallContext context)
    {
        var command = new ClearCartCommand { UserId = GetCurrentUserId() };
        await _sender.Send(command, context.CancellationToken);
        return new Empty();
    }
}
