using CMSMicroservice.Application.Common.Exceptions;
using CMSMicroservice.Domain.Entities;
using CMSMicroservice.Domain.Enums;

namespace CMSMicroservice.Application.InventoryItemCQ.Commands.ReserveInventory;

public class ReserveInventoryCommandHandler : IRequestHandler<ReserveInventoryCommand, ReserveInventoryResponseDto>
{
    private readonly IApplicationDbContext _context;

    public ReserveInventoryCommandHandler(IApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<ReserveInventoryResponseDto> Handle(ReserveInventoryCommand request, CancellationToken cancellationToken)
    {
        var item = await _context.InventoryItems
            .FirstOrDefaultAsync(i => i.Id == request.Id, cancellationToken);

        if (item == null)
        {
            throw new NotFoundException(nameof(Domain.Entities.InventoryItem), request.Id);
        }

        var availableQuantity = item.AvailableQuantity;

        if (availableQuantity < request.Quantity)
        {
            return new ReserveInventoryResponseDto
            {
                Success = false,
                Message = $"Insufficient stock. Available: {availableQuantity}, Requested: {request.Quantity}",
                AvailableQuantity = availableQuantity
            };
        }

        item.ReservedQuantity += request.Quantity;

        // ثبت حرکت موجودی
        var stockMovement = new StockMovement
        {
            InventoryItemId = item.Id,
            MovementType = StockMovementType.Reserved,
            Quantity = request.Quantity,
            QuantityBefore = item.Quantity,
            QuantityAfter = item.Quantity, // موجودی اصلی تغییر نمی‌کند، فقط رزرو می‌شود
            Note = "Stock reserved",
            ReferenceNumber = request.ReferenceNumber ?? $"RSV-{DateTime.UtcNow:yyyyMMddHHmmss}",
            OrderId = request.OrderId,
            DiscountOrderId = request.DiscountOrderId,
            PerformedByUserId = request.PerformedByUserId
        };

        await _context.StockMovements.AddAsync(stockMovement, cancellationToken);
        await _context.SaveChangesAsync(cancellationToken);

        return new ReserveInventoryResponseDto
        {
            Success = true,
            Message = "Stock reserved successfully",
            AvailableQuantity = item.AvailableQuantity
        };
    }
}
