using Microsoft.Extensions.Logging;
using System.Diagnostics;

namespace File_Folder_Helper.Helpers;

internal static class HelperPdfStripperWrapper
{

    private record Input(string? DestinationDirectory,
                         string? Key,
                         char? Parser);

    private const char _Linc = 'L';
    private const char _Ghost = 'G';
    private const char _Kofax = 'K';
    private const char _Stripper = 'S';

    private static string GetTextFromPDF(string pdfTextStripperFileName, string sourceFileNamePdf, string destinationFileName)
    {
        string result;
        ProcessStartInfo processStartInfo = new(pdfTextStripperFileName, $"s \"{sourceFileNamePdf}\"")
        {
            UseShellExecute = false,
            RedirectStandardError = true,
            RedirectStandardOutput = true,
        };
        Process? process = Process.Start(processStartInfo);
        _ = process?.WaitForExit(30000);
        if (!File.Exists(destinationFileName))
            result = string.Empty;
        else
            result = File.ReadAllText(destinationFileName);
        return result;
    }

    private static string GetLincTextFromPDF(string lincPDFCFileName, string sourceFileNamePdf, string destinationFileName)
    {
        string result;
        if (File.Exists(destinationFileName))
            File.Delete(destinationFileName);
        string arguments = string.Concat("-i \"", sourceFileNamePdf, "\" -o \"", destinationFileName, "\"");
        Process? process = Process.Start(lincPDFCFileName, arguments);
        _ = process?.WaitForExit(30000);
        if (!File.Exists(destinationFileName))
            result = string.Empty;
        else
            result = File.ReadAllText(destinationFileName);
        return result;
    }

    private static string GetGhostTextFromPDF(string ghostPCLFileName, string sourceFileNamePdf, string destinationFileName)
    {
        string result;
        if (File.Exists(destinationFileName))
            File.Delete(destinationFileName);
        string arguments = $"-dSAFER -dBATCH -dNOPAUSE -dFIXEDMEDIA -dFitPage -dAutoRotatePages=/All -dDEVICEWIDTHPOINTS=792 -dDEVICEHEIGHTPOINTS=612 -sOutputFile=\"{destinationFileName}\" -sDEVICE=pdfwrite \"{sourceFileNamePdf}\"";
        Process? process = Process.Start(ghostPCLFileName, arguments);
        _ = process?.WaitForExit(30000);
        if (!File.Exists(destinationFileName))
            result = string.Empty;
        else
            result = File.ReadAllText(destinationFileName);
        return result;
    }

    private static string GetKofaxTextFromPDF(string kofaxFileName, string sourceFileNamePdf, string destinationFileName)
    {
        string result;
        if (File.Exists(destinationFileName))
            File.Delete(destinationFileName);
        string arguments = $"-i\"{sourceFileNamePdf}\" -o\"{destinationFileName}\" -ttxt";
        Process? process = Process.Start(kofaxFileName, arguments);
        _ = process?.WaitForExit(30000);
        if (!File.Exists(destinationFileName))
            result = string.Empty;
        else
            result = File.ReadAllText(destinationFileName);
        return result;
    }

    private static Input GetInput(List<string> args)
    {
        string? d = null;
        string? k = null;
        string? p = null;
        for (int i = 1; i < args.Count; i++)
        {
            if (args[i].Length == 2 && i + 1 < args.Count)
            {
                if (args[i][1] == 'd')
                    d = Path.GetFullPath(args[i + 1]);
                else if (args[i][1] == 'k')
                    k = args[i + 1].Trim();
                else if (args[i][1] == 'p')
                    p = args[i + 1];
                i++;
            }
        }
        string directoryName = Path.GetFileName(args[0]);
        if (!string.IsNullOrEmpty(d) && !d.EndsWith(directoryName))
            d = Path.Combine(d, directoryName);
        if (!string.IsNullOrEmpty(d) && !Directory.Exists(d))
            _ = Directory.CreateDirectory(d);
        char? parser = p is null ? null : p == "S" ? _Stripper : p == "G" ? _Ghost : p == "K" ? _Kofax : p == "L" ? _Linc : null;
        return new(d, k, parser);
    }

    private static void ParseSave(ILogger log, string pdfTextStripperFileName, string ghostPCLFileName, string kofaxFileName, string lincPDFCFileName, string destinationDirectory, char parser, string[] files)
    {
        string text;
        string destinationFileName;
        if (!Directory.Exists(destinationDirectory))
            _ = Directory.CreateDirectory(destinationDirectory);
        foreach (string file in files)
        {
            destinationFileName = Path.Combine(destinationDirectory, $"{file}.txt");
            if (parser == _Kofax)
                text = GetKofaxTextFromPDF(kofaxFileName, file, destinationFileName);
            else if (parser == _Linc)
                text = GetLincTextFromPDF(lincPDFCFileName, file, destinationFileName);
            else if (parser == _Ghost)
                text = GetGhostTextFromPDF(ghostPCLFileName, file, destinationFileName);
            else if (parser == _Stripper)
                text = GetTextFromPDF(pdfTextStripperFileName, file, destinationFileName);
            else
                throw new NotImplementedException();
            log.LogInformation("<{file}> == {length}", Path.GetFileName(file), text.Length);
        }
    }

