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

namespace View_by_Distance.Tests;

[TestClass]
public partial class UnitTestHardCoded
{

    private readonly string _Git;
    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 UnitTestHardCoded()
    {
        AppSettings appSettings;
        string workingDirectory;
        Configuration configuration;
        IsEnvironment isEnvironment;
        IConfigurationRoot configurationRoot;
        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()
            .AddUserSecrets<UnitTestHardCoded>();
        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);
        propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot);
        configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration);
        _Git = "d8013da9";
        _AppSettings = appSettings;
        _Configuration = configuration;
        _IsEnvironment = isEnvironment;
        _WorkingDirectory = workingDirectory;
        _ConfigurationRoot = configurationRoot;
        _PropertyConfiguration = propertyConfiguration;
    }

    private static void NonThrowTryCatch()
    {
        try
        { throw new Exception(); }
        catch (Exception) { }
    }

    [TestMethod]
    public void TestMethodNull()
    {
        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);
        NonThrowTryCatch();
    }

    [TestMethod]
    public void TestMethodDel()
    {
        string directory = "F:/Tmp/Phares/Compare/Images 2022-09-15 - 7390c13 - III - Results/E)Distance/2022-09-15/7680 x 4320/7680x4320 - Hog - Large/()/(637992984751968513)";
        if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory))
        {
            for (int i = 1; i < 11; i++)
                _ = IPath.DeleteEmptyDirectories(directory);
            Assert.IsTrue(true);
        }
        NonThrowTryCatch();
    }

    [TestMethod]
    public void TestMethodGetApproximateYears()
    {
        string personDisplayDirectory = string.Concat($"D:/1-Images-A/Images-{_Git}-Results/A2)People/{_Git}", "/{}/^/Sydney Dupray^9");
        if (Directory.Exists(Directory.GetDirectoryRoot(personDisplayDirectory)) && Directory.Exists(personDisplayDirectory))
        {
            char numberSign = '#';
            string? minusOne = null;
            char[] personCharacters = ['^'];
            string personDisplayDirectoryName = Path.GetFileName(personDisplayDirectory);
            string personBirthdayFormat = _Configuration.PropertyConfiguration.PersonBirthdayFormat;
            string[] personKeyDirectories = Directory.GetDirectories(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly);
            List<(string, PersonBirthday)> collection = IPersonBirthday.GetPersonBirthdays(personBirthdayFormat, personKeyDirectories, personDisplayDirectoryName);
            int? approximateYears = IAge.GetApproximateYears(personCharacters, personDisplayDirectoryName);
            if (approximateYears is null)
                throw new NullReferenceException(nameof(approximateYears));
            Assert.IsNotNull(approximateYears);
            Assert.IsTrue(approximateYears.Value == 9);
            string? change = IPersonContainer.VerifyAge(numberSign, personDisplayDirectory, minusOne, personDisplayDirectoryName, approximateYears, collection);
            Assert.IsNull(change);
        }
        NonThrowTryCatch();
    }

    [TestMethod]
    public void TestMethodDel2()
    {
        string directory = "F:/Tmp/Phares/Compare/Images 2022-09-15 - 7390c13 - III - Results/E)Distance/2022-09-15/7680 x 4320/7680x4320 - Hog - Large/()/(637992984751968513)";
        if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory))
        {
            for (int i = 1; i < 11; i++)
                _ = IPath.DeleteEmptyDirectories(directory);
            Assert.IsTrue(true);
        }
        NonThrowTryCatch();
    }

    private static (string?, string, string) Get(string[] segments)
    {
        (string?, string, string) result;
        if ((!segments[0].Contains('#') && (segments[3].Contains('~') || segments[3].Contains('#'))) || (segments[0].Contains('#') && !segments[3].Contains('#')))
            result = new(null, segments[3], segments[4]);
        else
            result = new(segments[0], segments[3], segments[4]);
        return result;
    }

    [TestMethod]
    public void TestMoveToVerify()
    {
        string http;
        string[] lines;
        string? minusOne;
        string? minusTwo;
        string[] segments;
        string[] beforeSegments;
        string[] matchDirectories;
        string? personKeyFormattedNew;
        string? personDisplayDirectory;
        string personDisplayDirectoryNew;
        string personDisplayDirectoryNameNew;
        string personKeyFormattedDirectoryNew;
        string sourceDirectory = @"";
        string sourceFile = @"\People - C.tsv";
        if (!File.Exists(sourceFile))
            lines = [];
        else
            lines = File.ReadAllLines(sourceFile);
        for (int i = 0; i < lines.Length; i++)
        {
            if (!lines[i].Contains("https://"))
                continue;
            segments = lines[i].Split('\t');
            beforeSegments = lines[i - 1].Split('\t');
            if (beforeSegments.Length < 4 || segments.Length < 5)
                continue;
            matchDirectories = Directory.GetDirectories(sourceDirectory, beforeSegments[0], SearchOption.AllDirectories);
            if (matchDirectories.Length != 1)
                continue;
            personDisplayDirectory = Path.GetDirectoryName(matchDirectories[0]);
            if (personDisplayDirectory is null)
                continue;
            minusOne = Path.GetDirectoryName(personDisplayDirectory);
            if (minusOne is null)
                continue;
            minusTwo = Path.GetDirectoryName(minusOne);
            if (minusTwo is null)
                continue;
            (personKeyFormattedNew, personDisplayDirectoryNameNew, http) = Get(segments);
            if (personKeyFormattedNew is null)
                continue;
            personDisplayDirectoryNew = Path.Combine(minusTwo, "Verify", personDisplayDirectoryNameNew);
            if (Directory.Exists(personDisplayDirectoryNew))
                continue;
            personKeyFormattedDirectoryNew = Path.Combine(personDisplayDirectoryNew, personKeyFormattedNew);
            Directory.Move(personDisplayDirectory, personDisplayDirectoryNew);
            _ = Directory.CreateDirectory(personKeyFormattedDirectoryNew);
            File.WriteAllText(Path.Combine(personKeyFormattedDirectoryNew, "Facebook.txt"), http);
        }
        Assert.IsNotNull(lines);
        NonThrowTryCatch();
    }

    [TestMethod]
    public void TestMethodRenameAbandoned()
    {
        string directory = string.Concat($"D:/1-Images-A/Images-{_Git}-Results/A2)People/{_Git}", "/{}/!/Abandoned");
        if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory))
        {
            string checkFile;
            string[] files = Directory.GetFiles(directory, "*.abd", SearchOption.TopDirectoryOnly);
            foreach (string file in files)
            {
                checkFile = file[..^4];
                if (File.Exists(checkFile))
                    continue;
                File.Move(file, checkFile);
            }
            Assert.IsTrue(true);
        }
        NonThrowTryCatch();
    }

    [TestMethod]
    public void TestMethodRenameDelete()
    {
        string directory = string.Concat($"D:/1-Images-A/Images-{_Git}-Results/A)Property/{_Git}", "/{}");
        if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory))
        {
            string checkFile;
            string[] files = Directory.GetFiles(directory, "*.del", SearchOption.AllDirectories);
            foreach (string file in files)
            {
                checkFile = file[..^4];
                if (File.Exists(checkFile))
                    continue;
                File.Move(file, checkFile);
            }
            Assert.IsTrue(true);
        }
        NonThrowTryCatch();
    }

    [TestMethod]
    public void TestMethodRenameOld()
    {
        string directory = $"D:/1-Images-A/Images-{_Git}-Results/E)Distance/{_Git}/()";
        if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory))
        {
            string checkFile;
            string[] files = Directory.GetFiles(directory, "*.old", SearchOption.AllDirectories);
            foreach (string file in files)
            {
                checkFile = file[..^4];
                if (File.Exists(checkFile))
                    continue;
                File.Move(file, checkFile);
            }
            Assert.IsTrue(true);
        }
        NonThrowTryCatch();
    }

    [TestMethod]
    public void TestMethodRenameDup()
    {
        string directory;
        directory = $"D:/1-Images-A/Images-{_Git}-Results/E)Distance/{_Git}/()";
        if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory))
        {
            string checkFile;
            string[] files = Directory.GetFiles(directory, "*.dup", SearchOption.AllDirectories);
            foreach (string file in files)
            {
                checkFile = file[..^4];
                if (File.Exists(checkFile))
                    continue;
                File.Move(file, checkFile);
            }
            Assert.IsTrue(true);
        }
        directory = string.Concat($"D:/1-Images-A/Images-{_Git}-Results/A2)People/{_Git}", "/{}/!");
        if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory))
        {
            string checkFile;
            string[] files = Directory.GetFiles(directory, "*.dup", SearchOption.AllDirectories);
            foreach (string file in files)
            {
                checkFile = file[..^4];
                if (File.Exists(checkFile))
                    continue;
                File.Move(file, checkFile);
            }
            Assert.IsTrue(true);
        }
        NonThrowTryCatch();
    }

    [TestMethod]
    public void TestMethodRename()
    {
        // string $directory = "D:/2-Images-B/Not-Copy-Copy-{_Git}";
        string directory = $"D:/1-Images-A/Images-{_Git}";
        // string $directory = "D:/2-Images-B/Not-Copy-Copy-{_Git}";
        if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory))
        {
            string[] directories = Directory.GetDirectories(directory, "*;*", SearchOption.AllDirectories);
            foreach (string subDirectory in directories.OrderByDescending(l => l.Length - l.Replace(@"\", string.Empty).Length))
            {
                if (!subDirectory.EndsWith(";9"))
                    continue;
                Directory.Move(subDirectory, $"{subDirectory[..^2]} !9");
            }
        }
        NonThrowTryCatch();
    }

    [TestMethod]
    public void TestMethodRenameForUnknown()
    {
        string directory = $"D:/1-Images-A/Images-{_Git}-Results/E)Distance/{_Git}/(RectInt-2023-06-19-less-0.99)";
        if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory))
        {
            string[] files = Directory.GetFiles(directory, "*.unk", SearchOption.AllDirectories);
            foreach (string file in files)
                File.Move(file, file[..^4]);
        }
        NonThrowTryCatch();
    }

    [TestMethod]
    public void TestMethodRenameForTicks()
    {
        string directory = $"D:/1-Images-A/Images-{_Git}-Results/A2)People/{_Git}/([])/ged";
        if (Directory.Exists(Path.GetPathRoot(directory)) && Directory.Exists(directory))
        {
            string checkName;
            DateTime dateTime;
            string weekOfYear;
            string checkDirectory;
            Calendar calendar = new CultureInfo("en-US").Calendar;
            string[] files = Directory.GetFiles(directory, "*.ged", SearchOption.TopDirectoryOnly);
            foreach (string file in files)
            {
                if (!long.TryParse(Path.GetFileNameWithoutExtension(file), out long ticks))
                    continue;
                dateTime = new(ticks);
                weekOfYear = calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
                checkDirectory = Path.Combine(directory, dateTime.Year.ToString(), $"{dateTime.Year}-Week-{weekOfYear}");
                checkName = Path.Combine(checkDirectory, Path.GetFileName(file));
                if (!Directory.Exists(checkDirectory))
                    _ = Directory.CreateDirectory(checkDirectory);
                if (File.Exists(checkName))
                    continue;
                File.Move(file, checkName);
            }
        }
        NonThrowTryCatch();
    }

    [TestMethod]
    public void TestMethodImmichAsset()
    {
        if (!string.IsNullOrEmpty(_Configuration.ImmichAssetsFile) && File.Exists(_Configuration.ImmichAssetsFile))
        {
            Dictionary<string, ImmichAsset> keyValuePairs = [];
            string json = File.ReadAllText(_Configuration.ImmichAssetsFile);
            ImmichAsset[]? immichAssets = JsonSerializer.Deserialize(json, ImmichAssetCollectionSourceGenerationContext.Default.ImmichAssetArray);
            if (immichAssets is not null)
            {
                foreach (ImmichAsset immichAsset in immichAssets)
                    keyValuePairs.Add(immichAsset.OriginalPath, immichAsset);
            }
            Assert.IsTrue(keyValuePairs.Count > 0);
        }
        NonThrowTryCatch();
    }

}