namespace MemberCenter.Infrastructure.Configuration;

public static class EnvLoader
{
    public static void LoadDotEnvIfDevelopment(string? startDirectory = null)
    {
        var path = FindDotEnvPath(startDirectory ?? Directory.GetCurrentDirectory());
        if (path is null)
        {
            return;
        }

        var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")
            ?? Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");

        if (!string.IsNullOrWhiteSpace(environment))
        {
            if (!string.Equals(environment, "Development", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }
        }
        else if (!DotEnvDeclaresDevelopment(path))
        {
            return;
        }

        foreach (var (key, value) in ReadDotEnvPairs(path))
        {
            if (Environment.GetEnvironmentVariable(key) is null)
            {
                Environment.SetEnvironmentVariable(key, value);
            }
        }
    }

    private static string? FindDotEnvPath(string startDirectory)
    {
        var directory = new DirectoryInfo(startDirectory);
        for (var depth = 0; depth < 6 && directory is not null; depth++)
        {
            var candidate = Path.Combine(directory.FullName, ".env");
            if (File.Exists(candidate))
            {
                return candidate;
            }

            directory = directory.Parent;
        }

        return null;
    }

    private static bool DotEnvDeclaresDevelopment(string path)
    {
        foreach (var (key, value) in ReadDotEnvPairs(path))
        {
            if ((key.Equals("ASPNETCORE_ENVIRONMENT", StringComparison.OrdinalIgnoreCase)
                || key.Equals("DOTNET_ENVIRONMENT", StringComparison.OrdinalIgnoreCase))
                && value.Equals("Development", StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }
        }

        return false;
    }

    private static IEnumerable<(string Key, string Value)> ReadDotEnvPairs(string path)
    {
        foreach (var line in File.ReadAllLines(path))
        {
            var trimmed = line.Trim();
            if (string.IsNullOrWhiteSpace(trimmed) || trimmed.StartsWith('#'))
            {
                continue;
            }

            var separatorIndex = trimmed.IndexOf('=');
            if (separatorIndex <= 0)
            {
                continue;
            }

            var key = trimmed[..separatorIndex].Trim();
            if (string.IsNullOrWhiteSpace(key))
            {
                continue;
            }

            var value = trimmed[(separatorIndex + 1)..].Trim();
            if ((value.StartsWith('\"') && value.EndsWith('\"')) || (value.StartsWith('\'') && value.EndsWith('\'')))
            {
                value = value[1..^1];
            }

            yield return (key, value);
        }
    }
}
