using System.Runtime.InteropServices;
using System.Text;
using System.Xml.Linq;

#pragma warning disable IDE0130 // Namespace does not match folder structure
namespace ArmaRAMDb
#pragma warning restore IDE0130 // Namespace does not match folder structure
{
    public class CallContext
    {
        public ulong SteamId { get; set; }
        public string FileSource { get; set; }
        public string MissionName { get; set; }
        public string ServerName { get; set; }
        public short RemoteExecutedOwner { get; set; }
    }

    public class Main
    {
        private const string ARDB_VERSION = "1.0.0";
        public const int ARDB_BUFFERSIZE = 20480;
#pragma warning disable CA2211 // Non-constant fields should not be visible
        public static RAMDb db;
#pragma warning restore CA2211 // Non-constant fields should not be visible
        public static readonly string DEFAULT_ARDB_PATH = $"@ramdb{Path.DirectorySeparatorChar}ArmaRAMDb.ardb";
        public static string ARDB_LOGFOLDER { get; private set; } = $"{Path.DirectorySeparatorChar}@ramdb{Path.DirectorySeparatorChar}logs";
        public static bool ARDB_DEBUG {get; private set; } = false;
        public static bool ARDB_INITCHECK {get; private set; } = false;
        public static string STEAMID {get; private set; } = "";
        public static bool ARDB_CONTEXTLOG {get; private set; } = false;
        public static IntPtr ARDB_CONTEXT { get; private set; }
        private static int numCalls = 0;
        public static bool ARDB_ISLOADED { get; private set; } = false;
        public static ExtensionCallback Callback { get; private set; }
        public delegate int ExtensionCallback([MarshalAs(UnmanagedType.LPStr)] string name, [MarshalAs(UnmanagedType.LPStr)] string function, [MarshalAs(UnmanagedType.LPStr)] string data);

        public static void ARDB_Init()
        {
            char[] separator = ['='];
            string[] commandLineArgs = Environment.GetCommandLineArgs();
            string str = "";

            for (int index = 0; index < commandLineArgs.Length; index++)
            {
                string[] strArray = commandLineArgs[index].Split(separator, StringSplitOptions.RemoveEmptyEntries);
                if (strArray[0].Equals("-ardb", StringComparison.CurrentCultureIgnoreCase))
                {
                    str = strArray[1];
                    break;
                }
            }

            if (str == "")
                str = $"@ramdb{Path.DirectorySeparatorChar}config.xml";

            if (File.Exists(Environment.CurrentDirectory + $"{Path.DirectorySeparatorChar}{str}"))
            {
                try 
                {
                    var configXml = XElement.Load(Environment.CurrentDirectory + $"{Path.DirectorySeparatorChar}{str}");
                    List<string> settings = [.. configXml.Elements().Select(element => (string)element)];
                    
                    // Parse existing settings
                    if (settings.Count >= 2)
                    {
                        if (bool.TryParse(settings[0], out bool res0))
                            ARDB_CONTEXTLOG = res0;
                        if (bool.TryParse(settings[1], out bool res1))
                            ARDB_DEBUG = res1;
                    }
                    
                    // Parse new backup settings
                    if (settings.Count >= 5)
                    {
                        if (bool.TryParse(settings[2], out bool autoBackup))
                            RAMDb.AutoBackupEnabled = autoBackup;
                        
                        if (int.TryParse(settings[3], out int backupFreq) && backupFreq > 0)
                            RAMDb.BackupFrequencyMinutes = backupFreq;
                        
                        if (int.TryParse(settings[4], out int maxBackups) && maxBackups > 0)
                            RAMDb.MaxBackupsToKeep = maxBackups;
                    }
                    
                    Log($"Config file found! Context Mode: {ARDB_CONTEXTLOG}! Debug Mode: {ARDB_DEBUG}! " +
                        $"Auto Backup: {RAMDb.AutoBackupEnabled} (every {RAMDb.BackupFrequencyMinutes} min, keep {RAMDb.MaxBackupsToKeep})", "action");

                    db ??= new RAMDb();
                    
                    // First, load any existing RDB file
                    if (File.Exists(Path.Combine(Environment.CurrentDirectory, DEFAULT_ARDB_PATH)))
                    {
                        db.ImportFromBinary();
                        ARDB_ISLOADED = true;
                        Log("Existing ARDB data loaded during initialization", "action");
                    }
                    
                    // Then initialize automatic backup if enabled
                    if (RAMDb.AutoBackupEnabled)
                    {
                        RAMDb.InitializeAutoBackup();
                    }
                }
                catch (Exception ex)
                {
                    Log($"Error reading config file: {ex.Message}", "error");
                    Log("Default Settings Loaded.", "action");
                }
            }
            else
            {
                Log("Config file not found! Default Settings Loaded.", "action");
            }

            ARDB_INITCHECK = true;
        }

        public static void Log(string msg, string type)
        {
            if (!ARDB_DEBUG)
                return;
            string logFileName = type + ".log";
            string path = Environment.CurrentDirectory + ARDB_LOGFOLDER;

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            using StreamWriter sw = new(Path.Combine(path, logFileName), true);
            sw.WriteLine(DateTime.Now.ToString() + " >> " + msg);
        }

        /// <summary>
        /// Called only once when Arma 3 loads the extension.
        /// </summary>
        /// <param name="func">Pointer to Arma 3's callback function</param>
        [UnmanagedCallersOnly(EntryPoint = "RVExtensionRegisterCallback")]
        public unsafe static void RVExtensionRegisterCallback(nint func)
        {
            Callback = Marshal.GetDelegateForFunctionPointer<ExtensionCallback>(func);
        }

        /// <summary>
        /// Called only once when Arma 3 loads the extension.
        /// The output will be written in the RPT logs.
        /// </summary>
        /// <param name="output">A pointer to the output buffer</param>
        /// <param name="outputSize">The maximum length of the buffer (always 32 for this particular method)</param>
        [UnmanagedCallersOnly(EntryPoint = "RVExtensionVersion")]
    #pragma warning disable IDE0060 // Remove unused parameter
        public unsafe static void RVExtensionVersion(char* output, int outputSize)
    #pragma warning restore IDE0060 // Remove unused parameter
        {
            WriteOutput(output, ARDB_VERSION);
        }

        /// <summary>
        /// Called before every RVExtension/RVExtensionArgs execution, providing context about where the call came from.
        /// </summary>
        /// <param name="argv">
        /// Array of pointers to null-terminated strings containing:
        /// [0] - Steam 64bit UserID
        /// [1] - FileSource
        /// [2] - MissionName
        /// [3] - ServerName
        /// [4] - Machine Network ID
        /// </param>
        /// <param name="argc">Number of arguments in the argv array (always 5).</param>
        [UnmanagedCallersOnly(EntryPoint = "RVExtensionContext")]
        public unsafe static int RVExtensionContext(char** argv, int argc)
        {
            ARDB_CONTEXT = (IntPtr)argv;

            var context = new CallContext
            {
                SteamId = ulong.Parse(Marshal.PtrToStringAnsi((IntPtr)argv[0])),
                FileSource = Marshal.PtrToStringAnsi((IntPtr)argv[1]),
                MissionName = Marshal.PtrToStringAnsi((IntPtr)argv[2]),
                ServerName = Marshal.PtrToStringAnsi((IntPtr)argv[3]),
                RemoteExecutedOwner = short.Parse(Marshal.PtrToStringAnsi((IntPtr)argv[4]))
            };

            STEAMID = context.SteamId.ToString();

            if (ARDB_CONTEXTLOG)
            {
                Log($"Context: SteamID={context.SteamId}, FileSource={context.FileSource}, MissionName={context.MissionName}, ServerName={context.ServerName}, RemoteExecutedOwner={context.RemoteExecutedOwner}", "context");
            }

            return 100;
        }

        /// <summary>
        /// The entry point for the default "callExtension" command.
        /// </summary>
        /// <param name="output">A pointer to the output buffer</param>
        /// <param name="outputSize">The maximum size of the buffer (20480 bytes)</param>
        /// <param name="function">The function identifier passed in "callExtension"</param>
        [UnmanagedCallersOnly(EntryPoint = "RVExtension")]
    #pragma warning disable IDE0060 // Remove unused parameter
        public unsafe static void RVExtension(char* output, int outputSize, char* function)
    #pragma warning restore IDE0060 // Remove unused parameter
        {
            if (!ARDB_INITCHECK)
                ARDB_Init();

            numCalls++;

            var func = GetString(function);
            switch (func.ToLower())
            {
                case "time":
                    DateTime timeNow = DateTime.Now;
                    string timeNowString = timeNow.ToString("dd:MM:yyyy HH:mm:ss");
                    WriteOutput(output, timeNowString);
                    break;
                default:
                    WriteOutput(output, func);
                    break;
            }
        }

        /// <summary>
        /// The entry point for the "callExtension" command with function arguments.
        /// </summary>
        /// <param name="output">A pointer to the output buffer</param>
        /// <param name="outputSize">The maximum size of the buffer (20480 bytes)</param>
        /// <param name="function">The function identifier passed in "callExtension"</param>
        /// <param name="argv">The args passed to "callExtension" as a string array</param>
        /// <param name="argc">Number of elements in "argv"</param>
        /// <returns>The return code</returns>
        [UnmanagedCallersOnly(EntryPoint = "RVExtensionArgs")]
        public unsafe static int RVExtensionArgs(char* output, int outputSize, char* function, char** argv, int argc)
        {
            if (!ARDB_INITCHECK)
                ARDB_Init();

            numCalls++;

            var _id = DateTimeOffset.Now.ToUnixTimeMilliseconds();
            var func = GetString(function);
            
            List<string> args = [.. Enumerable.Range(0, argc).Select(i => GetString(argv[i]))];

            switch (func.ToLower())
            {
                case "del":
                    HandleDeleteOperation(args, argc);
                    WriteOutput(output, "Async");
                    return 200;
                case "get":
                    HandleGetOperation(_id, args, argc);
                    WriteOutput(output, $"[\"{_id}_get\",{args[0]}]");
                    return 100;
                case "hdel":
                    HandleHDelOperation();
                    WriteOutput(output, "Async");
                    return 200;
                case "hdelid":
                    HandleHDelIdOperation(args, argc);
                    WriteOutput(output, "Async");
                    return 200;
                case "hget":
                    HandleHGetOperation(_id, args, argc);
                    WriteOutput(output, $"[\"{_id}_hget\",{args[1]}]");
                    return 100;
                case "hgetid":
                    HandleHGetIdOperation(_id, args, argc);
                    WriteOutput(output, $"[\"{_id}_hgetid\",{args[0]}]");
                    return 100;
                case "hgetall":
                    HandleHGetAllOperation(_id, args, argc);
                    WriteOutput(output, $"[\"{_id}_hgetall\",{args[0]}]");
                    return 100;
                case "hgetallid":
                    HandleHGetAllIdOperation(_id, args, argc);
                    WriteOutput(output, $"[\"{_id}_hgetallid\",{args[0]}]");
                    return 100;
                case "hrem":
                    HandleHRemOperation(args, argc);
                    WriteOutput(output, "Async");
                    return 200;
                case "hremid":
                    HandleHRemIdOperation(args, argc);
                    WriteOutput(output, "Async");
                    return 200;
                case "hset":
                    HandleHSetOperation(args, argc);
                    WriteOutput(output, "Async");
                    return 200;
                case "hsetid":
                    HandleHSetIdOperation(args, argc);
                    WriteOutput(output, "Async");
                    return 200;
                case "isloaded":
                    WriteOutput(output, ARDB_ISLOADED.ToString().ToLower());
                    return 100;
                case "listadd":
                    HandleListAddOperation(args, argc);
                    WriteOutput(output, "Async");
                    return 200;
                case "listdel":
                    HandleListDelOperation(args, argc);
                    WriteOutput(output, "Async");
                    return 200;
                case "listidx":
                    HandleListIdxOperation(_id, args, argc);
                    WriteOutput(output, $"[\"{_id}_listindex\",{args[0]}]");
                    return 100;
                case "listrem":
                   HandleListRemOperation(args, argc);
                   WriteOutput(output, "Async");
                   return 200;
                case "listrng":
                    HandleListRngOperation(_id, args, argc);
                    WriteOutput(output, $"[\"{_id}_listrange\",{args[0]}]");
                    return 100;
                case "listset":
                    HandleListSetOperation(args, argc);
                    WriteOutput(output, "Async");
                    return 200;
                case "load":
                    Load();
                    WriteOutput(output, "Data loaded");
                    return 100;
                case "save":
                    Save(args, argc);
                    WriteOutput(output, "Data saved");
                    return 100;
                case "set":
                    HandleSetOperation(args, argc);
                    WriteOutput(output, "Async");
                    return 200;
                case "version":
                    WriteOutput(output, ARDB_VERSION);
                    return 100;
                case "listbackups":
                    string backupsList = HandleListBackupsOperation();
                    WriteOutput(output, backupsList);
                    return 100;
                case "restorebackup":
                    bool success = HandleRestoreBackupOperation(args);
                    WriteOutput(output, success.ToString().ToLower());
                    return 100;
                case "deletebackup":
                    bool deleted = HandleDeleteBackupOperation(args);
                    WriteOutput(output, deleted.ToString().ToLower());
                    return 100;
                default:
                    WriteOutput(output, "Available functions: del, get, hdel, hdelid, hget, hgetid, hgetall, hgetallid, hrem, hremid, hset, hsetid, isloaded, listadd, listidx, listrem, listrng, listset, load, save, set, version, listbackups, restorebackup, deletebackup");
                    return -1;
            }
        }

        /// <summary>
        /// Reads a string from the given pointer. 
        /// If the pointer is null, a default value will be returned instead.
        /// </summary>
        /// <param name="pointer">The pointer to read</param>
        /// <param name="defaultValue">The string's default value</param>
        /// <returns>The marshalled string</returns>
        private unsafe static string GetString(char* pointer, string defaultValue = "")
        {
            return Marshal.PtrToStringAnsi((nint)pointer) ?? defaultValue;
        }

        /// <summary>
        /// Serializes a list of strings into a string representing a valid Arma 3 array.
        /// </summary>
        /// <param name="list">The list of strings to serialize</param>
        /// <returns>A string representing an Arma 3 array</returns>
        private static string SerializeList(List<string> list)
        {
            var content = string.Join(",", [.. list]);
            return string.Format("[{0}]", content);
        }

        /// <summary>
        /// Writes the given payload to the output buffer using the provided pointer.
        /// Ensures that the payload string is always null terminated.
        /// </summary>
        /// <param name="output">A pointer to the output buffer</param>
        /// <param name="payload">The payload to write</param>
        private unsafe static void WriteOutput(char* output, string payload)
        {
            byte[] bytes = Encoding.ASCII.GetBytes(payload + '\0');
            Marshal.Copy(bytes, 0, (nint)output, bytes.Length);
        }

        private static void Save(List<string> args, int argc)
        {
            db ??= new RAMDb();
            
            // Convert string to boolean properly
            bool createBackup = argc > 0 && 
                (args[0].Trim('"').Equals("true", StringComparison.CurrentCultureIgnoreCase) || args[0].Trim('"') == "1");
            
            db.ExportToBinary(createBackup);
            Log($"Data saved to ARDB{(createBackup ? " with backup" : "")}", "action");
        }

        private static void Load()
        {
            db ??= new RAMDb();

            db.ImportFromBinary();
            ARDB_ISLOADED = true;
            Log("Data loaded from ARDB", "action");
        }

#pragma warning disable IDE0060 // Remove unused parameter
        private static void HandleHDelOperation()
#pragma warning restore IDE0060 // Remove unused parameter
        {
            Task.Run(async () =>
            {
                await HashStore.HashDelete(STEAMID);
            });
        }

#pragma warning disable IDE0060 // Remove unused parameter
        private static void HandleHDelIdOperation(List<string> args, int argc)
#pragma warning restore IDE0060 // Remove unused parameter
        {
            Task.Run(async () =>
            {
                await HashStore.HashDelete(args[0].Trim('"'));
            });
        }

        private static void HandleHGetOperation(long _id, List<string> args, int argc)
        {
            Task.Run(async () =>
            {
                string _uniqueID = $"{_id}_hget";
                switch (argc)
                {
                    case 2:
                        await HashStore.HashGet(STEAMID, args[0].Trim('"'), args[1].Trim('"'), _uniqueID);
                        break;
                    case 3:
                        await HashStore.HashGet(STEAMID, args[0].Trim('"'), args[1].Trim('"'), _uniqueID, args[2].Trim('"'));
                        break;
                    case 4:
                        await HashStore.HashGet(STEAMID, args[0].Trim('"'), args[1].Trim('"'), _uniqueID, args[2].Trim('"'), args[3].Trim('"'));
                        break;
                    default:
                        Log($"Unexpected argument count: {argc} for HashGet operation", "warning");
                        break;
                }
            });
        }

        private static void HandleHGetIdOperation(long _id, List<string> args, int argc)
        {
            Task.Run(async () =>
            {
                string _uniqueID = $"{_id}_hgetid";
                switch (argc)
                {
                    case 3:
                        await HashStore.HashGet(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), _uniqueID);
                        break;
                    case 4:
                        await HashStore.HashGet(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), _uniqueID, args[3].Trim('"'));
                        break;
                    case 5:
                        await HashStore.HashGet(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), _uniqueID, args[3].Trim('"'), args[4].Trim('"'));
                        break;
                    default:
                        Log($"Unexpected argument count: {argc} for HashGetId operation", "warning");
                        break;
                }
            });
        }

        private static void HandleHGetAllOperation(long _id, List<string> args, int argc)
        {
            Task.Run(async () =>
            {
                string _uniqueID = $"{_id}_hgetall";
                switch (argc)
                {
                    case 1:
                        await HashStore.HashGetAllAsync(STEAMID, args[0].Trim('"'), _uniqueID);
                        break;
                    case 2:
                        await HashStore.HashGetAllAsync(STEAMID, args[0].Trim('"'), _uniqueID, args[1].Trim('"'));
                        break;
                    case 3:
                        await HashStore.HashGetAllAsync(STEAMID, args[0].Trim('"'), _uniqueID, args[1].Trim('"'), args[2].Trim('"'));
                        break;
                    default:
                        Log($"Unexpected argument count: {argc} for HashGetAll operation", "warning");
                        break;
                }
            });
        }

        private static void HandleHGetAllIdOperation(long _id, List<string> args, int argc)
        {
            Task.Run(async () =>
            {
                string _uniqueID = $"{_id}_hgetallid";
                switch (argc)
                {
                    case 2:
                        await HashStore.HashGetAllAsync(args[0].Trim('"'), args[1].Trim('"'), _uniqueID);
                        break;
                    case 3:
                        await HashStore.HashGetAllAsync(args[0].Trim('"'), args[1].Trim('"'), _uniqueID, args[2].Trim('"'));
                        break;
                    case 4:
                        await HashStore.HashGetAllAsync(args[0].Trim('"'), args[1].Trim('"'), _uniqueID, args[2], args[3].Trim('"'));
                        break;
                    default:
                        Log($"Unexpected argument count: {argc} for HashGetAllId operation", "warning");
                        break;
                }
            });
        }

