using System.Collections.Concurrent;

#pragma warning disable IDE0130 // Namespace does not match folder structure
namespace ArmaRAMDb
#pragma warning restore IDE0130 // Namespace does not match folder structure
{
    internal class HashStore
    {
        private static readonly ConcurrentDictionary<string, ConcurrentDictionary<string, string>> _hashTables = RAMDb._hashTables;

        public static async Task HashDelete(string tableName)
        {
            await Task.Yield();
            bool result = _hashTables.TryRemove(tableName, out _);

            Main.Log($"HashDelete: {tableName} - Success: {result}", "debug");
        }

        public static async Task HashGet(string tableName, string key, string function, string uniqueID, string entity = null, string call = "false", int bufferSize = Main.ARDB_BUFFERSIZE)
        {
            if (string.IsNullOrEmpty(tableName) || string.IsNullOrEmpty(key) || string.IsNullOrEmpty(function))
            {
                Main.Log($"ArmaRAMDb 'tableName, 'key' or 'function' cannot be empty", "debug");
                return;
            }

            await Task.Yield();

            if (_hashTables.TryGetValue(tableName, out var table))
            {
                string data = table.TryGetValue(key, out string value) ? value : string.Empty;
                Main.Log($"HashGet: {tableName} - {key}", "debug");
                Main.Log($"Value: {data}", "debug");
                
                Utils.CheckByteCount(uniqueID, data, function, entity, Convert.ToBoolean(call), bufferSize);
            }
            else
            {
                Main.Log($"Table not found: {tableName}", "debug");
            }
        }

        public static async Task HashGetAllAsync(string tableName, string function, string uniqueId, string entity = null, string call = "false", int bufferSize = Main.ARDB_BUFFERSIZE)
        {
            Main.Log($"Getting contents for table: {tableName}", "debug");
            
            if (string.IsNullOrEmpty(tableName) || string.IsNullOrEmpty(function))
            {
                Main.Log($"ArmaRAMDb 'tableName' or 'function' cannot be empty", "debug");
                return;
            }

            await Task.Yield();

            if (_hashTables.TryGetValue(tableName, out var table))
            {
                var contents = table.ToDictionary(kv => kv.Key, kv => kv.Value);
                Main.Log($"Found {contents.Count} entries in table {tableName}", "debug");

                foreach (var entry in contents)
                {
                    Main.Log($"Key: {entry.Key}, Value: {entry.Value}", "debug");
                }

                string data = string.Join(",", contents.Select(kv => $"[\"{kv.Key}\",{kv.Value}]"));
                Utils.CheckByteCount(uniqueId, $"[{data}]", function, entity, Convert.ToBoolean(call), bufferSize);
            }
            else
            {
                Main.Log($"Table {tableName} not found", "debug");
            }
        }

        public static async Task HashRemoveAsync(string tableName, string key)
        {
            await Task.Yield();
            
            if (_hashTables.TryGetValue(tableName, out var table))
            {
                table.TryRemove(key, out _);
            }
            else
            {
                Main.Log($"Table not found: {tableName}", "debug");
            }
        }

        public static async Task HashSetBulkAsync(string tableName, Dictionary<string, string> values)
        {
            var table = _hashTables.GetOrAdd(tableName, _ => new ConcurrentDictionary<string, string>());

            await Task.Yield();

            foreach (var kv in values)
            {
                var value = kv.Value;
                if (value.StartsWith('[') && value.EndsWith(']'))
                {
                    table.AddOrUpdate(kv.Key, value, (_, _) => value);
                }
                else
                {
                    table.AddOrUpdate(kv.Key, $"[\"{value}\"]", (_, _) => $"[\"{value}\"]");
                }
                Main.Log($"HashSet: {tableName} - {kv.Key} - {value}", "debug");
            }
        }

        public static async Task HashSetAsync(string tableName, string key, string value)
        {
            await HashSetBulkAsync(tableName, new Dictionary<string, string> { { key, value } });
        }
    }
}