using MediatR;
using TakeoutSaaS.Application.App.Merchants.Commands;
using TakeoutSaaS.Application.App.Merchants.Dto;
using TakeoutSaaS.Domain.Merchants.Entities;
using TakeoutSaaS.Domain.Merchants.Enums;
using TakeoutSaaS.Domain.Merchants.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Security;

namespace TakeoutSaaS.Application.App.Merchants.Handlers;

/// <summary>
/// 释放审核领取处理器。
/// </summary>
public sealed class ReleaseClaimHandler(
    IMerchantRepository merchantRepository,
    ICurrentUserAccessor currentUserAccessor)
    : IRequestHandler<ReleaseClaimCommand, ClaimInfoDto?>
{
    /// <inheritdoc />
    public async Task<ClaimInfoDto?> Handle(ReleaseClaimCommand request, CancellationToken cancellationToken)
    {
        var merchant = await merchantRepository.FindByIdAsync(request.MerchantId, cancellationToken)
            ?? throw new BusinessException(ErrorCodes.NotFound, "商户不存在");

        if (!merchant.ClaimedBy.HasValue)
        {
            return null;
        }

        var now = DateTime.UtcNow;
        var claimExpired = merchant.ClaimExpiresAt.HasValue && merchant.ClaimExpiresAt <= now;

        if (!claimExpired && merchant.ClaimedBy != currentUserAccessor.UserId)
        {
            throw new BusinessException(ErrorCodes.Conflict, $"该审核已被 {merchant.ClaimedByName} 领取");
        }

        var actorName = currentUserAccessor.IsAuthenticated
            ? $"user:{currentUserAccessor.UserId}"
            : "system";

        merchant.ClaimedBy = null;
        merchant.ClaimedByName = null;
        merchant.ClaimedAt = null;
        merchant.ClaimExpiresAt = null;

        await merchantRepository.UpdateMerchantAsync(merchant, cancellationToken);
        await merchantRepository.AddAuditLogAsync(new MerchantAuditLog
        {
            TenantId = merchant.TenantId,
            MerchantId = merchant.Id,
            Action = MerchantAuditAction.ReviewReleased,
            Title = "释放审核",
            Description = $"释放人：{actorName}",
            OperatorId = currentUserAccessor.UserId == 0 ? null : currentUserAccessor.UserId,
            OperatorName = actorName
        }, cancellationToken);
        await merchantRepository.SaveChangesAsync(cancellationToken);

        return null;
    }
}