#pragma warning disable IDE0060 // Remove unused parameter
        private static void HandleHRemOperation(List<string> args, int argc)
#pragma warning restore IDE0060 // Remove unused parameter
        {
            Task.Run(async () =>
            {
                await HashStore.HashRemoveAsync(STEAMID, args[0].Trim('"'));
            });
        }

#pragma warning disable IDE0060 // Remove unused parameter
        private static void HandleHRemIdOperation(List<string> args, int argc)
#pragma warning restore IDE0060 // Remove unused parameter
        {
            Task.Run(async () =>
            {
                await HashStore.HashRemoveAsync(args[0].Trim('"'), args[1].Trim('"'));
            });
        }

        private static void HandleHSetOperation(List<string> args, int argc)
        {
            Task.Run(async () =>
            {
                switch (argc)
                {
                    case > 2: // For bulk operations
                        var bulkValues = new Dictionary<string, string>();
                        for (var i = 0; i < argc; i += 2)
                        {
                            bulkValues[args[i].Trim('"')] = args[i + 1];
                        }
                        await HashStore.HashSetBulkAsync(STEAMID, bulkValues);
                        break;
                    case 2: // For single key-value pair
                        await HashStore.HashSetAsync(STEAMID, args[0].Trim('"'), args[1].Trim('"'));
                        break;
                    default:
                        Log($"Invalid argument count: {argc} for HashSet operation", "warning");
                        break;
                }
            });
        }

        private static void HandleHSetIdOperation(List<string> args, int argc)
        {
            Task.Run(async () =>
            {
                switch (argc)
                {
                    case > 4: // For bulk operations
                        var bulkValues = new Dictionary<string, string>();
                        for (var i = 1; i < argc; i += 2)
                        {
                            bulkValues[args[i].Trim('"')] = args[i + 1];
                        }
                        await HashStore.HashSetBulkAsync(args[0].Trim('"'), bulkValues);
                        break;
                    case 3: // For single key-value pair
                        await HashStore.HashSetAsync(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'));
                        break;
                    default:
                        Log($"Invalid argument count: {argc} for HashSetId operation", "warning");
                        break;
                }
            });
        }

        private static void HandleListAddOperation(List<string> args, int argc)
        {
            Task.Run(async () =>
            {
                switch (argc)
                {
                    case > 2:
                        for (var i = 1; i < argc; i++) // Fixed: start from index 1 to skip list name
                        {
                            await ListStore.ListAddAsync(args[0].Trim('"'), args[i]);
                        }
                        break;
                    case 2:
                        await ListStore.ListAddAsync(args[0].Trim('"'), args[1].Trim('"'));
                        break;
                    default:
                        Log($"Invalid argument count: {argc} for ListAdd operation", "warning");
                        break;
                }
            });
        }

        private static void HandleListDelOperation(List<string> args, int argc)
        {
            Task.Run(async () =>
            {
                await ListStore.ListDeleteAsync(args[0].Trim('"'));
            });
        }

#pragma warning disable IDE0060 // Remove unused parameter
        private static void HandleListRemOperation(List<string> args, int argc)
#pragma warning restore IDE0060 // Remove unused parameter
        {
            Task.Run(async () =>
            {
                await ListStore.ListSetAsync(args[0].Trim('"'), args[1].Trim('"'), "RAMDBREMOVE");
                await ListStore.ListRemoveAsync(args[0].Trim('"'), "RAMDBREMOVE");
            });
        }

        private static void HandleListIdxOperation(long _id, List<string> args, int argc)
        {
            Task.Run(async () =>
            {
                string _uniqueID = $"{_id}_listidx";
                switch (argc)
                {
                    case 3:
                        await ListStore.ListIndexAsync(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), _uniqueID);
                        break;
                    case 4:
                        await ListStore.ListIndexAsync(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), _uniqueID, args[3].Trim('"'));
                        break;
                    case 5:
                        await ListStore.ListIndexAsync(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), _uniqueID, args[3].Trim('"'), args[4].Trim('"'));
                        break;
                    default:
                        Log($"Unexpected argument count: {argc} for ListIdx operation", "warning");
                        break;
                }
            });
        }

        private static void HandleListRngOperation(long _id, List<string> args, int argc)
        {
            Task.Run(async () =>
            {
                string _uniqueID = $"{_id}_listrng";
                switch (argc)
                {
                    case 4:
                        await ListStore.ListRangeAsync(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), args[3].Trim('"'), _uniqueID);
                        break;
                    case 5:
                        await ListStore.ListRangeAsync(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), args[3].Trim('"'), _uniqueID, args[4].Trim('"'));
                        break;
                    case 6:
                        await ListStore.ListRangeAsync(args[0].Trim('"'), args[1].Trim('"'), args[2].Trim('"'), args[3].Trim('"'), _uniqueID, args[4].Trim('"'), args[5].Trim('"'));
                        break;
                    default:
                        Log($"Unexpected argument count: {argc} for ListRng operation", "warning");
                        break;
                }
            });
        }

