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

namespace Books.Api.EventFlow.ReadModels;

[Table("attachment_read_models")]
public class AttachmentReadModel : IReadModel,
    IAmReadModelFor<AttachmentAggregate, AttachmentId, AttachmentUploadedEvent>,
    IAmReadModelFor<AttachmentAggregate, AttachmentId, AttachmentLinkedToTransactionEvent>,
    IAmReadModelFor<AttachmentAggregate, AttachmentId, AttachmentDeletedEvent>
{
    // 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 FileName { get; set; } = string.Empty;
    public string OriginalFileName { get; set; } = string.Empty;
    public string ContentType { get; set; } = string.Empty;
    public long FileSize { get; set; }
    public string StoragePath { get; set; } = string.Empty;
    public string UploadedBy { get; set; } = string.Empty;
    public DateTimeOffset UploadedAt { get; set; }

    /// <summary>
    /// Reference to journal entry draft (before posting).
    /// </summary>
    public string? DraftId { get; set; }

    /// <summary>
    /// Reference to posted transaction (after posting).
    /// </summary>
    public string? TransactionId { get; set; }

    /// <summary>
    /// Retention end date - 5 years from upload per Bogføringsloven § 6.
    /// </summary>
    public DateTimeOffset RetentionEndDate { get; set; }

    public bool IsDeleted { get; set; }
    public string? DeletedBy { get; set; }
    public string? DeleteReason { get; set; }
    public DateTimeOffset? DeletedAt { get; set; }

    public Task ApplyAsync(
        IReadModelContext context,
        IDomainEvent<AttachmentAggregate, AttachmentId, AttachmentUploadedEvent> domainEvent,
        CancellationToken cancellationToken)
    {
        var e = domainEvent.AggregateEvent;
        AggregateId = domainEvent.AggregateIdentity.Value;
        CreateTime = domainEvent.Timestamp;
        UpdatedTime = domainEvent.Timestamp;
        LastAggregateSequenceNumber = (int)domainEvent.AggregateSequenceNumber;

        CompanyId = e.CompanyId;
        FileName = e.FileName;
        OriginalFileName = e.OriginalFileName;
        ContentType = e.ContentType;
        FileSize = e.FileSize;
        StoragePath = e.StoragePath;
        UploadedBy = e.UploadedBy;
        UploadedAt = domainEvent.Timestamp;
        DraftId = e.DraftId;
        TransactionId = e.TransactionId;

        // Bogføringsloven § 6: 5-year retention
        RetentionEndDate = domainEvent.Timestamp.AddYears(5);

        IsDeleted = false;

        return Task.CompletedTask;
    }

    public Task ApplyAsync(
        IReadModelContext context,
        IDomainEvent<AttachmentAggregate, AttachmentId, AttachmentLinkedToTransactionEvent> domainEvent,
        CancellationToken cancellationToken)
    {
        var e = domainEvent.AggregateEvent;
        UpdatedTime = domainEvent.Timestamp;
        LastAggregateSequenceNumber = (int)domainEvent.AggregateSequenceNumber;
        TransactionId = e.TransactionId;
        return Task.CompletedTask;
    }

    public Task ApplyAsync(
        IReadModelContext context,
        IDomainEvent<AttachmentAggregate, AttachmentId, AttachmentDeletedEvent> domainEvent,
        CancellationToken cancellationToken)
    {
        var e = domainEvent.AggregateEvent;
        UpdatedTime = domainEvent.Timestamp;
        LastAggregateSequenceNumber = (int)domainEvent.AggregateSequenceNumber;
        IsDeleted = true;
        DeletedBy = e.DeletedBy;
        DeleteReason = e.Reason;
        DeletedAt = domainEvent.Timestamp;
        return Task.CompletedTask;
    }
}
