using Adaptation.Shared;
using Adaptation.Shared.Methods;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.Json;

namespace _Tests.Helpers;

public class Deposition
{

    internal static Tuple<string, string[], string[]> GetLogisticsColumnsAndBody(string fileFullName)
    {
        Tuple<string, string[], string[]> results;
        results = ProcessDataStandardFormat.GetLogisticsColumnsAndBody(fileFullName);
        Assert.IsFalse(string.IsNullOrEmpty(results.Item1));
        Assert.IsTrue(results.Item2.Length > 0, "Column check");
        Assert.IsTrue(results.Item3.Length > 0, "Body check");
        return results;
    }

    internal static Tuple<string, string[], string[]> GetLogisticsColumnsAndBody(string searchDirectory, string searchPattern)
    {
        Tuple<string, string[], string[]> results;
        if (searchPattern.Length > 3 && !searchPattern.Contains('*') && File.Exists(searchPattern))
            results = GetLogisticsColumnsAndBody(searchPattern);
        else
        {
            string[] pdsfFiles;
            pdsfFiles = Directory.GetFiles(searchDirectory, searchPattern, SearchOption.TopDirectoryOnly);
            if (!pdsfFiles.Any())
                _ = Process.Start("explorer.exe", searchDirectory);
            Assert.IsTrue(pdsfFiles.Any(), "GetFiles check");
            results = GetLogisticsColumnsAndBody(pdsfFiles[0]);
        }
        Assert.IsFalse(string.IsNullOrEmpty(results.Item1));
        Assert.IsTrue(results.Item2.Length > 0, "Column check");
        Assert.IsTrue(results.Item3.Length > 0, "Body check");
        return results;
    }

    internal static Tuple<string, string[], string[]> GetLogisticsColumnsAndBody(IFileRead fileRead, Logistics logistics, Tuple<string, Test[], JsonElement[], List<FileInfo>> extractResult, Tuple<string, string[], string[]> pdsf)
    {
        Tuple<string, string[], string[]> results;
        string text = ProcessDataStandardFormat.GetPDSFText(fileRead, logistics, extractResult.Item3, logisticsText: pdsf.Item1);
        string[] lines = text.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
        results = ProcessDataStandardFormat.GetLogisticsColumnsAndBody(logistics.ReportFullPath, lines);
        Assert.IsFalse(string.IsNullOrEmpty(results.Item1));
        Assert.IsTrue(results.Item2.Length > 0, "Column check");
        Assert.IsTrue(results.Item3.Length > 0, "Body check");
        return results;
    }