#pragma warning disable IDE0060 // Remove unused parameter
        private static void HandleListSetOperation(List<string> args, int argc)
#pragma warning restore IDE0060 // Remove unused parameter
        {
            Task.Run(async () =>
            {
                await ListStore.ListSetAsync(args[0].Trim('"'), args[1].Trim('"'), args[2]);
            });
        }

#pragma warning disable IDE0060 // Remove unused parameter
        private static void HandleSetOperation(List<string> args, int argc)
#pragma warning restore IDE0060 // Remove unused parameter
        {
            Task.Run(async () =>
            {
                await KeyValueStore.SetAsync(args[0].Trim('"'), args[1]);
            });
        }

        private static void HandleGetOperation(long _id, List<string> args, int argc)
        {
            Task.Run(async () =>
            {
                string _uniqueID = $"{_id}_get";
                switch (argc)
                {
                    case 2:
                        await KeyValueStore.GetAsync(args[0].Trim('"'), args[1].Trim('"'), _uniqueID);
                        break;
                    case 3:
                        await KeyValueStore.GetAsync(args[0].Trim('"'), args[1].Trim('"'), _uniqueID, args[2].Trim('"'));
                        break;
                    case 4:
                        await KeyValueStore.GetAsync(args[0].Trim('"'), args[1].Trim('"'), _uniqueID, args[2].Trim('"'), args[3].Trim('"'));
                        break;
                    default:
                        Log($"Unexpected argument count: {argc} for Get operation", "warning");
                        break;
                }
            });
        }

