using Adaptation._Tests.Shared.Log;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.IO;

namespace Adaptation._Tests.Shared;

public class LoggingUnitTesting : UnitTesting, IDisposable
{

    protected ILogger<object> _Logger;
    protected ILoggerFactory _LoggerFactory;
    protected readonly LogLevel? _DefaultLogLevel;
    protected readonly LogLevel? _Log4netProviderLogLevel;
    protected readonly IConfigurationRoot _ConfigurationRoot;
    public ILogger<object> Logger => _Logger;
    public LogLevel? DefaultLogLevel => _DefaultLogLevel;
    public ILoggerFactory LoggerFactory => _LoggerFactory;
    public IConfigurationRoot ConfigurationRoot => _ConfigurationRoot;
    public LogLevel? Log4netProviderLogLevel => _Log4netProviderLogLevel;

    public LoggingUnitTesting(TestContext testContext, Type declaringType) :
        base(testContext, declaringType)
    {
        _LoggerFactory = new LoggerFactory();
        if (testContext is null || declaringType is null || _IsEnvironment is null)
        {
            _ConfigurationRoot = null;
            _DefaultLogLevel = null;
            _Log4netProviderLogLevel = null;
        }
        else
        {
            LogLevel logLevel;
            IConfigurationSection configurationSection;
            List<LogLevel> logLevels = new();
            string defaultLogLevelSection = "Logging:LogLevel:Default";
            string log4netProviderLogLevelSection = "Logging:LogLevel:Log4netProvider";
            string[] sections = new string[] { defaultLogLevelSection, log4netProviderLogLevelSection };
            IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
                .AddEnvironmentVariables()
                .AddJsonFile(_IsEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
            _ConfigurationRoot = configurationBuilder.Build();
            foreach (string section in sections)
            {
                configurationSection = _ConfigurationRoot.GetSection(section);
                if (configurationSection is null)
                    logLevel = LogLevel.Debug;
                else if (!Enum.TryParse(configurationSection.Value, out logLevel))
                    logLevel = LogLevel.Debug;
                logLevels.Add(logLevel);
            }
            _DefaultLogLevel = logLevels[0];
            _Log4netProviderLogLevel = logLevels[1];
        }
        if (DefaultLogLevel.HasValue)
            _LoggerFactory.AddProvider(new DebugProvider(DefaultLogLevel.Value));
        if (DefaultLogLevel.HasValue)
            _LoggerFactory.AddProvider(new ConsoleProvider(DefaultLogLevel.Value));
        _Logger = _LoggerFactory.CreateLogger<object>();
    }

    public static string GetEnvironmentSpecialDirectory()
    {
        string result = string.Empty;
        string traceFile;
        List<string> directories = new();
        Environment.SpecialFolder[] specialFolders = new Environment.SpecialFolder[]
        {
                    Environment.SpecialFolder.LocalApplicationData,
                    Environment.SpecialFolder.ApplicationData,
                    Environment.SpecialFolder.History,
                    Environment.SpecialFolder.CommonApplicationData,
                    Environment.SpecialFolder.InternetCache
        };
        foreach (Environment.SpecialFolder specialFolder in specialFolders)
            directories.Add(Environment.GetFolderPath(specialFolder));
        foreach (string directory in directories)
        {
            for (int i = 1; i < 3; i++)
            {
                if (i == 1)
                    result = directory;
                else
                    result = string.Concat("D", directory.Substring(1));
                try
                {
                    if (!Directory.Exists(result))
                        _ = Directory.CreateDirectory(result);
                    traceFile = string.Concat(result, @"\", DateTime.Now.Ticks, ".txt");
                    File.WriteAllText(traceFile, traceFile);
                    File.Delete(traceFile);
                    break;
                }
                catch (Exception) { result = string.Empty; }
            }
            if (!string.IsNullOrEmpty(result))
                break;
        }
        return result;
    }

    public void Dispose()
    {
        _LoggerFactory.Dispose();
        GC.SuppressFinalize(this);
    }

}