using Microsoft.Extensions.Configuration;
using System.Collections.Concurrent;

namespace Kit.Helpers.Log
{

    public enum TypeInfo { Debug = 1, Info, Warn, Error, }

    public class LoggerKey : IDisposable
    {
        private bool disposed = false;
        public Guid Key { get; set; }
        public void Dispose()
        {

            Dispose(true);
            // подавляем финализацию
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    LoggerDB.Commit(this);
                }
                // освобождаем неуправляемые объекты
                disposed = true;
            }
        }

        // Деструктор
        ~LoggerKey()
        {
            Dispose(false);
        }
    }

    public class LoggerItems
    {
        public string SessionKey { get; set; }
        public LogMessageType LogMessageType { get; set; }
        public DateTime DateCreated { get; set; }
        public string Target { get; set; }
        public string Action { get; set; }
        public string Message { get; set; }
        public double Duration { get; set; }
    }

    public static class LoggerDB
    {
        private static string _connectionString;
        private static bool _isRun;

        private static ConcurrentDictionary<Guid, LoggerItems> _items = new ConcurrentDictionary<Guid, LoggerItems>();

        public static void Configure(IConfiguration configuration)
        {
            _connectionString = "";// new ConfigurationHelper("Logger") ConfigurationManager.ConnectionStrings["Logger.Db"].ConnectionString;
            var config = new ConfigurationHelper(configuration, "LogDb");
            _isRun = config.GetAppSettingValue("IsRun").TryParseToBool(false);
        }

        public static LoggerKey Log(string sessionKey, LogMessageType type, string target, string action, string message)
        {
            return Log(sessionKey, type, DateTime.UtcNow, target, action, message);
        }
        public static LoggerKey Log(string sessionKey, LogMessageType type, DateTime dateCreated, string target, string action, string message)
        {
            if (_isRun)
            {
                Guid key = Guid.NewGuid();
                _items.TryAdd(key, new LoggerItems
                {
                    SessionKey = sessionKey,
                    Action = action,
                    DateCreated = dateCreated,
                    Duration = 0,
                    LogMessageType = type,
                    Message = message,
                    Target = target
                });

                return new LoggerKey { Key = key };
            }
            return new LoggerKey { Key = Guid.Empty }; ;
        }

        public static void Commit(LoggerKey key, DateTime? finishDate = null)
        {
            if (_items.ContainsKey(key.Key))
            {
                LoggerItems item = _items.GetByKey(key.Key);

                double duration = ((finishDate ?? DateTime.UtcNow) - item.DateCreated).TotalMilliseconds;
                //_connectionString.ExecuteScalar<int>("[Logs].[Insert_Logger]", true, new List<KeyValuePair<string, object>>
                //{
                //    new KeyValuePair<string, object>("@LogMessageType", (int)item.LogMessageType),
                //    new KeyValuePair<string, object>("@SessionKey", item.SessionKey),
                //    new KeyValuePair<string, object>("@DateCreate", item.DateCreated),
                //    new KeyValuePair<string, object>("@Target", item.Target),
                //    new KeyValuePair<string, object>("@Action", item.Action),
                //    new KeyValuePair<string, object>("@Message", item.Message),
                //    new KeyValuePair<string, object>("@Duration", duration),
                //});

                _items.TryRemove(key.Key, out item!);
            }
        }
        public static void Commit(params LoggerKey[] keys)
        {
            foreach (LoggerKey key in keys)
            {
                Commit(key);
            }
        }

        public static void Commit(string sessionKey, LogMessageType type, string target, string action, DateTime dateTime, Dictionary<string, long> logs)
        {
            foreach (var log in logs)
            {
                //_connectionString.ExecuteScalar<int>("[Logs].[Insert_Logger]", true, new List<KeyValuePair<string, object>>
                //{
                //    new KeyValuePair<string, object>("@LogMessageType", (int)type),
                //    new KeyValuePair<string, object>("@SessionKey", sessionKey),
                //    new KeyValuePair<string, object>("@DateCreate", dateTime),
                //    new KeyValuePair<string, object>("@Target", target),
                //    new KeyValuePair<string, object>("@Action", action),
                //    new KeyValuePair<string, object>("@Message", log.Key),
                //    new KeyValuePair<string, object>("@Duration", log.Value),
                //});
            }
        }
    }
}
