using Netina.Common.Models.Api;
using Netina.Common.Models.Exception;
using Netina.Domain.CommandQueries.Commands;
using Netina.Domain.Dtos.SmallDtos;
using Netina.Domain.Entities.Discounts;
using Netina.Domain.Entities.Orders;
using Netina.Repository.Repositories.Base.Contracts;

namespace Netina.Core.EntityServices.OrderBagHandlers;

public class SubmitDiscountCommandHandler : IRequestHandler<SubmitDiscountCommand,OrderSDto>
{
    private readonly IRepositoryWrapper _repositoryWrapper;
    private readonly IMediator _mediator;

    public SubmitDiscountCommandHandler(IRepositoryWrapper repositoryWrapper,IMediator mediator)
    {
        _repositoryWrapper = repositoryWrapper;
        _mediator = mediator;
    }
    public async Task<OrderSDto> Handle(SubmitDiscountCommand request, CancellationToken cancellationToken)
    {
        var order = await _repositoryWrapper.SetRepository<Order>()
            .TableNoTracking
            .FirstOrDefaultAsync(o => o.Id == request.OrderId, cancellationToken);
        if (order == null)
            throw new AppException("Order not found", ApiResultStatusCode.NotFound);
        var discount = await _repositoryWrapper.SetRepository<Discount>()
            .TableNoTracking
            .FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken);
        if (discount == null || discount.IsExpired())
            throw new AppException("تخفیف منقضی شده است یا وجود ندارد", ApiResultStatusCode.NotFound);
        order.SetDiscount(request.DiscountCode);
        _repositoryWrapper.SetRepository<Order>().Update(order);
        await _repositoryWrapper.SaveChangesAsync(cancellationToken);
        var calculateOrder = await _mediator.Send(new CalculateOrderCommand(order.Id), cancellationToken);

        return calculateOrder.AdaptToSDto();
    }
}