using Grand.Business.Core.Interfaces.Catalog.Products;
using Grand.Business.Core.Interfaces.Checkout.Shipping;
using Grand.Business.Core.Queries.Checkout.Orders;
using Grand.Domain.Orders;
using MediatR;

namespace Grand.Business.Checkout.Queries.Handlers.Orders;

public class IsMerchandiseReturnAllowedQueryHandler : IRequestHandler<IsMerchandiseReturnAllowedQuery, bool>
{
    private readonly IMediator _mediator;
    private readonly OrderSettings _orderSettings;
    private readonly IProductService _productService;
    private readonly IShipmentService _shipmentService;

    public IsMerchandiseReturnAllowedQueryHandler(
        IShipmentService shipmentService,
        IProductService productService,
        IMediator mediator,
        OrderSettings orderSettings)
    {
        _shipmentService = shipmentService;
        _productService = productService;
        _mediator = mediator;
        _orderSettings = orderSettings;
    }

    public async Task<bool> Handle(IsMerchandiseReturnAllowedQuery request, CancellationToken cancellationToken)
    {
        if (!_orderSettings.MerchandiseReturnsEnabled)
            return false;

        if (request.Order == null || request.Order.Deleted)
            return false;

        var shipments = await _shipmentService.GetShipmentsByOrder(request.Order.Id);

        //validate allowed number of days
        if (_orderSettings.NumberOfDaysMerchandiseReturnAvailable > 0)
        {
            var daysPassed = (DateTime.UtcNow - request.Order.CreatedOnUtc).TotalDays;
            if (daysPassed >= _orderSettings.NumberOfDaysMerchandiseReturnAvailable)
                return false;
        }

        foreach (var item in request.Order.OrderItems)
        {
            var product = await _productService.GetProductById(item.ProductId);
            if (product == null)
                return false;

            var qtyDelivery = shipments.Where(x => x.DeliveryDateUtc.HasValue).SelectMany(x => x.ShipmentItems)
                .Where(x => x.OrderItemId == item.Id).Sum(x => x.Quantity);
            var merchandiseReturns =
                (await _mediator.Send(new GetMerchandiseReturnQuery { OrderItemId = item.Id }, cancellationToken))
                .ToList();
            var qtyReturn = merchandiseReturns.Sum(rr => rr.MerchandiseReturnItems.Sum(rrItem => rrItem.Quantity));

            if (!product.NotReturnable && qtyDelivery - qtyReturn > 0)
                return true;
        }

        return false;
    }
}