using Newtonsoft.Json;
using PlcSiemens.Core.Extension;
using ServiceCenter.Extensions;
using ServiceCenter.Redis;
using System.Collections.Concurrent;
using System.Diagnostics;
using WCS.Core;

namespace ServiceCenter.Logs
{
    public static class LogHub
    {
        /// <summary>
        ///  发布世界交互日志
        /// </summary>
        /// <param name="logs"></param>
        /// <param name="World">当前世界</param>
        public static void WorldPublish(ConcurrentQueue<KeyLog> logs, string World)
        {
            if (logs.Count <= 0) return;
            //var sql = new StringBuilder();
            //sql.Append("INSERT INTO ");
            //var db = new SqlSugarHelper().PLC;
            try
            {
                Parallel.ForEach(logs.GroupBy(x => x.Channel.System), item1 =>
                {
                    Parallel.ForEach(item1.GroupBy(x => x.Channel.Item), item2 =>
                    {
                        var msgList = item2.Select(x => new
                        {
                            x.Time,
                            x.Log.Message
                        }).ToList();
                        RedisHub.Default.Set($"WCSLog:{item1.Key}:{item2.Key}", JsonConvert.SerializeObject(msgList));
                    });
                });
            }
            catch
            {
                // ignored
            }

            try
            {
                //每一条数据存入redis
                foreach (var log in logs.OrderBy(x => x.Time))
                {
                    try
                    {
                        var dir = $"D:\\WCSLogs\\{DateTime.Now.yyyyMMdd()}\\{log.Channel.World}\\{log.Channel.System}\\{log.Channel.Item}\\";
                        var msg = $"{log.Time.yyyyMMddhhmmssf()}--[{Thread.CurrentThread.ManagedThreadId}]--{log}";
                        if (log.Log.Message.IsNullOrEmpty()) continue;
                        var title = $"{log.Log.Message.Split(":")[0]}.txt";
                        RedisHub.Default.RPush("LogHub", JsonConvert.SerializeObject(new LogModel
                        {
                            Time = log.Time,
                            path = dir,
                            Title = title,
                            Con = msg
                        }));
                    }
                    catch
                    {
                        // ignored
                    }
                }

                if (RedisHub.WMSContextType != null)
                {
                    //存入业务报警内容
                    var businesses = logs.Where(x => x.Log is { Level: > LogLevelEnum.Low, LogUpLoad: LogUpLoadEnum.UpLoadWMS } && !x.Log.Message.Contains("读取DB块数据失败")).Select(v => new BusinessAlarm()
                    {
                        BusinessName = v.Channel.System,
                        DevNo = v.Channel.Item,
                        Con = v.ToString(),
                        Time = DateTime.Now
                    }).ToList();
                    RedisHub.WMS.Set($"{nameof(BusinessAlarm)}:{World}", JsonConvert.SerializeObject(businesses));
                }
            }
            catch
            {
                // ignored
            }
        }

        /// <summary>
        ///  去除转义字符
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string RemoveEscapeCharacters(this string? value)
        {
            return value.Trim('\0', '\a', '\b', '\f', '\n', '\r', '\t', '\v').Trim();
        }

        public static string GetString(string value)
        {
            return value.Replace("INSERT INTO ", "")
                .Replace(",N'", ",'")
                .Replace("\0", "")
                .Replace("wcs_", "")
                .Replace("(N'", "('") + "\r";
        }

        /// <summary>
        ///   执行记录
        /// </summary>
        /// <param name="system">系统</param>
        /// <param name="devCode">设备号</param>
        /// <param name="msg">内容</param>
        public static void ExRecord(this SystemBase system, string devCode, string msg)
        {
        }

        /// <summary>
        ///   执行记录
        /// </summary>
        /// <param name="system">系统</param>
        /// <param name="devCode">设备号</param>
        /// <param name="msg">内容</param>
        public static async void ExRecord<T>(this SystemBase system, string devCode, string msg, List<T> ints)
        {
            try
            {
            }
            catch
            {
                // ignored
            }
        }

