using System;

namespace StellaOps.Scanner.Queue;

public sealed class ScannerQueueOptions
{
    public QueueTransportKind Kind { get; set; } = QueueTransportKind.Redis;

    public RedisQueueOptions Redis { get; set; } = new();

    public NatsQueueOptions Nats { get; set; } = new();

    /// <summary>
    /// Default lease duration applied when callers do not override the visibility timeout.
    /// </summary>
    public TimeSpan DefaultLeaseDuration { get; set; } = TimeSpan.FromMinutes(5);

    /// <summary>
    /// Maximum number of times a message may be delivered before it is shunted to the dead-letter queue.
    /// </summary>
    public int MaxDeliveryAttempts { get; set; } = 5;

    /// <summary>
    /// Options controlling retry/backoff/dead-letter handling.
    /// </summary>
    public DeadLetterQueueOptions DeadLetter { get; set; } = new();

    /// <summary>
    /// Initial backoff applied when a job is retried after failure.
    /// </summary>
    public TimeSpan RetryInitialBackoff { get; set; } = TimeSpan.FromSeconds(5);

    /// <summary>
    /// Maximum backoff window applied for exponential retry.
    /// </summary>
    public TimeSpan RetryMaxBackoff { get; set; } = TimeSpan.FromMinutes(2);
}

public sealed class RedisQueueOptions
{
    public string? ConnectionString { get; set; }

    public int? Database { get; set; }

    public string StreamName { get; set; } = "scanner:jobs";

    public string ConsumerGroup { get; set; } = "scanner-workers";

    public string IdempotencyKeyPrefix { get; set; } = "scanner:jobs:idemp:";

    public TimeSpan IdempotencyWindow { get; set; } = TimeSpan.FromHours(12);

    public int? ApproximateMaxLength { get; set; }

    public TimeSpan InitializationTimeout { get; set; } = TimeSpan.FromSeconds(30);

    public TimeSpan ClaimIdleThreshold { get; set; } = TimeSpan.FromMinutes(10);

    public TimeSpan PendingScanWindow { get; set; } = TimeSpan.FromMinutes(30);

    public TimeSpan RetryInitialBackoff { get; set; } = TimeSpan.FromSeconds(5);
}

public sealed class NatsQueueOptions
{
    public string? Url { get; set; }

    public string Stream { get; set; } = "SCANNER_JOBS";

    public string Subject { get; set; } = "scanner.jobs";

    public string DurableConsumer { get; set; } = "scanner-workers";

    public int MaxInFlight { get; set; } = 64;

    public TimeSpan AckWait { get; set; } = TimeSpan.FromMinutes(5);

    public string DeadLetterStream { get; set; } = "SCANNER_JOBS_DEAD";

    public string DeadLetterSubject { get; set; } = "scanner.jobs.dead";

    public TimeSpan RetryDelay { get; set; } = TimeSpan.FromSeconds(10);

    public TimeSpan IdleHeartbeat { get; set; } = TimeSpan.FromSeconds(30);
}

public sealed class DeadLetterQueueOptions
{
    public string StreamName { get; set; } = "scanner:jobs:dead";

    public TimeSpan Retention { get; set; } = TimeSpan.FromDays(7);
}