#pragma warning disable IDE0060 // Remove unused parameter
        private static void HandleDeleteOperation(List<string> args, int argc)
#pragma warning restore IDE0060 // Remove unused parameter
        {
            Task.Run(async () =>
            {
                await KeyValueStore.DeleteAsync(args[0].Trim('"'));
            });
        }

        private static string HandleListBackupsOperation()
        {
            db ??= new RAMDb();
            var backups = db.ListBackups();
            
            if (backups.Count > 0)
            {
                // Format backup list for Arma by joining filenames with proper array syntax
                var backupFileNames = backups.Select(Path.GetFileName).ToList();
                var formattedResult = string.Join("\",\"", backupFileNames);

                Log($"Listed {backups.Count} available backups", "action");
                return $"[\"{formattedResult}\"]";
            }
            else
            {
                // Return empty array if no backups exist
                Log("No backups available", "action");
                return "[]";
            }
        }

        private static bool HandleRestoreBackupOperation(List<string> args)
        {
            if (args.Count < 1) return false;
            
            string backupFileName = args[0].Trim('"');
            db ??= new RAMDb();
            var backups = db.ListBackups();
            
            // Find the full path based on filename
            var backupPath = backups.FirstOrDefault(b => Path.GetFileName(b).Equals(backupFileName, StringComparison.OrdinalIgnoreCase));
            
            if (backupPath != null)
            {
                bool success = RAMDb.RestoreFromBackup(backupPath);
                Log($"Restore from backup {backupFileName}: {(success ? "successful" : "failed")}", "action");
                return success;
            }
            
            Log($"Backup {backupFileName} not found", "error");
            return false;
        }

        private static bool HandleDeleteBackupOperation(List<string> args)
        {
            if (args.Count < 1) return false;
            
            string backupFileName = args[0].Trim('"');
            db ??= new RAMDb();
            var backups = db.ListBackups();
            
            // Find the full path based on filename
            var backupPath = backups.FirstOrDefault(b => Path.GetFileName(b).Equals(backupFileName, StringComparison.OrdinalIgnoreCase));
            
            if (backupPath != null)
            {
                try
                {
                    File.Delete(backupPath);
                    Log($"Deleted backup: {backupFileName}", "action");
                    return true;
                }
                catch (Exception ex)
                {
                    Log($"Failed to delete backup {backupFileName}: {ex.Message}", "error");
                }
            }
            else
            {
                Log($"Backup {backupFileName} not found", "error");
            }
            
            return false;
        }
    }
}