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

namespace Books.Api.EventFlow.ReadModels;

[Table("product_read_models")]
public class ProductReadModel : IReadModel,
    IAmReadModelFor<ProductAggregate, ProductId, ProductCreatedEvent>,
    IAmReadModelFor<ProductAggregate, ProductId, ProductUpdatedEvent>,
    IAmReadModelFor<ProductAggregate, ProductId, ProductDeactivatedEvent>,
    IAmReadModelFor<ProductAggregate, ProductId, ProductReactivatedEvent>
{
    // EventFlow standard columns
    [PostgreSqlReadModelIdentityColumn]
    public string AggregateId { get; set; } = string.Empty;

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

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

    // Business columns
    public string CompanyId { get; set; } = string.Empty;
    public string? ProductNumber { get; set; }
    public string Name { get; set; } = string.Empty;
    public string? Description { get; set; }
    public decimal UnitPrice { get; set; }
    public string VatCode { get; set; } = "U25";
    public string? Unit { get; set; }
    public string? DefaultAccountId { get; set; }
    public string? Ean { get; set; }
    public string? Manufacturer { get; set; }
    public bool IsActive { get; set; } = true;

    public Task ApplyAsync(
        IReadModelContext context,
        IDomainEvent<ProductAggregate, ProductId, ProductCreatedEvent> domainEvent,
        CancellationToken cancellationToken)
    {
        var e = domainEvent.AggregateEvent;
        AggregateId = domainEvent.AggregateIdentity.Value;
        CreateTime = domainEvent.Timestamp;
        UpdateTime = domainEvent.Timestamp;
        LastAggregateSequenceNumber = (int)domainEvent.AggregateSequenceNumber;
        CompanyId = e.CompanyId;
        ProductNumber = e.ProductNumber;
        Name = e.Name;
        Description = e.Description;
        UnitPrice = e.UnitPrice;
        VatCode = e.VatCode;
        Unit = e.Unit;
        DefaultAccountId = e.DefaultAccountId;
        Ean = e.Ean;
        Manufacturer = e.Manufacturer;
        IsActive = true;
        return Task.CompletedTask;
    }

    public Task ApplyAsync(
        IReadModelContext context,
        IDomainEvent<ProductAggregate, ProductId, ProductUpdatedEvent> domainEvent,
        CancellationToken cancellationToken)
    {
        var e = domainEvent.AggregateEvent;
        UpdateTime = domainEvent.Timestamp;
        LastAggregateSequenceNumber = (int)domainEvent.AggregateSequenceNumber;
        ProductNumber = e.ProductNumber;
        Name = e.Name;
        Description = e.Description;
        UnitPrice = e.UnitPrice;
        VatCode = e.VatCode;
        Unit = e.Unit;
        DefaultAccountId = e.DefaultAccountId;
        Ean = e.Ean;
        Manufacturer = e.Manufacturer;
        return Task.CompletedTask;
    }

    public Task ApplyAsync(
        IReadModelContext context,
        IDomainEvent<ProductAggregate, ProductId, ProductDeactivatedEvent> domainEvent,
        CancellationToken cancellationToken)
    {
        UpdateTime = domainEvent.Timestamp;
        LastAggregateSequenceNumber = (int)domainEvent.AggregateSequenceNumber;
        IsActive = false;
        return Task.CompletedTask;
    }

    public Task ApplyAsync(
        IReadModelContext context,
        IDomainEvent<ProductAggregate, ProductId, ProductReactivatedEvent> domainEvent,
        CancellationToken cancellationToken)
    {
        UpdateTime = domainEvent.Timestamp;
        LastAggregateSequenceNumber = (int)domainEvent.AggregateSequenceNumber;
        IsActive = true;
        return Task.CompletedTask;
    }
}
