using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Adaptation._Tests.Shared;

public class IsEnvironment
{

    public enum Name
    {
        LinuxDevelopment,
        LinuxProduction,
        LinuxStaging,
        OSXDevelopment,
        OSXProduction,
        OSXStaging,
        WindowsDevelopment,
        WindowsProduction,
        WindowsStaging
    }

    public bool DebuggerWasAttachedDuringConstructor { get; private set; }
    public bool Development { get; private set; }
    public bool Linux { get; private set; }
    public bool OSX { get; private set; }
    public bool Production { get; private set; }
    public bool Staging { get; private set; }
    public bool Windows { get; private set; }
    public string Profile { get; private set; }
    public string AppSettingsFileName { get; private set; }
    public string ASPNetCoreEnvironment { get; private set; }

    public IsEnvironment(string testCategory)
    {
        if (testCategory.EndsWith(".json"))
        {
            Production = testCategory == "appsettings.json";
            Staging = testCategory.EndsWith(nameof(Staging));
            OSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
            Development = testCategory.EndsWith(nameof(Development));
            Linux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
            DebuggerWasAttachedDuringConstructor = Debugger.IsAttached;
            Windows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
            ASPNetCoreEnvironment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        }
        else
        {
            DebuggerWasAttachedDuringConstructor = Debugger.IsAttached;
            OSX = !string.IsNullOrEmpty(testCategory) && testCategory.StartsWith(nameof(OSX));
            ASPNetCoreEnvironment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
            Linux = !string.IsNullOrEmpty(testCategory) && testCategory.StartsWith(nameof(Linux));
            Staging = !string.IsNullOrEmpty(testCategory) && testCategory.EndsWith(nameof(Staging));
            Windows = !string.IsNullOrEmpty(testCategory) && testCategory.StartsWith(nameof(Windows));
            Production = !string.IsNullOrEmpty(testCategory) && testCategory.EndsWith(nameof(Production));
            Development = !string.IsNullOrEmpty(testCategory) && testCategory.EndsWith(nameof(Development));
        }
        Profile = GetProfile();
        AppSettingsFileName = GetAppSettingsFileName(processesCount: null);
    }

    public IsEnvironment(bool isDevelopment, bool isStaging, bool isProduction)
    {
        Staging = isStaging;
        Production = isProduction;
        Development = isDevelopment;
        OSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
        Linux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
        DebuggerWasAttachedDuringConstructor = Debugger.IsAttached;
        Windows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
        ASPNetCoreEnvironment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        Profile = GetProfile();
        AppSettingsFileName = GetAppSettingsFileName(processesCount: null);
    }

    public IsEnvironment(int? processesCount, bool nullASPNetCoreEnvironmentIsDevelopment, bool nullASPNetCoreEnvironmentIsProduction)
    {
        OSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
        Linux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
        DebuggerWasAttachedDuringConstructor = Debugger.IsAttached;
        Windows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
        ASPNetCoreEnvironment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        if (nullASPNetCoreEnvironmentIsDevelopment && nullASPNetCoreEnvironmentIsProduction)
            throw new Exception();
        else if (string.IsNullOrEmpty(ASPNetCoreEnvironment) && nullASPNetCoreEnvironmentIsProduction)
            Production = true;
        else if (string.IsNullOrEmpty(ASPNetCoreEnvironment) && nullASPNetCoreEnvironmentIsDevelopment)
            Development = true;
        else if (string.IsNullOrEmpty(ASPNetCoreEnvironment) && !nullASPNetCoreEnvironmentIsDevelopment && !nullASPNetCoreEnvironmentIsProduction)
            throw new Exception();
        else
        {
            Staging = ASPNetCoreEnvironment is not null && ASPNetCoreEnvironment.EndsWith(nameof(Staging));
            Production = ASPNetCoreEnvironment is not null && ASPNetCoreEnvironment.EndsWith(nameof(Production));
            Development = ASPNetCoreEnvironment is not null && ASPNetCoreEnvironment.EndsWith(nameof(Development));
        }
        Profile = GetProfile();
        AppSettingsFileName = GetAppSettingsFileName(processesCount);
    }

    private string GetProfile()
    {
        string result;
        if (Windows && Production)
            result = nameof(Production);
        else if (Windows && Staging)
            result = nameof(Staging);
        else if (Windows && Development)
            result = nameof(Development);
        else if (Linux && Production)
            result = nameof(Name.LinuxProduction);
        else if (Linux && Staging)
            result = nameof(Name.LinuxStaging);
        else if (Linux && Development)
            result = nameof(Name.LinuxDevelopment);
        else if (OSX && Production)
            result = nameof(Name.OSXProduction);
        else if (OSX && Staging)
            result = nameof(Name.OSXStaging);
        else if (OSX && Development)
            result = nameof(Name.OSXDevelopment);
        else
            throw new Exception();
        return result;
    }

    private string GetAppSettingsFileName(int? processesCount)
    {
        string result;
        if (Production)
        {
            if (processesCount is null)
                result = "appsettings.json";
            else
                result = $"appsettings.{processesCount}.json";
        }
        else
        {
            string environment;
            if (Staging)
                environment = nameof(Staging);
            else if (Development)
                environment = nameof(Development);
            else
                throw new Exception();
            if (processesCount is null)
                result = $"appsettings.{environment}.json";
            else
                result = $"appsettings.{environment}.{processesCount}.json";
        }
        return result;
    }

    public static string GetEnvironmentName(IsEnvironment isEnvironment)
    {
        string result;
        if (isEnvironment.Windows)
            result = nameof(Windows);
        else if (isEnvironment.Linux)
            result = nameof(Linux);
        else if (isEnvironment.OSX)
            result = nameof(OSX);
        else
            throw new Exception();
        return result;
    }

}