using AdsBillingService.Domain.AggregatesModel.BillingAccountAggregate;
using AdsBillingService.Infrastructure;
using Microsoft.EntityFrameworkCore;
using MediatR;

namespace AdsBillingService.API.Application.Commands;

public class CreateBillingAccountCommandHandler : IRequestHandler<CreateBillingAccountCommand, Guid>
{
    private readonly AdsBillingServiceContext _context;
    private readonly ILogger<CreateBillingAccountCommandHandler> _logger;

    public CreateBillingAccountCommandHandler(
        AdsBillingServiceContext context,
        ILogger<CreateBillingAccountCommandHandler> logger)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<Guid> Handle(CreateBillingAccountCommand request, CancellationToken cancellationToken)
    {
        var existingAccount = await _context.BillingAccounts
            .AsNoTracking()
            .FirstOrDefaultAsync(account => account.AdvertiserId == request.AdvertiserId, cancellationToken);

        if (existingAccount != null)
        {
            _logger.LogInformation(
                "Billing account already exists for advertiser {AdvertiserId}. Returning existing account {AccountId}",
                request.AdvertiserId,
                existingAccount.Id);
            return existingAccount.Id;
        }

        var paymentMethod = request.PaymentMethod.ToLower() switch
        {
            "prepaid" => PaymentMethodType.Prepaid,
            "postpaid" => PaymentMethodType.Postpaid,
            "creditcard" => PaymentMethodType.CreditCard,
            _ => PaymentMethodType.Prepaid
        };

        var billingAccount = new BillingAccount(
            request.AdvertiserId,
            request.WalletId,
            paymentMethod
        );

        _context.BillingAccounts.Add(billingAccount);
        await _context.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation("Billing account created for advertiser {AdvertiserId}", request.AdvertiserId);

        return billingAccount.Id;
    }
}
