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;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.App.Merchants.Handlers;

/// <summary>
/// 审核证照处理器。
/// </summary>
public sealed class ReviewMerchantDocumentCommandHandler(
    IMerchantRepository merchantRepository,
    ITenantProvider tenantProvider,
    ICurrentUserAccessor currentUserAccessor)
    : IRequestHandler<ReviewMerchantDocumentCommand, MerchantDocumentDto>
{
    /// <summary>
    /// 审核商户证照。
    /// </summary>
    /// <param name="request">审核命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>证照 DTO。</returns>
    public async Task<MerchantDocumentDto> Handle(ReviewMerchantDocumentCommand request, CancellationToken cancellationToken)
    {
        // 1. 读取证照
        var tenantId = tenantProvider.GetCurrentTenantId();
        var document = await merchantRepository.FindDocumentByIdAsync(request.MerchantId, tenantId, request.DocumentId, cancellationToken)
                       ?? throw new BusinessException(ErrorCodes.NotFound, "证照不存在");

        // 2. 若状态无变化且备注相同，直接返回
        var targetStatus = request.Approve ? MerchantDocumentStatus.Approved : MerchantDocumentStatus.Rejected;
        if (document.Status == targetStatus && document.Remarks == request.Remarks)
        {
            return MerchantMapping.ToDto(document);
        }

        // 3. 更新状态
        document.Status = targetStatus;
        document.Remarks = request.Remarks;

        // 4. 持久化与审计
        await merchantRepository.UpdateDocumentAsync(document, cancellationToken);
        await merchantRepository.AddAuditLogAsync(new MerchantAuditLog
        {
            TenantId = tenantId,
            MerchantId = document.MerchantId,
            Action = MerchantAuditAction.DocumentReviewed,
            Title = request.Approve ? "证照审核通过" : "证照审核驳回",
            Description = request.Remarks,
            OperatorId = ResolveOperatorId(),
            OperatorName = ResolveOperatorName()
        }, cancellationToken);
        await merchantRepository.SaveChangesAsync(cancellationToken);

        // 5. 返回 DTO
        return MerchantMapping.ToDto(document);
    }

    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}";
    }
}
