using Xunit;

namespace Nexus.Api.Tests;

internal static class DockerIntegrationTestEnvironment
{
    public const string CollectionName = "Docker integration";
    public const string PostgreSqlOptIn = "NEXUS_RUN_DOCKER_INTEGRATION_TESTS";
    public const string ToxiproxyOptIn = "NEXUS_RUN_TOXIPROXY_INTEGRATION_TESTS";

    public static bool PostgreSqlEnabled => IsEnabled(PostgreSqlOptIn);

    public static bool ToxiproxyEnabled =>
        PostgreSqlEnabled && IsEnabled(ToxiproxyOptIn);

    private static bool IsEnabled(string variable)
    {
        var value = Environment.GetEnvironmentVariable(variable)?.Trim();
        return value is not null
               && (string.Equals(value, "1", StringComparison.Ordinal)
                   || string.Equals(value, "true", StringComparison.OrdinalIgnoreCase)
                   || string.Equals(value, "yes", StringComparison.OrdinalIgnoreCase)
                   || string.Equals(value, "on", StringComparison.OrdinalIgnoreCase));
    }
}

[AttributeUsage(AttributeTargets.Method)]
public sealed class PostgreSqlIntegrationFactAttribute : FactAttribute
{
    public PostgreSqlIntegrationFactAttribute()
    {
        if (!DockerIntegrationTestEnvironment.PostgreSqlEnabled)
        {
            Skip =
                $"Requires Docker and explicit {DockerIntegrationTestEnvironment.PostgreSqlOptIn}=true opt-in.";
        }
    }
}

[AttributeUsage(AttributeTargets.Method)]
public sealed class ToxiproxyIntegrationFactAttribute : FactAttribute
{
    public ToxiproxyIntegrationFactAttribute()
    {
        if (!DockerIntegrationTestEnvironment.ToxiproxyEnabled)
        {
            Skip =
                "Requires Docker plus explicit "
                + $"{DockerIntegrationTestEnvironment.PostgreSqlOptIn}=true and "
                + $"{DockerIntegrationTestEnvironment.ToxiproxyOptIn}=true opt-in.";
        }
    }
}

[CollectionDefinition(
    DockerIntegrationTestEnvironment.CollectionName,
    DisableParallelization = true)]
public sealed class DockerIntegrationCollectionDefinition
{
}
