using System.ComponentModel.DataAnnotations.Schema;
using Books.Api.Domain.Accounts;
using Books.Api.Domain.Accounts.Events;
using EventFlow.Aggregates;
using EventFlow.PostgreSql.ReadStores.Attributes;
using EventFlow.ReadStores;

namespace Books.Api.EventFlow.ReadModels;

[Table("account_read_models")]
public class AccountReadModel : IReadModel,
    IAmReadModelFor<AccountAggregate, AccountId, AccountCreatedEvent>,
    IAmReadModelFor<AccountAggregate, AccountId, AccountUpdatedEvent>,
    IAmReadModelFor<AccountAggregate, AccountId, AccountDeactivatedEvent>,
    IAmReadModelFor<AccountAggregate, AccountId, AccountReactivatedEvent>
{
    // EventFlow standard columns
    [PostgreSqlReadModelIdentityColumn]
    public string AggregateId { get; set; } = string.Empty;

    public DateTimeOffset CreateTime { get; set; }
    public DateTimeOffset UpdatedTime { get; set; }

    [PostgreSqlReadModelVersionColumn]
    public int LastAggregateSequenceNumber { get; set; }

    // Business columns
    public string CompanyId { get; set; } = string.Empty;
    public string AccountNumber { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    public string AccountType { get; set; } = string.Empty;
    public string? ParentId { get; set; }
    public string? Description { get; set; }
    public string? VatCodeId { get; set; }
    public bool IsActive { get; set; } = true;
    public bool IsSystemAccount { get; set; }
    /// <summary>
    /// Erhvervsstyrelsens standardkontonummer for SAF-T rapportering.
    /// </summary>
    public string? StandardAccountNumber { get; set; }

    public Task ApplyAsync(
        IReadModelContext context,
        IDomainEvent<AccountAggregate, AccountId, AccountCreatedEvent> domainEvent,
        CancellationToken cancellationToken)
    {
        var e = domainEvent.AggregateEvent;
        AggregateId = domainEvent.AggregateIdentity.Value;
        CreateTime = domainEvent.Timestamp;
        UpdatedTime = domainEvent.Timestamp;
        LastAggregateSequenceNumber = (int)domainEvent.AggregateSequenceNumber;
        CompanyId = e.CompanyId;
        AccountNumber = e.AccountNumber;
        Name = e.Name;
        AccountType = e.AccountType.ToString().ToLowerInvariant();
        ParentId = e.ParentId;
        Description = e.Description;
        VatCodeId = e.VatCodeId;
        IsActive = true;
        IsSystemAccount = e.IsSystemAccount;
        StandardAccountNumber = e.StandardAccountNumber;
        return Task.CompletedTask;
    }

    public Task ApplyAsync(
        IReadModelContext context,
        IDomainEvent<AccountAggregate, AccountId, AccountUpdatedEvent> domainEvent,
        CancellationToken cancellationToken)
    {
        var e = domainEvent.AggregateEvent;
        UpdatedTime = domainEvent.Timestamp;
        LastAggregateSequenceNumber = (int)domainEvent.AggregateSequenceNumber;
        Name = e.Name;
        ParentId = e.ParentId;
        Description = e.Description;
        VatCodeId = e.VatCodeId;
        return Task.CompletedTask;
    }

    public Task ApplyAsync(
        IReadModelContext context,
        IDomainEvent<AccountAggregate, AccountId, AccountDeactivatedEvent> domainEvent,
        CancellationToken cancellationToken)
    {
        UpdatedTime = domainEvent.Timestamp;
        LastAggregateSequenceNumber = (int)domainEvent.AggregateSequenceNumber;
        IsActive = false;
        return Task.CompletedTask;
    }

    public Task ApplyAsync(
        IReadModelContext context,
        IDomainEvent<AccountAggregate, AccountId, AccountReactivatedEvent> domainEvent,
        CancellationToken cancellationToken)
    {
        UpdatedTime = domainEvent.Timestamp;
        LastAggregateSequenceNumber = (int)domainEvent.AggregateSequenceNumber;
        IsActive = true;
        return Task.CompletedTask;
    }
}
