using MongoDB.Driver;

namespace StellaOps.Scanner.Storage;

public sealed class ScannerStorageOptions
{
    public MongoOptions Mongo { get; set; } = new();

    public ObjectStoreOptions ObjectStore { get; set; } = new();

    public DualWriteOptions DualWrite { get; set; } = new();

    public void EnsureValid()
    {
        Mongo.EnsureValid();
        ObjectStore.EnsureValid();
        DualWrite.EnsureValid();
    }
}

public sealed class MongoOptions
{
    public string ConnectionString { get; set; } = string.Empty;

    public string? DatabaseName { get; set; }
        = null;

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

    public bool UseMajorityReadConcern { get; set; }
        = true;

    public bool UseMajorityWriteConcern { get; set; }
        = true;

    public string ResolveDatabaseName()
    {
        if (!string.IsNullOrWhiteSpace(DatabaseName))
        {
            return DatabaseName.Trim();
        }

        if (!string.IsNullOrWhiteSpace(ConnectionString))
        {
            var url = MongoUrl.Create(ConnectionString);
            if (!string.IsNullOrWhiteSpace(url.DatabaseName))
            {
                return url.DatabaseName;
            }
        }

        return ScannerStorageDefaults.DefaultDatabaseName;
    }

    public void EnsureValid()
    {
        if (string.IsNullOrWhiteSpace(ConnectionString))
        {
            throw new InvalidOperationException("Scanner storage Mongo connection string is not configured.");
        }

        if (CommandTimeout <= TimeSpan.Zero)
        {
            throw new InvalidOperationException("Scanner storage Mongo command timeout must be positive.");
        }

        _ = ResolveDatabaseName();
    }
}

public sealed class ObjectStoreOptions
{
    public string Region { get; set; } = "us-east-1";

    public string? ServiceUrl { get; set; }
        = null;

    public string BucketName { get; set; } = ScannerStorageDefaults.DefaultBucketName;

    public string RootPrefix { get; set; } = ScannerStorageDefaults.DefaultRootPrefix;

    public bool ForcePathStyle { get; set; } = true;

    public bool EnableObjectLock { get; set; } = false;

    public TimeSpan? ComplianceRetention { get; set; }
        = TimeSpan.FromDays(90);

    public void EnsureValid()
    {
        if (string.IsNullOrWhiteSpace(BucketName))
        {
            throw new InvalidOperationException("Scanner storage bucket name cannot be empty.");
        }

        if (string.IsNullOrWhiteSpace(RootPrefix))
        {
            throw new InvalidOperationException("Scanner storage root prefix cannot be empty.");
        }

        if (ComplianceRetention is { } retention && retention <= TimeSpan.Zero)
        {
            throw new InvalidOperationException("Compliance retention must be positive when specified.");
        }
    }
}

public sealed class DualWriteOptions
{
    public bool Enabled { get; set; }
        = false;

    public string? MirrorBucket { get; set; }
        = null;

    public void EnsureValid()
    {
        if (Enabled && string.IsNullOrWhiteSpace(MirrorBucket))
        {
            throw new InvalidOperationException("Dual-write mirror bucket must be configured when enabled.");
        }
    }
}
