using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace StellaOps.Feedser.Storage.Mongo;

[BsonIgnoreExtraElements]
public sealed class SourceStateDocument
{
    [BsonId]
    public string SourceName { get; set; } = string.Empty;

    [BsonElement("enabled")]
    public bool Enabled { get; set; } = true;

    [BsonElement("paused")]
    public bool Paused { get; set; }

    [BsonElement("cursor")]
    public BsonDocument Cursor { get; set; } = new();

    [BsonElement("lastSuccess")]
    [BsonIgnoreIfNull]
    public DateTime? LastSuccess { get; set; }

    [BsonElement("lastFailure")]
    [BsonIgnoreIfNull]
    public DateTime? LastFailure { get; set; }

    [BsonElement("failCount")]
    public int FailCount { get; set; }

    [BsonElement("backoffUntil")]
    [BsonIgnoreIfNull]
    public DateTime? BackoffUntil { get; set; }

    [BsonElement("updatedAt")]
    public DateTime UpdatedAt { get; set; }

    [BsonElement("lastFailureReason")]
    [BsonIgnoreIfNull]
    public string? LastFailureReason { get; set; }
}

internal static class SourceStateDocumentExtensions
{
    public static SourceStateDocument FromRecord(SourceStateRecord record)
        => new()
        {
            SourceName = record.SourceName,
            Enabled = record.Enabled,
            Paused = record.Paused,
            Cursor = record.Cursor ?? new BsonDocument(),
            LastSuccess = record.LastSuccess?.UtcDateTime,
            LastFailure = record.LastFailure?.UtcDateTime,
            FailCount = record.FailCount,
            BackoffUntil = record.BackoffUntil?.UtcDateTime,
            UpdatedAt = record.UpdatedAt.UtcDateTime,
            LastFailureReason = record.LastFailureReason,
        };

    public static SourceStateRecord ToRecord(this SourceStateDocument document)
        => new(
            document.SourceName,
            document.Enabled,
            document.Paused,
            document.Cursor ?? new BsonDocument(),
            document.LastSuccess.HasValue ? DateTime.SpecifyKind(document.LastSuccess.Value, DateTimeKind.Utc) : null,
            document.LastFailure.HasValue ? DateTime.SpecifyKind(document.LastFailure.Value, DateTimeKind.Utc) : null,
            document.FailCount,
            document.BackoffUntil.HasValue ? DateTime.SpecifyKind(document.BackoffUntil.Value, DateTimeKind.Utc) : null,
            DateTime.SpecifyKind(document.UpdatedAt, DateTimeKind.Utc),
            document.LastFailureReason);
}
