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 ReviewMerchantCommandHandler(
    IMerchantRepository merchantRepository,
    ICurrentUserAccessor currentUserAccessor)
    : IRequestHandler<ReviewMerchantCommand, MerchantDto>
{
    /// <summary>
    /// 审核商户。
    /// </summary>
    /// <param name="request">审核命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>商户 DTO。</returns>
    public async Task<MerchantDto> Handle(ReviewMerchantCommand request, CancellationToken cancellationToken)
    {
        // 1. 读取商户
        var merchant = await merchantRepository.FindByIdAsync(request.MerchantId, cancellationToken)
                       ?? throw new BusinessException(ErrorCodes.NotFound, "商户不存在");

        var now = DateTime.UtcNow;
        if (!merchant.ClaimedBy.HasValue || !merchant.ClaimExpiresAt.HasValue || merchant.ClaimExpiresAt <= now)
        {
            throw new BusinessException(ErrorCodes.Conflict, "请先领取审核");
        }

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

        if (merchant.Status != MerchantStatus.Pending)
        {
            throw new BusinessException(ErrorCodes.Conflict, "商户不在待审核状态");
        }

        // 2. 更新审核状态
        merchant.Status = request.Approve ? MerchantStatus.Approved : MerchantStatus.Rejected;
        merchant.ReviewRemarks = request.Remarks;
        merchant.LastReviewedAt = now;
        merchant.LastReviewedBy = ResolveOperatorId();
        if (request.Approve && merchant.JoinedAt == null)
        {
            merchant.JoinedAt = now;
        }

        if (request.Approve)
        {
            merchant.IsFrozen = false;
            merchant.FrozenReason = null;
            merchant.FrozenAt = null;
            merchant.ApprovedAt = now;
            merchant.ApprovedBy = ResolveOperatorId();
        }
        else
        {
            merchant.IsFrozen = false;
            merchant.FrozenReason = null;
            merchant.FrozenAt = null;
        }

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

        // 3. 持久化与审计
        await merchantRepository.UpdateMerchantAsync(merchant, cancellationToken);
        await merchantRepository.AddAuditLogAsync(new MerchantAuditLog
        {
            TenantId = merchant.TenantId,
            MerchantId = merchant.Id,
            Action = request.Approve ? MerchantAuditAction.ReviewApproved : MerchantAuditAction.ReviewRejected,
            Title = request.Approve ? "商户审核通过" : "商户审核驳回",
            Description = request.Remarks,
            OperatorId = ResolveOperatorId(),
            OperatorName = ResolveOperatorName()
        }, cancellationToken);
        await merchantRepository.SaveChangesAsync(cancellationToken);

        // 4. 返回 DTO
        return MerchantMapping.ToDto(merchant);
    }

    private long? ResolveOperatorId()
    {
        var id = currentUserAccessor.UserId;
        return id == 0 ? null : id;
    }

    private string ResolveOperatorName()
    {
        var id = currentUserAccessor.UserId;
        return id == 0 ? "system" : $"user:{id}";
    }
}
