using Books.Api.Domain;
using Books.Api.Domain.Accounts;
using Books.Api.EventFlow.Repositories;
using EventFlow.Commands;

namespace Books.Api.Commands.Accounts;

/// <summary>
/// Command handler for creating a new account.
/// Validates that the account number is unique within the company.
/// </summary>
public class CreateAccountCommandHandler(
    IAccountRepository accountRepository)
    : CommandHandler<AccountAggregate, AccountId, CreateAccountCommand>
{
    public override async Task ExecuteAsync(
        AccountAggregate aggregate,
        CreateAccountCommand command,
        CancellationToken cancellationToken)
    {
        // Check if an account with the same number already exists for this company
        var existingAccount = await accountRepository.GetByCompanyAndNumberAsync(
            command.CompanyId, command.AccountNumber, cancellationToken);

        if (existingAccount != null)
        {
            throw new DomainException(
                "ACCOUNT_NUMBER_EXISTS",
                $"Account number {command.AccountNumber} already exists for this company",
                $"Kontonummer {command.AccountNumber} eksisterer allerede");
        }

        aggregate.Create(
            command.CompanyId,
            command.AccountNumber,
            command.Name,
            command.AccountType,
            command.ParentId,
            command.Description,
            command.VatCodeId,
            command.IsSystemAccount,
            command.StandardAccountNumber);
    }
}

public class UpdateAccountCommandHandler : CommandHandler<AccountAggregate, AccountId, UpdateAccountCommand>
{
    public override Task ExecuteAsync(
        AccountAggregate aggregate,
        UpdateAccountCommand command,
        CancellationToken cancellationToken)
    {
        aggregate.Update(
            command.Name,
            command.ParentId,
            command.Description,
            command.VatCodeId);

        return Task.CompletedTask;
    }
}

public class DeactivateAccountCommandHandler : CommandHandler<AccountAggregate, AccountId, DeactivateAccountCommand>
{
    public override Task ExecuteAsync(
        AccountAggregate aggregate,
        DeactivateAccountCommand command,
        CancellationToken cancellationToken)
    {
        aggregate.Deactivate();
        return Task.CompletedTask;
    }
}

public class ReactivateAccountCommandHandler : CommandHandler<AccountAggregate, AccountId, ReactivateAccountCommand>
{
    public override Task ExecuteAsync(
        AccountAggregate aggregate,
        ReactivateAccountCommand command,
        CancellationToken cancellationToken)
    {
        aggregate.Reactivate();
        return Task.CompletedTask;
    }
}