    private static void ParseStrip(ILogger log, string destinationDirectory, string key, string[] files)
    {
        string[] lines;
        string fileName;
        string[] segments;
        List<string> collection = [];
        foreach (string file in files)
        {
            lines = File.ReadAllLines(file);
            fileName = Path.GetFileName(file);
            foreach (string line in lines)
            {
                segments = line.Split(':');
                if (segments.Length < 2)
                    continue;
                if (segments[0].Trim() != key)
                    continue;
                collection.Add($"{fileName}\t{line}");
            }
            log.LogInformation("<{fileName}>", fileName);
        }
        if (collection.Count > 0)
            File.WriteAllLines(Path.Combine(destinationDirectory, $"{key}.txt"), collection);
    }

    internal static void ParseSave(ILogger log, List<string> args)
    {
        // <ItemGroup>
        //     <PackageReference Include="Infineon.Mesa.PDF.Text.Stripper" Version="4.8.0.1"><NoWarn>NU1701</NoWarn></PackageReference>
        // </ItemGroup>
        // <ItemGroup>
        //     <None Include="\\mestsa003.infineon.com\EC_EAFRepository\Staging\DeploymentStorage\GhostPCL\gpcl6win64\gpcl6dll64.dll">
        //         <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        //     </None>
        //     <None Include="\\mestsa003.infineon.com\EC_EAFRepository\Staging\DeploymentStorage\GhostPCL\gpcl6win64\gpcl6win64.exe">
        //         <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        //     </None>
        //     <None Include="\\mestsa003.infineon.com\EC_EAFRepository\Staging\DeploymentStorage\LincPDFC\v2.6.6.21\LincPDFC.exe">
        //         <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        //     </None>
        // </ItemGroup>
        string sourceDirectory = Path.GetFullPath(args[0]);
        Input input = GetInput(args);
        if (string.IsNullOrEmpty(input.DestinationDirectory))
            log.LogInformation("-d <{DestinationDirectory}> wasn't supplied!", nameof(input.DestinationDirectory));
        else
        {
            if (input.Parser is null)
                log.LogInformation("-p <{Parser}> wasn't supplied!", nameof(input.Parser));
            else
            {
                string pdfTextStripperFileName = Path.Combine(AppContext.BaseDirectory, "PDF-Text-Stripper.exe");
                if (input.Parser == _Stripper && !File.Exists(pdfTextStripperFileName))
                    log.LogInformation("exe <{pdfTextStripperFileName}> doesn't exist!", pdfTextStripperFileName);
                else
                {
                    string ghostPCLFileName = Path.Combine(AppContext.BaseDirectory, "gPcl6win64.exe");
                    if (input.Parser == _Ghost && !File.Exists(ghostPCLFileName))
                        log.LogInformation("exe <{ghostPCLFileName}> doesn't exist!", ghostPCLFileName);
                    else
                    {
                        string kofaxFileName = "C:/Program Files (x86)/Kofax/Power PDF 50/batchConverter.com";
                        if (input.Parser == _Kofax && !File.Exists(kofaxFileName))
                            log.LogInformation("exe <{kofaxFileName}> doesn't exist!", kofaxFileName);
                        else
                        {
                            string lincPDFCFileName = Path.Combine(AppContext.BaseDirectory, "LincPDFC.exe");
                            if (input.Parser == _Kofax && !File.Exists(lincPDFCFileName))
                                log.LogInformation("exe <{lincPDFCFileName}> doesn't exist!", lincPDFCFileName);
                            else
                            {
                                string[] files = Directory.GetFiles(sourceDirectory, "*.pdf", SearchOption.TopDirectoryOnly);
                                if (files.Length == 0)
                                    log.LogInformation("Length == {length}", files.Length);
                                else
                                    ParseSave(log, pdfTextStripperFileName, ghostPCLFileName, kofaxFileName, lincPDFCFileName, input.DestinationDirectory, input.Parser.Value, files);
                            }
                        }
                    }
                }
            }
        }
    }

    internal static void ParseStrip(ILogger log, List<string> args)
    {
        if (DateTime.Now > new DateTime(2023, 9, 15))
            log.LogInformation("This helper was a short term helper!");
        else
        {
            Input input = GetInput(args);
            if (string.IsNullOrEmpty(input.DestinationDirectory))
                log.LogInformation("-d <{DestinationDirectory}> wasn't supplied!", nameof(input.DestinationDirectory));
            else
            {
                if (string.IsNullOrEmpty(input.Key))
                    log.LogInformation("-k <{key}> wasn't supplied!", nameof(input.Key));
                else
                {
                    string[] files = Directory.GetFiles(input.DestinationDirectory, "*.txt", SearchOption.TopDirectoryOnly);
                    if (files.Length == 0)
                        log.LogInformation("Length == {length}", files.Length);
                    else
                        ParseStrip(log, input.DestinationDirectory, input.Key, files);
                }
            }
        }
    }

}