        /// <summary>
        ///  发布一条日志记录
        /// </summary>
        /// <param name="title">接口名</param>
        /// <param name="con">内容</param>
        public static void InterfacePublish(string title, string con)
        {
            RedisHub.Default.RPush("LogHub", JsonConvert.SerializeObject(new LogModel
            {
                path = $"D:\\WCSLogs\\{DateTime.Now.yyyyMMdd()}\\接口日志\\",
                Title = $"{title}.txt",
                Con = $"{DateTime.Now.yyyyMMddhhmmssf()}--{con}"
            }));
        }

        /// <summary>
        ///  初始化日志处理进程
        /// </summary>
        public static void init()
        {
            var toao = 1000;
            while (true)
            {
                var sw = new Stopwatch();
                sw.Start();
                int index = 0;
                List<LogModel> logs = new List<LogModel>();
                try
                {
                    var tran = RedisHub.Default.Multi();
                    var a = tran.LRange("LogHub", 0, 19999);
                    tran.LTrim("LogHub", 20000, -1);
                    var value = tran.Exec()[0];
                    tran.Discard();
                    var ret = value as string[];
                    logs = ret.Select(JsonConvert.DeserializeObject<LogModel>).ToList();

                    foreach (var paths in logs.Where(log => log != null).GroupBy(x => x.path))
                    {
                        foreach (var title in paths.GroupBy(x => x.Title))
                        {
                            var log = title.First();
                            var cons = title.OrderBy(x => x.Time).Select(x => x.Con);
                            if (!Directory.Exists(log.path)) Directory.CreateDirectory(log.path);/*.txt*/
                            var path = Path.Combine(log.path, log.Title);
                            if (!File.Exists(path))
                            {
                                File.AppendAllLines(path, cons);
                            }
                            else
                            {
                                var fileInfo = new FileInfo(path);
                                var fileMb = fileInfo.Length / 1024 / 1024;
                                if (fileMb > 20) //如果当前文件大小超过20MB 开始封存此文件，
                                {
                                    var fileIndex = 1; //文件索引
                                    var isSave = false;
                                    while (!isSave) //未保存成功
                                    {
                                        var newPath = Path.Combine(log.path, log.Title.Replace(".txt", $"{fileIndex}.txt"));//使用文件索引头来判断当前索引对应的标题文件是否存在
                                        if (!File.Exists(newPath))//不存在，将现有文件更名成新的文件名
                                        {
                                            File.Move(path, newPath);
                                            isSave = true;
                                        }
                                        fileIndex++;
                                    }
                                }
                                File.AppendAllLines(path, cons);
                            }

                            index++;
                        }
                    }
                }
                catch (Exception ex)
                {
                    var path = $"D:\\WCSLogs\\{DateTime.Now.yyyyMMdd()}\\日志处理进程";
                    if (!Directory.Exists(path)) Directory.CreateDirectory(path);
                }
                sw.Stop();
                var path1 = $"D:\\WCSLogs\\{DateTime.Now.yyyyMMdd()}\\日志处理进程";
                if (!Directory.Exists(path1)) Directory.CreateDirectory(path1);
                File.AppendAllText(Path.Combine(path1, "耗时.txt"), $"{DateTime.Now.yyyyMMddhhmmssf()}耗时:{sw.ElapsedMilliseconds}--{logs.Count}--{index}\n");
                if (sw.ElapsedMilliseconds >= toao) continue;
                var time = toao - sw.ElapsedMilliseconds.ToInt();
                Thread.Sleep(time);
            }
        }
    }

    public class LogModel
    {
        public string path { get; set; }

        public DateTime Time { get; set; }

        public string Title { get; set; }

        public string Con { get; set; }
    }

    /// <summary>
    ///  业务报警
    /// </summary>
    public class BusinessAlarm
    {
        /// <summary>
        ///  业务名称
        /// </summary>
        public string BusinessName { get; set; }

        /// <summary>
        ///  设备号
        /// </summary>
        public string DevNo { get; set; }

        /// <summary>
        ///  内容
        /// </summary>
        public string Con { get; set; }

        /// <summary>
        ///  时间
        /// </summary>
        public DateTime Time { get; set; }
    }
}
