using System.Diagnostics;
using System.IO;
using System;
using System.Collections.Generic;
using SolviaOneDriveKiller.Entities;
using System.Text.RegularExpressions;

namespace SolviaOneDriveKillerLib.Helpers
{
    public class HelperFunctions
    {
        public static string ExtractPathFromCommandLine(string commandLine)
        {
            // Use Regex to handle both quoted and unquoted paths
            var match = Regex.Match(commandLine, "^\"([^\"]+)\"|^([^ ]+)");
            if (match.Success)
            {
                return match.Groups[1].Value != "" ? match.Groups[1].Value : match.Groups[2].Value;
            }
            return string.Empty;
        }

        public static string ExtractArgumentsFromCommandLine(string commandLine, string extractedPath)
        {
            // Adjust extraction based on whether the path was quoted
            int pathEndIndex = extractedPath.StartsWith("\"") ? commandLine.IndexOf($"\"{extractedPath}\"") + extractedPath.Length + 2 : commandLine.IndexOf(extractedPath) + extractedPath.Length;

            if (pathEndIndex < commandLine.Length)
            {
                return commandLine.Substring(pathEndIndex+1).Trim();
            }

            return string.Empty;
        }

        public static bool UninstallOneDrive()
        {
            Logging.Log(Logging.LogLevel.Info, "UninstallOneDrive called");
            bool result = false;
            try
            {
                Logging.Log(Logging.LogLevel.Info, "Killing OneDrive processes");
                KillProcess("OneDrive");
                KillProcess("OneDriveSetup");
                Logging.Log(Logging.LogLevel.Info, "OneDrive processes killed");

                Logging.Log(Logging.LogLevel.Info, "Uninstalling OneDrive");

                string uninstallString = WindowsRegistry.GetOneDriveUninstallStringMachine();
                Logging.Log(Logging.LogLevel.Info, $"Uninstall string: {uninstallString}");

                var path = HelperFunctions.ExtractPathFromCommandLine(uninstallString);
                var args = ExtractArgumentsFromCommandLine(uninstallString, path);
                var ret = WindowsProcess.ExecuteCommand(path, args, true);

                Logging.Log(Logging.LogLevel.Info, "OneDrive uninstalled");
                result = true;
            }
            catch (Exception ex)
            {
                Logging.Log(Logging.LogLevel.Error, $"An error occurred while trying to uninstall OneDrive: {ex.Message}");
                Logging.SendToLog($"An error occurred while trying to uninstall OneDrive: {ex.Message}");
            }
            return result;
        }

        public static void GetProcessDetails(string processName)
        {
            Process[] processes = Process.GetProcessesByName(processName);

            if (processes.Length > 0)
            {
                foreach (Process process in processes)
                {
                    try
                    {
                        string exePath = process.MainModule.FileName;

                        FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(exePath);

                        Logging.Log(Logging.LogLevel.Info, $"Process: {processName} , ID: {process.Id}, Path: {exePath}, FileVersion: {fileVersionInfo.FileVersion}");
                    }
                    catch (Exception ex)
                    {
                        Logging.Log(Logging.LogLevel.Error, $"An error occurred while trying to get process details for {processName}: {ex.Message}");
                        Logging.SendToLog($"An error occurred while trying to get process details for {processName}: {ex.Message}");
                    }
                }
            }
        }

        public static bool KillProcess(string processName)
        {
            var processes = Process.GetProcessesByName(processName);
            Logging.Log(Logging.LogLevel.Info, $"Found {processes.Length} {processName} processes");
            Logging.SendToLog($"Found {processes.Length} {processName} processes");
            foreach (var process in processes)
            {
                Logging.Log(Logging.LogLevel.Info, $"Killing {processName} process with ID {process.Id}");
                Logging.SendToLog($"Killing {processName} process with ID {process.Id}");
                process.Kill();
                Logging.Log(Logging.LogLevel.Info, $"{processName} process with ID {process.Id} killed");
                Logging.SendToLog($"{processName} process with ID {process.Id} killed");
            }
            return true;
        }

        public static List<OneDriveSetups> GetOneDriveSetups()
        {
            List<OneDriveSetups> oneDriveSetupFiles = new List<OneDriveSetups>();
            string startDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Windows);

            SearchDirectory(startDirectory, oneDriveSetupFiles);

            return oneDriveSetupFiles;
        }
        private static void SearchDirectory(string directoryPath, List<OneDriveSetups> oneDriveSetupFiles)
        {
            try
            {
                // Get all files in the current directory.
                foreach (string file in Directory.EnumerateFiles(directoryPath, "OneDriveSetup.exe", SearchOption.TopDirectoryOnly))
                {
                    try
                    {
                        FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(file);
                        oneDriveSetupFiles.Add(new OneDriveSetups
                        {
                            FileName = versionInfo.FileName,
                            FileVersion = versionInfo.FileVersion
                        });
                    }
                    catch (Exception ex)
                    {
                        // Handle file-specific exceptions (e.g., unable to read file metadata).
                        Console.WriteLine($"Error processing file {file}: {ex.Message}");
                    }
                }

                // Recursively search subdirectories.
                foreach (string subDirectory in Directory.EnumerateDirectories(directoryPath))
                {
                    SearchDirectory(subDirectory, oneDriveSetupFiles);
                }
            }
            catch (UnauthorizedAccessException ex)
            {
                // Handle exceptions for directories that cannot be accessed.
                Console.WriteLine($"Access denied to directory {directoryPath}: {ex.Message}");
            }
            catch (Exception ex)
            {
                // Handle other potential exceptions.
                Console.WriteLine($"An error occurred accessing directory {directoryPath}: {ex.Message}");
            }
        }
    }
}
