using MediatR;
using TakeoutSaaS.Application.App.Finance.Invoice.Commands;
using TakeoutSaaS.Application.App.Finance.Invoice.Dto;
using TakeoutSaaS.Domain.Tenants.Enums;
using TakeoutSaaS.Domain.Tenants.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.Finance.Invoice.Handlers;

/// <summary>
/// 发票作废处理器。
/// </summary>
public sealed class VoidFinanceInvoiceRecordCommandHandler(
    ITenantInvoiceRepository repository,
    ITenantProvider tenantProvider,
    ICurrentUserAccessor currentUserAccessor)
    : IRequestHandler<VoidFinanceInvoiceRecordCommand, FinanceInvoiceRecordDetailDto>
{
    /// <inheritdoc />
    public async Task<FinanceInvoiceRecordDetailDto> Handle(
        VoidFinanceInvoiceRecordCommand request,
        CancellationToken cancellationToken)
    {
        var tenantId = tenantProvider.GetCurrentTenantId();
        var record = await repository.FindRecordByIdAsync(tenantId, request.RecordId, cancellationToken)
                     ?? throw new BusinessException(ErrorCodes.NotFound, "发票记录不存在");

        if (record.Status != TenantInvoiceStatus.Issued)
        {
            throw new BusinessException(ErrorCodes.BadRequest, "仅已开票记录允许作废");
        }

        record.Status = TenantInvoiceStatus.Voided;
        record.VoidReason = FinanceInvoiceMapping.NormalizeVoidReason(request.VoidReason);
        record.VoidedAt = DateTime.UtcNow;
        record.VoidedByUserId = currentUserAccessor.IsAuthenticated ? currentUserAccessor.UserId : null;

        await repository.UpdateRecordAsync(record, cancellationToken);
        await repository.SaveChangesAsync(cancellationToken);

        return FinanceInvoiceDtoFactory.ToRecordDetailDto(record);
    }
}
