using File_Folder_Helper.Models;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using WindowsShortcutFactory;

namespace File_Folder_Helper;

public class Worker : BackgroundService
{

    private readonly bool _IsSilent;
    private readonly List<string> _Args;
    private readonly ILogger<Worker> _Logger;
    private readonly AppSettings _AppSettings;
    private readonly ConsoleKey[] _ConsoleKeys;
    private readonly IHostApplicationLifetime _Lifetime;

    public Worker(ILogger<Worker> logger, IHostApplicationLifetime lifetime, List<string> args, AppSettings appSettings)
    {
        _Args = args;
        _Logger = logger;
        _Lifetime = lifetime;
        _AppSettings = appSettings;
        int silentIndex = args.IndexOf("s");
        _IsSilent = silentIndex > -1;
        if (_IsSilent)
            args.RemoveAt(silentIndex);
        _ConsoleKeys =
        [
            ConsoleKey.A,
            ConsoleKey.B,
            ConsoleKey.C,
            ConsoleKey.D,
            ConsoleKey.E,
            ConsoleKey.F,
            ConsoleKey.G,
            ConsoleKey.H,
            ConsoleKey.I,
            ConsoleKey.J,
            ConsoleKey.K,
            ConsoleKey.L,
            ConsoleKey.M,
            ConsoleKey.N,
            ConsoleKey.O,
            ConsoleKey.P,
            ConsoleKey.R,
            ConsoleKey.S,
            ConsoleKey.T,
            ConsoleKey.U,
            ConsoleKey.V,
            ConsoleKey.W,
            ConsoleKey.X,
            ConsoleKey.Y,
            ConsoleKey.Z,
            ConsoleKey.Delete
        ];
    }

    public override Task StartAsync(CancellationToken cancellationToken) =>
        base.StartAsync(cancellationToken);

    public override Task StopAsync(CancellationToken cancellationToken) =>
        base.StopAsync(cancellationToken);

    private void CreateWindowsShortcut()
    {
        object? assemblyName = AppContext.GetData("AssemblyName");
        string sendToDirectory = Environment.GetFolderPath(Environment.SpecialFolder.SendTo);
        string localApplicationData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
        if (Directory.Exists(sendToDirectory) && Directory.Exists(localApplicationData) && assemblyName is string assemblyNameValue)
        {
            string shortcut = Path.Combine(sendToDirectory, $"{assemblyNameValue}.lnk");
            string directory = Path.Combine(localApplicationData, _AppSettings.WorkingDirectoryName, assemblyNameValue);
            if (!Directory.Exists(directory))
                _ = Directory.CreateDirectory(directory);
            if (!File.Exists(sendToDirectory))
            {
                WindowsShortcut windowsShortcut = new()
                {
                    Arguments = "s X C:/ProgramData Day-Helper-2024-01-07 1",
                    Path = Path.Combine(directory, $"{assemblyNameValue}.exe"),
                    WorkingDirectory = AppContext.BaseDirectory
                };
                windowsShortcut.Save(shortcut);
                windowsShortcut.Dispose();
            }
        }
    }

    private void LogOptions()
    {
        _Logger.LogInformation("A) Save (Top Directory Only),");
        _Logger.LogInformation("B) Save (All Directories),");
        _Logger.LogInformation("C) Clipboard (Top Directory Only),");
        _Logger.LogInformation("D) Clipboard (All Directories),");
        _Logger.LogInformation("E) Everything delete recursive,");
        _Logger.LogInformation("F) Find and delete all *.log.* files then empty directories,");
        _Logger.LogInformation("G) Genealogical Data Communication,");
        // H
        _Logger.LogInformation("I) Ignore case and rename files to lowercase,");
        _Logger.LogInformation("J) Set Date from Json Entry,");
        _Logger.LogInformation("K) Kanban support,");
        _Logger.LogInformation("L) Log Merge (APC Log [0-9(8)]_*.log),");
        _Logger.LogInformation("M) Markdown Wiki Link Verification,");
        _Logger.LogInformation("N) Create Note Files,");
        _Logger.LogInformation("O) Oracle tnsNames.ora,");
        _Logger.LogInformation("P) PDF parse,");
        // Q
        _Logger.LogInformation("R) Rename to old, copy, delete old,");
        _Logger.LogInformation("S) Set Date from Zip Entry,");
        _Logger.LogInformation("T) *Ticks ~~Too long rename~~,");
        // U
        // V
        // W
        _Logger.LogInformation("X) Day Helpers,");
        _Logger.LogInformation("Y) Zip file(s) by directory with file,");
        _Logger.LogInformation("Z) Zip file(s) by date,");
        _Logger.LogInformation("Delete) Delete empty directories,");
    }

