using Netina.Domain.Entities.Warehouses;

namespace Netina.Core.EntityServices.OrderBagHandlers;

public class SubmitOrderDeliveryCommandHandler(IMediator mediator, IRepositoryWrapper repositoryWrapper)
    : IRequestHandler<SubmitOrderDeliveryCommand, OrderSDto>
{
    public async Task<OrderSDto> Handle(SubmitOrderDeliveryCommand 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 orderDelivery = await repositoryWrapper.SetRepository<OrderDelivery>()
            .TableNoTracking
            .FirstOrDefaultAsync(od => od.OrderId == request.OrderId, cancellationToken);
        if (orderDelivery != null)
        {
            order.AddOrderDelivery(orderDelivery.AddressId, orderDelivery.DeliveryCost, orderDelivery.ShippingId, orderDelivery.OrderId, orderDelivery.Id);
        }

        var shipping = await repositoryWrapper.SetRepository<Shipping>()
            .TableNoTracking
            .FirstOrDefaultAsync(s => s.Id == request.ShippingId, cancellationToken);
        if (shipping == null)
            throw new AppException("Shipping not found", ApiResultStatusCode.NotFound);

        order.AddOrderDelivery(request.AddressId, shipping.DeliveryCost, request.ShippingId, request.OrderId);

        repositoryWrapper.SetRepository<Order>().Update(order);
        await repositoryWrapper.SaveChangesAsync(cancellationToken);

        var calculatedOrder = await mediator.Send(new CalculateOrderCommand(order.Id), cancellationToken);
        return calculatedOrder.AdaptToSDto();
    }
}