    internal static string[] GetItem2(Tuple<string, string[], string[]> pdsf, Tuple<string, string[], string[]> pdsfNew)
    {
        JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true };
        string jsonOld = JsonSerializer.Serialize(pdsf.Item2, pdsf.Item2.GetType(), jsonSerializerOptions);
        string jsonNew = JsonSerializer.Serialize(pdsfNew.Item2, pdsfNew.Item2.GetType(), jsonSerializerOptions);
        return new string[] { jsonOld, jsonNew };
    }

    internal static string[] GetItem3(Tuple<string, string[], string[]> pdsf, Tuple<string, string[], string[]> pdsfNew)
    {
        string joinOld = string.Join(Environment.NewLine, from l in pdsf.Item3 select string.Join('\t', from t in l.Split('\t') where !t.Contains(@"\\") select t));
        string joinNew = string.Join(Environment.NewLine, from l in pdsfNew.Item3 select string.Join('\t', from t in l.Split('\t') where !t.Contains(@"\\") select t));
        return new string[] { joinOld, joinNew };
    }

    internal static void UpdatePassDirectory(string searchDirectory)
    {
        DateTime dateTime = DateTime.Now;
        try
        { Directory.SetLastWriteTime(searchDirectory, dateTime); }
        catch (System.Exception) { }
        string ticksDirectory = Path.GetDirectoryName(searchDirectory);
        try
        { Directory.SetLastWriteTime(ticksDirectory, dateTime); }
        catch (System.Exception) { }
        string[] directories = Directory.GetDirectories(searchDirectory, "*", SearchOption.TopDirectoryOnly);
        foreach (string directory in directories)
        {
            try
            { Directory.SetLastWriteTime(directory, dateTime); }
            catch (System.Exception) { }
        }
    }

    internal static string GetFileName(MethodBase methodBase)
    {
        string result;
        string connectionName;
        string seperator = "__";
        string connectionNameAndTicks;
        string[] segments = methodBase.Name.Split(new string[] { seperator }, StringSplitOptions.None);
        string environment = segments[0];
        string rawVersionName = segments[1];
        string equipmentTypeDirectory = segments[2];
        string ticks = DateTime.Now.Ticks.ToString();
        string comment = segments[segments.Length - 1];
        string versionName = segments[1].Replace('_', '.');
        string before = string.Concat(environment, seperator, rawVersionName, seperator, equipmentTypeDirectory, seperator);
        string after = methodBase.Name.Substring(before.Length);
        if (after.Length < ticks.Length)
        {
            connectionName = after;
        }
        else
        {
            connectionNameAndTicks = after.Substring(0, after.Length - 2 - comment.Length);
            connectionName = connectionNameAndTicks.Substring(0, connectionNameAndTicks.Length - ticks.Length);
            ticks = connectionNameAndTicks.Substring(connectionName.Length);
        }
        result = Path.Combine(environment, equipmentTypeDirectory, versionName, $"{environment}__{rawVersionName}__{equipmentTypeDirectory}__{connectionName}", ticks, $"{connectionName.Replace('_', '-')}.json");
        if (result.Contains('/'))
            result = string.Concat('/', result);
        else
            result = string.Concat('\\', result);
        return result;
    }

    internal static void CompareSaveTSV(string textFileDirectory, string[] join)
    {
        if (join[0] != join[1])
        {
            _ = Process.Start("explorer.exe", textFileDirectory);
            File.WriteAllText(Path.Combine(textFileDirectory, "0.tsv"), join[0]);
            File.WriteAllText(Path.Combine(textFileDirectory, "1.tsv"), join[1]);
        }
    }

    internal static void CompareSaveJSON(string textFileDirectory, string[] json)
    {
        if (json[0] != json[1])
        {
            _ = Process.Start("explorer.exe", textFileDirectory);
            File.WriteAllText(Path.Combine(textFileDirectory, "0.json"), json[0]);
            File.WriteAllText(Path.Combine(textFileDirectory, "1.json"), json[1]);
        }
    }

    internal static void CompareSave(string textFileDirectory, Tuple<string, string[], string[]> pdsf, Tuple<string, string[], string[]> pdsfNew)
    {
        if (pdsf.Item1 != pdsfNew.Item1)
        {
            _ = Process.Start("explorer.exe", textFileDirectory);
            File.WriteAllText(Path.Combine(textFileDirectory, "0.dat"), pdsf.Item1);
            File.WriteAllText(Path.Combine(textFileDirectory, "1.dat"), pdsfNew.Item1);
        }
    }

    internal static IFileRead GetWriteConfigurationGetFileRead(MethodBase methodBase, string check, Shared.AdaptationTesting adaptationTesting)
    {
        IFileRead result;
        string[] fileNameAndJson = adaptationTesting.GetConfiguration(methodBase);
        Assert.IsTrue(fileNameAndJson[1].Contains(check));
        File.WriteAllText(fileNameAndJson[0], fileNameAndJson[1]);
        result = adaptationTesting.Get(methodBase, sourceFileLocation: string.Empty, sourceFileFilter: string.Empty, useCyclicalForDescription: false);
        Assert.IsFalse(string.IsNullOrEmpty(result.CellInstanceConnectionName));
        return result;
    }

    internal static string ReExtractComapareUpdatePassDirectory(string[] variables, IFileRead fileRead, Logistics logistics)
    {
        string result;
        Tuple<string, Test[], JsonElement[], List<FileInfo>> extractResult = fileRead.ReExtract();
        Assert.IsFalse(string.IsNullOrEmpty(extractResult?.Item1));
        Assert.IsTrue(extractResult.Item3.Length > 0, "extractResult Array Length check!");
        Assert.IsNotNull(extractResult.Item4);
        Tuple<string, string[], string[]> pdsf = GetLogisticsColumnsAndBody(variables[2], variables[4]);
        Tuple<string, string[], string[]> pdsfNew = GetLogisticsColumnsAndBody(fileRead, logistics, extractResult, pdsf);
        CompareSave(variables[5], pdsf, pdsfNew);
        Assert.IsTrue(pdsf.Item1 == pdsfNew.Item1, "Item1 check!");
        string[] json = GetItem2(pdsf, pdsfNew);
        CompareSaveJSON(variables[5], json);
        Assert.IsTrue(json[0] == json[1], "Item2 check!");
        string[] join = GetItem3(pdsf, pdsfNew);
        CompareSaveTSV(variables[5], join);
        Assert.IsTrue(join[0] == join[1], "Item3 (Join) check!");
        UpdatePassDirectory(variables[2]);
        result = extractResult.Item1;
        return result;
    }

}