    protected override async Task ExecuteAsync(CancellationToken cancellationToken)
    {
        if (!cancellationToken.IsCancellationRequested)
            await Task.Delay(500, cancellationToken);
        if (_AppSettings is null)
            throw new NullReferenceException(nameof(_AppSettings));
        try
        {
            int? singleCharIndex = null;
            ConsoleKey consoleKey = ConsoleKey.End;
            for (int i = 0; i < _Args.Count; i++)
            {
                if (_Args[i].Length == 1 && Enum.TryParse(_Args[i], out consoleKey) && _ConsoleKeys.Contains(consoleKey))
                {
                    singleCharIndex = i;
                    break;
                }
            }
            string extension = Path.GetExtension(_Args[0]);
            if (consoleKey is not ConsoleKey.End && !_ConsoleKeys.Contains(consoleKey))
                consoleKey = ConsoleKey.End;
            if (singleCharIndex is not null)
                _Args.RemoveAt(singleCharIndex.Value);
            _Logger.LogInformation(consoleKey.ToString());
            if (_Args.Count == 0)
            {
                _Logger.LogWarning("Must pass a argument!");
                CreateWindowsShortcut();
            }
            else if (Directory.Exists(_Args[0].Split('~')[0]) || Directory.Exists(_Args[0]))
            {
                if (!_ConsoleKeys.Contains(consoleKey))
                {
                    for (int i = 0; i < int.MaxValue; i++)
                    {
                        if (_ConsoleKeys.Contains(consoleKey))
                            break;
                        LogOptions();
                        consoleKey = Console.ReadKey().Key;
                        _Logger.LogInformation(" ");
                    }
                }
                switch (consoleKey)
                {
                    case ConsoleKey.A:
                    case ConsoleKey.B:
                    case ConsoleKey.C:
                    case ConsoleKey.D:
                        Helpers.HelperSaveOrCopyContents.SaveOrCopyContents(_Logger, _Args[0], consoleKey);
                        break;
                    case ConsoleKey.E:
                        Helpers.HelperDeleteEmptyDirectories.EverythingDeleteRecursive(_Logger, _Args[0]);
                        break;
                    case ConsoleKey.F:
                        Helpers.HelperDeleteEmptyDirectories.DeleteOldLogFilesAndDeleteEmptyDirectories(_Logger, _Args[0]);
                        break;
                    case ConsoleKey.G:
                        Helpers.HelperGenealogicalDataCommunication.FileSystemToGenealogicalDataCommunication(_AppSettings, _Logger, _Args);
                        break;
                    case ConsoleKey.I:
                        Helpers.HelperSaveOrCopyContents.IgnoreCaseAndRenameFilesToLowercase(_Logger, _Args[0]);
                        break;
                    case ConsoleKey.J:
                        Helpers.HelperPackageFilesByDate.SetDateFromJsonEntry(_Logger, _Args[0]);
                        break;
                    case ConsoleKey.K:
                        Helpers.HelperKanbanMetadata.SetMetadata(_Logger, _Args[0]);
                        break;
                    case ConsoleKey.L:
                        Helpers.HelperLogMerge.LogMerge(_Args[0]);
                        break;
                    case ConsoleKey.N:
                        Helpers.HelperCreateNoteFiles.CreateNoteFiles(_Logger, _Args[0]);
                        break;
                    case ConsoleKey.M:
                        Helpers.HelperMarkdown.MarkdownWikiLinkVerification(_AppSettings, _Logger, _Args, cancellationToken);
                        break;
                    case ConsoleKey.O:
                        Helpers.HelperFindReplace.UpdateTnsNames(_Logger, _Args);
                        break;
                    case ConsoleKey.P:
                        Helpers.HelperPdfStripperWrapper.ParseSave(_Logger, _Args);
                        Helpers.HelperPdfStripperWrapper.ParseStrip(_Logger, _Args);
                        break;
                    case ConsoleKey.R:
                        Helpers.HelperRenameToOldMoveDeleteOldMerge.RenameToOldMoveDeleteOld(_Logger, _Args[0]);
                        break;
                    case ConsoleKey.S:
                        _ = Helpers.HelperZipFilesBy.ExtractKeyFileAndSetDateFromZipEntry(_Logger, _Args[0]);
                        break;
                    case ConsoleKey.T:
                        Helpers.HelperTooLong.UpdateDateVerifyAndGetTicksDirectories(_Logger, _AppSettings, _Args[0]);
                        // Helpers.HelperTooLong.TooLong(_Args[0], delete: false);
                        // Helpers.HelperTooLong.TooLong(_Args[0], delete: true);
                        break;
                    case ConsoleKey.X:
                        Helpers.HelperDay.Select(_AppSettings, _Logger, _Args, cancellationToken);
                        break;
                    case ConsoleKey.Y:
                        Helpers.HelperZipFilesBy.ZipFilesByDirectoryWithFile(_Logger, _Args[0]);
                        break;
                    case ConsoleKey.Z:
                        _ = Helpers.HelperZipFilesBy.ZipFilesByDate(_Logger, _Args[0]);
                        break;
                    default:
                        switch (consoleKey)
                        {
                            case ConsoleKey.Delete:
                                Helpers.HelperDeleteEmptyDirectories.DeleteEmptyDirectories(_Logger, _Args[0]);
                                break;
                            default:
                                throw new Exception();
                        }
                        break;
                }
            }
            else if (_AppSettings.ValidImageFormatExtensions.Contains(extension) && File.Exists(_Args[0]))
                Helpers.Exif.HelperExif.DragAndDrop(_Logger, _Args[0]);
            else
                throw new Exception(_Args[0]);
        }
        catch (Exception ex)
        { _Logger.LogError("{Message}{NewLine}{_Args}{NewLine}{StackTrace}", ex.Message, Environment.NewLine, string.Join(' ', _Args), Environment.NewLine, ex.StackTrace); }
        if (_IsSilent)
            _Logger.LogInformation("Done. Bye");
        else
        {
            _Logger.LogInformation("Done. Press 'Enter' to end");
            _ = Console.ReadLine();
        }
        _Lifetime.StopApplication();
    }

}