using MediatR;
using TakeoutSaaS.Application.App.Billings.Commands;
using TakeoutSaaS.Application.App.Billings.Dto;
using TakeoutSaaS.Domain.Tenants.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Security;

namespace TakeoutSaaS.Application.App.Billings.Handlers;

/// <summary>
/// 审核支付命令处理器。
/// </summary>
public sealed class VerifyPaymentCommandHandler(
    ITenantPaymentRepository paymentRepository,
    ITenantBillingRepository billingRepository,
    ICurrentUserAccessor currentUserAccessor)
    : IRequestHandler<VerifyPaymentCommand, PaymentRecordDto>
{
    /// <inheritdoc />
    public async Task<PaymentRecordDto> Handle(VerifyPaymentCommand request, CancellationToken cancellationToken)
    {
        // 1. 校验操作者身份
        if (!currentUserAccessor.IsAuthenticated || currentUserAccessor.UserId <= 0)
        {
            throw new BusinessException(ErrorCodes.Unauthorized, "未登录或无效的操作者身份");
        }

        // 2. 查询支付记录
        var payment = await paymentRepository.FindByIdAsync(request.PaymentId, cancellationToken);
        if (payment is null)
        {
            throw new BusinessException(ErrorCodes.NotFound, "支付记录不存在");
        }

        // 3. 查询关联账单
        var billing = await billingRepository.FindByIdAsync(payment.BillingStatementId, cancellationToken);
        if (billing is null)
        {
            throw new BusinessException(ErrorCodes.NotFound, "关联账单不存在");
        }

        // 4. 归一化审核备注
        var normalizedNotes = string.IsNullOrWhiteSpace(request.Notes) ? null : request.Notes.Trim();

        // 5. 根据审核结果更新支付与账单状态
        if (request.Approved)
        {
            payment.Verify(currentUserAccessor.UserId);
            payment.Notes = normalizedNotes;

            billing.MarkAsPaid(payment.Amount, payment.TransactionNo ?? string.Empty);
        }
        else
        {
            payment.Reject(currentUserAccessor.UserId, normalizedNotes ?? string.Empty);
            payment.Notes = normalizedNotes;
        }

        // 6. 持久化更新状态
        await paymentRepository.UpdateAsync(payment, cancellationToken);
        if (request.Approved)
        {
            await billingRepository.UpdateAsync(billing, cancellationToken);
        }

        // 7. 保存数据库更改
        await paymentRepository.SaveChangesAsync(cancellationToken);

        // 8. 返回 DTO
        return payment.ToPaymentRecordDto();
    }
}
