using MediatR;
using Microsoft.Extensions.Logging;
using TakeoutSaaS.Application.App.Inventory.Commands;
using TakeoutSaaS.Domain.Inventory.Enums;
using TakeoutSaaS.Domain.Inventory.Repositories;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.App.Inventory.Handlers;

/// <summary>
/// 释放过期锁定处理器。
/// </summary>
public sealed class ReleaseExpiredInventoryLocksCommandHandler(
    IInventoryRepository inventoryRepository,
    ITenantProvider tenantProvider,
    ILogger<ReleaseExpiredInventoryLocksCommandHandler> logger)
    : IRequestHandler<ReleaseExpiredInventoryLocksCommand, int>
{
    /// <inheritdoc />
    public async Task<int> Handle(ReleaseExpiredInventoryLocksCommand request, CancellationToken cancellationToken)
    {
        // 1. 查询过期锁
        var tenantId = tenantProvider.GetCurrentTenantId();
        var now = DateTime.UtcNow;
        var expiredLocks = await inventoryRepository.FindExpiredLocksAsync(tenantId, now, cancellationToken);
        if (expiredLocks.Count == 0)
        {
            return 0;
        }

        // 2. 释放锁对应库存
        var affected = 0;
        foreach (var lockRecord in expiredLocks)
        {
            var item = await inventoryRepository.GetForUpdateAsync(tenantId, lockRecord.StoreId, lockRecord.ProductSkuId, cancellationToken);
            if (item is null)
            {
                continue;
            }

            if (lockRecord.IsPresale)
            {
                item.PresaleLocked = Math.Max(0, item.PresaleLocked - lockRecord.Quantity);
            }
            else
            {
                item.QuantityReserved = Math.Max(0, item.QuantityReserved - lockRecord.Quantity);
            }

            item.IsSoldOut = item.QuantityOnHand - item.QuantityReserved - item.PresaleLocked <= (item.SafetyStock ?? 0);
            await inventoryRepository.UpdateItemAsync(item, cancellationToken);
            await inventoryRepository.MarkLockStatusAsync(lockRecord, InventoryLockStatus.Released, cancellationToken);
            affected++;
        }

        await inventoryRepository.SaveChangesAsync(cancellationToken);
        logger.LogInformation("释放过期库存锁定 {Count} 条", affected);
        return affected;
    }
}
