using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Phares.Shared;
using Serilog;
using System.Diagnostics;
using System.Reflection;
using View_by_Distance.Shared.Models.Stateless.Methods;
using View_by_Distance.Tests.Models;

namespace View_by_Distance.Tests;

[TestClass]
public class UnitTestIsEnvironment
{

    private readonly ILogger _Logger;
    private readonly AppSettings _AppSettings;
    private readonly string _WorkingDirectory;
    private readonly IConfigurationRoot _ConfigurationRoot;

    public UnitTestIsEnvironment()
    {
        ILogger logger;
        AppSettings appSettings;
        string workingDirectory;
        IConfigurationRoot configurationRoot;
        LoggerConfiguration loggerConfiguration = new();
        Assembly assembly = Assembly.GetExecutingAssembly();
        IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
            .AddEnvironmentVariables()
            .AddJsonFile("appsettings.Development.json");
        configurationRoot = configurationBuilder.Build();
        appSettings = Models.Binder.AppSettings.Get(configurationRoot);
        if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
            throw new Exception("Working directory name must have a value!");
        workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName);
        Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
        _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot);
        Log.Logger = loggerConfiguration.CreateLogger();
        logger = Log.ForContext<UnitTestIsEnvironment>();
        logger.Information("Complete");
        _Logger = logger;
        _AppSettings = appSettings;
        _WorkingDirectory = workingDirectory;
        _ConfigurationRoot = configurationRoot;
    }

    [TestMethod]
    public void TestMethodNull()
    {
        Assert.IsFalse(_Logger is null);
        Assert.IsFalse(_AppSettings is null);
        Assert.IsFalse(_WorkingDirectory is null);
        Assert.IsFalse(_ConfigurationRoot is null);
    }

    [TestMethod]
    public void TestMethodTest()
    {
        List<string> jsonFiles = new();
        foreach (IConfigurationProvider configurationProvider in _ConfigurationRoot.Providers)
        {
            if (configurationProvider is not JsonConfigurationProvider jsonConfigurationProvider || jsonConfigurationProvider.Source.Path is null)
                continue;
            jsonFiles.Add(jsonConfigurationProvider.Source.Path);
        }
        Assert.IsTrue(jsonFiles.Any());
        foreach (string jsonFile in jsonFiles)
            _ = new IsEnvironment(jsonFile);
    }

    [TestMethod]
    [TestCategory(nameof(IsEnvironment.Name.WindowsDevelopment))]
    public void TestMethodTestCategory()
    {
        MethodBase? methodBase = new StackFrame().GetMethod();
        if (methodBase is not null)
        {
            TestCategoryAttribute? testCategoryAttribute = methodBase.GetCustomAttribute<TestCategoryAttribute>();
            if (testCategoryAttribute is not null)
            {
                foreach (string testCategory in testCategoryAttribute.TestCategories)
                    _ = new IsEnvironment(testCategory);
            }
        }
    }

    [TestMethod]
    public void TestMethodHardcoded()
    {
        _ = new IsEnvironment(isDevelopment: true, isStaging: false, isProduction: false);
        _ = new IsEnvironment(isDevelopment: false, isStaging: true, isProduction: false);
        _ = new IsEnvironment(isDevelopment: false, isStaging: false, isProduction: true);
    }

    [TestMethod]
    public void TestMethodAssembly()
    {
        Assembly assembly = Assembly.GetExecutingAssembly();
        bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug");
        IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero);
        _ = IsEnvironment.GetEnvironmentName(isEnvironment);
    }

}