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

namespace View_by_Distance.Tests;

[TestClass]
public class UnitTestResize
{

    private readonly ILogger _Logger;
    private readonly AppSettings _AppSettings;
    private readonly string _WorkingDirectory;
    private readonly Configuration _Configuration;
    private readonly IsEnvironment _IsEnvironment;
    private readonly IConfigurationRoot _ConfigurationRoot;
    private readonly Property.Models.Configuration _PropertyConfiguration;

    public UnitTestResize()
    {
        ILogger logger;
        AppSettings appSettings;
        string workingDirectory;
        Configuration configuration;
        IsEnvironment isEnvironment;
        IConfigurationRoot configurationRoot;
        LoggerConfiguration loggerConfiguration = new();
        Property.Models.Configuration propertyConfiguration;
        Assembly assembly = Assembly.GetExecutingAssembly();
        bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug");
        isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero);
        IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
            .AddEnvironmentVariables()
            .AddJsonFile(isEnvironment.AppSettingsFileName);
        configurationRoot = configurationBuilder.Build();
        appSettings = Models.Stateless.AppSettings.Get(configurationRoot);
        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<UnitTestResize>();
        propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory);
        configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration);
        logger.Information("Complete");
        _Logger = logger;
        _AppSettings = appSettings;
        _Configuration = configuration;
        _IsEnvironment = isEnvironment;
        _WorkingDirectory = workingDirectory;
        _ConfigurationRoot = configurationRoot;
        _PropertyConfiguration = propertyConfiguration;
    }

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

    private Property.Models.PropertyLogic GetPropertyLogic(bool reverse, Model? model, PredictorModel? predictorModel)
    {
        Property.Models.PropertyLogic result;
        if (_AppSettings.MaxDegreeOfParallelism is null)
            throw new NullReferenceException(nameof(_AppSettings.MaxDegreeOfParallelism));
        if (_Configuration?.PropertyConfiguration is null)
            throw new NullReferenceException(nameof(_Configuration.PropertyConfiguration));
        result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, reverse, model, predictorModel);
        return result;
    }

    [TestMethod]
    public void TestMethodResize()
    {
        // string sourceFileName = "IMG_0067.jpg";
        // string sourceDirectoryName = "Mackenzie Prom 2017";
        string sourceFileName = "Fall 2005 (113).jpg";
        string sourceDirectoryName = "=2005.3 Fall";
        if (_Configuration.ForceMetadataLastWriteTimeToCreationTime is null)
            throw new NullReferenceException(nameof(_Configuration.ForceMetadataLastWriteTimeToCreationTime));
        if (_Configuration.ForceResizeLastWriteTimeToCreationTime is null)
            throw new NullReferenceException(nameof(_Configuration.ForceResizeLastWriteTimeToCreationTime));
        if (_Configuration.OutputQuality is null)
            throw new NullReferenceException(nameof(_Configuration.OutputQuality));
        if (_Configuration.OverrideForResizeImages is null)
            throw new NullReferenceException(nameof(_Configuration.OverrideForResizeImages));
        if (_Configuration.PropertiesChangedForMetadata is null)
            throw new NullReferenceException(nameof(_Configuration.PropertiesChangedForMetadata));
        if (_Configuration.PropertiesChangedForResize is null)
            throw new NullReferenceException(nameof(_Configuration.PropertiesChangedForResize));
        Model? model = null;
        bool reverse = false;
        Property.Models.Item item;
        string original = "Original";
        List<string> parseExceptions = new();
        PredictorModel? predictorModel = null;
        bool isValidImageFormatExtension = true;
        Property.Models.A_Property? property = null;
        Dictionary<string, int[]> imageResizeKeyValuePairs;
        List<Tuple<string, DateTime>> subFileTuples = new();
        List<KeyValuePair<string, string>> metadataCollection;
        int length = _PropertyConfiguration.RootDirectory.Length;
        string outputResolution = _Configuration.OutputResolutions[0];
        Property.Models.PropertyLogic propertyLogic = GetPropertyLogic(reverse, model, predictorModel);
        string sourceDirectory = Path.Combine(_PropertyConfiguration.RootDirectory, sourceDirectoryName);
        string aPropertySingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_PropertyConfiguration, nameof(Property.Models.A_Property), "{}");
        B_Metadata metadata = new(_Configuration.ForceMetadataLastWriteTimeToCreationTime.Value, _Configuration.PropertiesChangedForMetadata.Value);
        (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters) = C_Resize.GetTuple(_Configuration.OutputExtension, _Configuration.OutputQuality.Value);
        C_Resize resize = new(_Configuration.ForceResizeLastWriteTimeToCreationTime.Value, _Configuration.OverrideForResizeImages.Value, _Configuration.PropertiesChangedForResize.Value, _Configuration.ValidResolutions, imageCodecInfo, encoderParameters);
        propertyLogic.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_PropertyConfiguration,
                                                                                                                   model,
                                                                                                                   predictorModel,
                                                                                                                   sourceDirectory,
                                                                                                                   nameof(Property.Models.A_Property),
                                                                                                                   outputResolution,
                                                                                                                   includeResizeGroup: false,
                                                                                                                   includeModel: false,
                                                                                                                   includePredictorModel: false,
                                                                                                                   contentDescription: string.Empty,
                                                                                                                   singletonDescription: "Properties for each image",
                                                                                                                   collectionDescription: string.Empty));
        metadata.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_PropertyConfiguration,
                                                                                                              model,
                                                                                                              predictorModel,
                                                                                                              sourceDirectory,
                                                                                                              nameof(B_Metadata),
                                                                                                              outputResolution,
                                                                                                              includeResizeGroup: false,
                                                                                                              includeModel: false,
                                                                                                              includePredictorModel: false,
                                                                                                              contentDescription: string.Empty,
                                                                                                              singletonDescription: "Metadata as key value pairs",
                                                                                                              collectionDescription: string.Empty));
        resize.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(_PropertyConfiguration,
                                                                                                            model,
                                                                                                            predictorModel,
                                                                                                            sourceDirectory,
                                                                                                            nameof(C_Resize),
                                                                                                            outputResolution,
                                                                                                            includeResizeGroup: true,
                                                                                                            includeModel: false,
                                                                                                            includePredictorModel: false,
                                                                                                            contentDescription: "Resized image",
                                                                                                            singletonDescription: "Resize dimensions for each resolution",
                                                                                                            collectionDescription: string.Empty));
        string sourceDirectoryFile = ".json";
        Property.Models.FileHolder fileHolder = new(Path.Combine(sourceDirectory, sourceFileName));
        string relativePath = Property.Models.Stateless.IPath.GetRelativePath(fileHolder.FullName, length);
        sourceDirectory = Path.Combine(aPropertySingletonDirectory, sourceDirectoryName);
        item = new(sourceDirectoryFile, relativePath, fileHolder, isValidImageFormatExtension, property, false, false);
        Assert.IsNotNull(item.ImageFileHolder);
        property = propertyLogic.GetProperty(item, subFileTuples, parseExceptions);
        (int _, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, item);
        imageResizeKeyValuePairs = resize.GetResizeKeyValuePairs(subFileTuples, parseExceptions, original, metadataCollection, property, item);
        Property.Models.FileHolder resizedFileHolder = new(Path.Combine(resize.AngleBracketCollection[0].Replace("<>", "()"), Path.GetFileName(item.ImageFileHolder.FullName)));
        item.SetResizedFileHolder(resizedFileHolder);
        resize.SaveResizedSubfile(outputResolution, subFileTuples, item, original, property, imageResizeKeyValuePairs);
        item.SetResizedFileHolder(Property.Models.FileHolder.Refresh(resizedFileHolder));
    }

}