using System.Text.RegularExpressions;
using Books.Api.Domain.Accounts.Events;
using EventFlow.Aggregates;

namespace Books.Api.Domain.Accounts;

public class AccountAggregate(AccountId id) : AggregateRoot<AccountAggregate, AccountId>(id),
    IEmit<AccountCreatedEvent>,
    IEmit<AccountUpdatedEvent>,
    IEmit<AccountDeactivatedEvent>,
    IEmit<AccountReactivatedEvent>
{
    private bool _isCreated;
    private bool _isActive = true;
    private bool _isSystemAccount;

    public void Apply(AccountCreatedEvent e)
    {
        _isCreated = true;
        _isSystemAccount = e.IsSystemAccount;
    }

    public void Apply(AccountUpdatedEvent e) { }

    public void Apply(AccountDeactivatedEvent e) => _isActive = false;

    public void Apply(AccountReactivatedEvent e) => _isActive = true;

    public void Create(
        string companyId,
        string accountNumber,
        string name,
        AccountType accountType,
        string? parentId,
        string? description,
        string? vatCodeId,
        bool isSystemAccount = false,
        string? standardAccountNumber = null)
    {
        if (_isCreated)
            throw new DomainException("ACCOUNT_EXISTS", "Account already exists", "Konto eksisterer allerede");

        if (string.IsNullOrWhiteSpace(companyId))
            throw new DomainException("COMPANY_REQUIRED", "Company ID is required", "Virksomheds-ID er paakraevet");

        if (string.IsNullOrWhiteSpace(accountNumber))
            throw new DomainException("ACCOUNT_NUMBER_REQUIRED", "Account number is required", "Kontonummer er paakraevet");

        if (string.IsNullOrWhiteSpace(name))
            throw new DomainException("ACCOUNT_NAME_REQUIRED", "Account name is required", "Kontonavn er paakraevet");

        // Validate account number format (4-10 digits, Danish standard)
        if (!Regex.IsMatch(accountNumber.Trim(), @"^\d{4,10}$"))
            throw new DomainException("INVALID_ACCOUNT_NUMBER", "Account number must be 4-10 digits", "Kontonummer skal vaere 4-10 cifre");

        Emit(new AccountCreatedEvent(
            companyId,
            accountNumber.Trim(),
            name.Trim(),
            accountType,
            parentId,
            description?.Trim(),
            vatCodeId,
            isSystemAccount,
            standardAccountNumber?.Trim()));
    }

    public void Update(string name, string? parentId, string? description, string? vatCodeId)
    {
        if (!_isCreated)
            throw new DomainException("ACCOUNT_NOT_FOUND", "Account does not exist", "Konto findes ikke");

        if (_isSystemAccount)
            throw new DomainException("SYSTEM_ACCOUNT_READONLY", "System accounts cannot be modified", "Systemkonti kan ikke aendres");

        if (string.IsNullOrWhiteSpace(name))
            throw new DomainException("ACCOUNT_NAME_REQUIRED", "Account name is required", "Kontonavn er paakraevet");

        Emit(new AccountUpdatedEvent(name.Trim(), parentId, description?.Trim(), vatCodeId));
    }

    public void Deactivate()
    {
        if (!_isCreated)
            throw new DomainException("ACCOUNT_NOT_FOUND", "Account does not exist", "Konto findes ikke");

        if (_isSystemAccount)
            throw new DomainException("SYSTEM_ACCOUNT_READONLY", "System accounts cannot be deactivated", "Systemkonti kan ikke deaktiveres");

        if (!_isActive)
            throw new DomainException("ACCOUNT_ALREADY_INACTIVE", "Account is already inactive", "Konto er allerede inaktiv");

        Emit(new AccountDeactivatedEvent());
    }

    public void Reactivate()
    {
        if (!_isCreated)
            throw new DomainException("ACCOUNT_NOT_FOUND", "Account does not exist", "Konto findes ikke");

        if (_isActive)
            throw new DomainException("ACCOUNT_ALREADY_ACTIVE", "Account is already active", "Konto er allerede aktiv");

        Emit(new AccountReactivatedEvent());
    }
}
