using XKRS.UI.Model.Winform;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static DH.Commons.Enums.EnumHelper;
using DH.Commons.Enums;
using System.ComponentModel;
using System.Reflection;


namespace DHSoftware.Views
{
    public partial class FrmLog : UserControl
    {
        #region Win32 API双缓冲处理
        private const int LVM_SETEXTENDEDLISTVIEWSTYLE = 0x1036;
        private const int LVS_EX_DOUBLEBUFFER = 0x00010000;

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);
        #endregion

        #region 常量配置
        private const string SOURCE_PROCESS = "流程";
        private const int LOG_NUM_LIMIT = 2000;
        private const int BATCH_SIZE = 50;
        private const int PROCESS_INTERVAL = 100;
        private const int FIRST_COL_WIDTH = 120;
        #endregion

        #region 控件状态
        private readonly ConcurrentQueue<LogMsg> _logQueue = new ConcurrentQueue<LogMsg>();
        private List<LogMsg> _logBuffer = new List<LogMsg>();
        private List<LogLevel> _showLevels = new List<LogLevel>();
        private List<string> _showSources = new List<string>();
        private Task _logTask;
        private static readonly object _logLock = new object();
        #endregion

        public FrmLog()
        {
            InitializeComponent();
            InitializeCustomComponents();
        }

        private void InitializeCustomComponents()
        {
            // 启用双缓冲
            SendMessage(lvLog.Handle, LVM_SETEXTENDEDLISTVIEWSTYLE,
                      LVS_EX_DOUBLEBUFFER, LVS_EX_DOUBLEBUFFER);

            lvLog.ShowItemToolTips = true;
            lvLog.FullRowSelect = true;
            lvLog.View = View.Details;
            // 启用自定义绘制
            //lvLog.OwnerDraw = true;
            //lvLog.DrawColumnHeader += LvLog_DrawColumnHeader;
            //lvLog.DrawSubItem += LvLog_DrawSubItem;
            //lvLog.DrawItem += LvLog_DrawItem;

            // 初始化列头
            lvLog.Columns.Add("时间", FIRST_COL_WIDTH);
            lvLog.Columns.Add("来源", 150);
            lvLog.Columns.Add("内容", 400);

            InitializeLevelFilter();
            StartProcessingTask();
        }

        private void InitializeLevelFilter()
        {
            _showLevels.Clear();
            tsmiLogLevels.DropDownItems.Clear();

            foreach (LogLevel level in Enum.GetValues(typeof(LogLevel)))
            {
                var item = new ToolStripMenuItem(level.GetEnumDescription())
                {
                    CheckOnClick = true,
                    Checked = true,
                    Tag = level,
                    BackColor = level.GetEnumSelectedColor(),
                    ForeColor = level.GetEnumSelectedFontColor()
                };
                item.CheckedChanged += LevelItem_CheckedChanged;
                tsmiLogLevels.DropDownItems.Add(item);
                _showLevels.Add(level);
            }
        }
        #region 自定义绘制方法
        private void LvLog_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
        {
            e.DrawDefault = true;
        }

        private void LvLog_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
        {
            var item = e.Item;
            var log = item.Tag as LogMsg;

            // 设置背景色
            e.Graphics.FillRectangle(new SolidBrush(log.LogLevel.GetEnumSelectedColor()), e.Bounds);

            // 设置文字颜色
            TextRenderer.DrawText(e.Graphics, e.SubItem.Text, lvLog.Font,
                e.Bounds, log.LogLevel.GetEnumSelectedFontColor(), TextFormatFlags.Left);
        }
        //private ListViewItem CreateLogItem(LogMsg log)
        //{
        //    var item = new ListViewItem(log.LogTime.ToString("HH:mm:ss.fff"));
        //    item.SubItems.Add(FormatSource(log));
        //    item.SubItems.Add(log.Msg);
        //    item.Tag = log; // 重要:将日志对象绑定到Tag
        //    return item;
        //}
        private void LvLog_DrawItem(object sender, DrawListViewItemEventArgs e)
        {
            e.DrawDefault = false; // 禁用默认绘制
        }
        #endregion
        private void StartProcessingTask()
        {
            lock (_logLock)
            {
                if (_logTask == null || _logTask.IsCompleted)
                {
                    _logTask = Task.Run(ProcessLogs);
                }
            }
        }

        private async Task ProcessLogs()
        {
            while (!IsDisposed)
            {
                try
                {
                    await Task.Delay(PROCESS_INTERVAL);
                    ProcessBatch(BATCH_SIZE);
                }
                catch (Exception ex)
                {
                    DebugWrite($"日志处理异常: {ex.Message}");
                }
            }
        }

        private void ProcessBatch(int batchSize)
        {
            if (InvokeRequired)
            {
                BeginInvoke(new Action(() => ProcessBatch(batchSize)));
                return;
            }

            lvLog.BeginUpdate();
            try
            {
                var items = new List<ListViewItem>();
                int processed = 0;

                while (processed < batchSize && _logQueue.TryDequeue(out var log))
                {
                    _logBuffer.Add(log);
                    if (ShouldShow(log))
                    {
                        items.Add(CreateLogItem(log));
                        processed++;
                    }
                }

                if (items.Count > 0)
                {
                    lvLog.Items.AddRange(items.ToArray());
                    MaintainBuffer();
                    AutoScrollIfNeeded();
                }
            }
            finally
            {
                lvLog.EndUpdate();
                UpdateLayout();
            }
        }

        private bool ShouldShow(LogMsg log)
        {
            return _showLevels.Contains(log.LogLevel) &&
                  (_showSources.Count == 0 ||
                   (string.IsNullOrEmpty(log.MsgSource) ?
                    _showSources.Contains(SOURCE_PROCESS) :
                    _showSources.Contains(log.MsgSource)));
        }

        private ListViewItem CreateLogItem(LogMsg log)
        {
            var item = new ListViewItem(log.LogTime.ToString("HH:mm:ss.fff"));
            item.SubItems.Add(FormatSource(log));
            item.SubItems.Add(log.Msg);
            item.ToolTipText = log.Msg;
            item.BackColor = log.LogLevel.GetEnumSelectedColor();
            item.ForeColor = log.LogLevel.GetEnumSelectedFontColor();
            return item;
        }

        private string FormatSource(LogMsg log)
        {
            return string.IsNullOrEmpty(log.MsgSource) ?
                SOURCE_PROCESS :
                $"{log.MsgSource}[{log.ThreadId}]";
        }

        private void MaintainBuffer()
        {
            if (_logBuffer.Count > LOG_NUM_LIMIT * 2)
            {
                _logBuffer = _logBuffer
                    .Skip(_logBuffer.Count - LOG_NUM_LIMIT)
                    .ToList();
                RefreshLogs();
            }
        }

        public void AddLog(LogMsg log)
        {
            _logQueue.Enqueue(log);
        }

        private void RefreshLogs()
        {
            lvLog.BeginUpdate();
            try
            {
                lvLog.Items.Clear();
                var items = _logBuffer
                    .Where(ShouldShow)
                    .Select(CreateLogItem);
                lvLog.Items.AddRange(items.ToArray());
            }
            finally
            {
                lvLog.EndUpdate();
                UpdateLayout();
            }
        }

        private void AutoScrollIfNeeded()
        {
            try
            {
                if (lvLog.Items.Count > 0 /*&& chkAutoScroll.Checked*/)
                {
                    lvLog.EnsureVisible(lvLog.Items.Count - 1);
                }
            }
            catch (Exception ex) {
            }
            
        }

        private void UpdateLayout()
        {
            if (lvLog.Columns.Count < 3) return;

            // 动态调整列宽
            lvLog.Columns[0].Width = FIRST_COL_WIDTH;
            lvLog.Columns[1].Width = lvLog.Width > 600 ? 150 : 0;
            lvLog.Columns[2].Width = lvLog.ClientSize.Width -
                                    lvLog.Columns[0].Width -
                                    lvLog.Columns[1].Width -
                                    SystemInformation.VerticalScrollBarWidth;
        }

        #region 事件处理
        private void LevelItem_CheckedChanged(object sender, EventArgs e)
        {
            _showLevels = tsmiLogLevels.DropDownItems
                .Cast<ToolStripMenuItem>()
                .Where(i => i.Checked)
                .Select(i => (LogLevel)i.Tag)
                .ToList();

            RefreshLogs();
        }

        private void SourceItem_CheckedChanged(object sender, EventArgs e)
        {
            _showSources = tsmiLogSources.DropDownItems
                .Cast<ToolStripMenuItem>()
                .Where(i => i.Checked)
                .Select(i => i.Text)
                .ToList();

            RefreshLogs();
        }

        private void tsmiClearLog_Click(object sender, EventArgs e)
        {
            lvLog.Items.Clear();
            _logBuffer.Clear();
        }

        private void lvLog_SizeChanged(object sender, EventArgs e)
        {
            UpdateLayout();
        }
        #endregion

        #region 辅助方法
        private void DebugWrite(string message)
        {
            System.Diagnostics.Debug.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] {message}");
        }
        #endregion
    }

   
    //public partial class FrmLog1 : UserControl
    //{
    //    // 添加双缓冲字段
    //    private const int LVM_SETEXTENDEDLISTVIEWSTYLE = 0x1036;
    //    private const int LVS_EX_DOUBLEBUFFER = 0x00010000;

    //    [System.Runtime.InteropServices.DllImport("user32.dll")]
    //    private static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);

    //    public FrmLog()
    //    {
    //        InitializeComponent();
    //        // 启用双缓冲
    //        SendMessage(lvLog.Handle, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER, LVS_EX_DOUBLEBUFFER);
    //        lvLog.ShowItemToolTips = true;

    //        this.Load += (s, e) =>
    //          {
    //              _showLevels.Clear();
    //              tsmiLogLevels.DropDownItems.Clear();
    //              JsonConvert.DeserializeObject<List<dynamic>>(JsonConvert.SerializeObject(EnumHelper.GetEnumListByType(typeof(LogLevel)))).ForEach(d =>
    //              {
    //                  LogLevel lvl = (LogLevel)((int)d.Value);
    //                  ToolStripMenuItem item = new ToolStripMenuItem(d.Desc.ToString());
    //                  item.CheckOnClick = true;
    //                  item.Checked = true;
    //                  item.Tag = lvl;
    //                  item.CheckedChanged += LevelItem_CheckedChanged;

    //                  item.BackColor = lvl.GetEnumSelectedColor();
    //                  item.ForeColor = lvl.GetEnumSelectedFontColor();
    //                  tsmiLogLevels.DropDownItems.Add(item);
    //                  _showLevels.Add(lvl);
    //              });
    //          };
    //    }

    //    //public override void OnProcessUpdated()
    //    //{
           

    //    //    Invoke(new Action(() =>
    //    //    {
    //    //        _showDevice.Clear();
    //    //        tsmiLogSources.DropDownItems.Clear();
    //    //        ToolStripMenuItem processItem = new ToolStripMenuItem(SOURCE_PROCESS);
    //    //        processItem.CheckOnClick = true;
    //    //        processItem.Checked = true;
    //    //        processItem.CheckedChanged += SourceItem_CheckedChanged;
    //    //        tsmiLogSources.DropDownItems.Add(processItem);
    //    //        _showDevice.Add(SOURCE_PROCESS);

    //    //        Process.DeviceCollection.ForEach(d =>
    //    //        {
    //    //            ToolStripMenuItem item = new ToolStripMenuItem(d.Name);
    //    //            item.CheckOnClick = true;
    //    //            item.Checked = true;
    //    //            item.CheckedChanged += SourceItem_CheckedChanged;
    //    //            tsmiLogSources.DropDownItems.Add(item);
    //    //            _showDevice.Add(d.Name);
    //    //        });
    //    //    }));
    //    //}

    //    private void LevelItem_CheckedChanged(object sender, EventArgs e)
    //    {
    //        _showLevels.Clear();
    //        foreach (ToolStripMenuItem item in tsmiLogLevels.DropDownItems)
    //        {
    //            if (item.Checked)
    //            {
    //                LogLevel lv = (LogLevel)Convert.ToInt32(item.Tag);
    //                _showLevels.Add(lv);
    //            }
    //        }

    //        RefreshLogs();
    //    }

    //    private void SourceItem_CheckedChanged(object sender, EventArgs e)
    //    {
    //        _showDevice.Clear();
    //        foreach (ToolStripMenuItem item in tsmiLogSources.DropDownItems)
    //        {
    //            if (item.Checked)
    //            {
    //                _showDevice.Add(item.Text);
    //            }
    //        }
    //        RefreshLogs();
    //    }
    //    //public TaskFactory _taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.LongRunning);
    //    readonly ConcurrentQueue<LogMsg> _logQueue = new ConcurrentQueue<LogMsg>();
    //    Task _logTask = null;
    //    static readonly object _logLock = new object();

    //    List<LogMsg> _logBuffer = new List<LogMsg>();
    //    List<LogLevel> _showLevels = new List<LogLevel>();
    //    List<string> _showDevice = new List<string>();
    //    const string SOURCE_PROCESS = "流程";
    //    const int LOG_NUM_LIMIT = 20;

    //    public void LogDisplay(LogMsg msg)
    //    {
    //        _logQueue.Enqueue(msg);

    //        lock (_logLock)
    //        {
    //            if (_logTask == null)
    //            {
    //                _logTask = Task.Run(async () =>
    //                {
    //                    while (true)
    //                    {
    //                        try
    //                        {
    //                            Invoke(new Action(() =>
    //                    {
    //                        bool isNeedScroll = false;
    //                        while (_logQueue.TryDequeue(out LogMsg log))
    //                        {
    //                            _logBuffer.Add(log);

    //                            if (_showLevels.Contains(log.LogLevel) && (_showDevice.Count == 0 || (string.IsNullOrWhiteSpace(log.MsgSource) && _showDevice.Contains(SOURCE_PROCESS)) || _showDevice.Contains(log.MsgSource)))
    //                            {
    //                                isNeedScroll = true;

    //                                ListViewItem item = new ListViewItem($"{log.LogTime.ToString("HH:mm:ss.fff")}");
    //                                item.SubItems.Add($"{log.MsgSource}[{log.ThreadId}]");
    //                                item.SubItems.Add(log.Msg);

    //                                item.ToolTipText = log.Msg;
    //                                item.ForeColor = log.LogLevel.GetEnumSelectedFontColor();
    //                                item.BackColor = log.LogLevel.GetEnumSelectedColor();

    //                                lvLog.Items.Add(item);
    //                            }
    //                        }

    //                        if (_logBuffer.Count > LOG_NUM_LIMIT * 2)
    //                        {
    //                            _logBuffer = _logBuffer.Skip(_logBuffer.Count - LOG_NUM_LIMIT).ToList();
    //                            RefreshLogs();
    //                            isNeedScroll = true;
    //                        }

    //                        if (isNeedScroll && lvLog.Items.Count > 0)
    //                        {
    //                            RefreshLvLayout();
    //                        }
    //                    }));
    //                        }
    //                        catch (Exception ex)
    //                        {
    //                        }

    //                        await Task.Delay(2000);
    //                    }
    //                });
    //            }
    //        }
    //    }

    //    private void RefreshLogs()
    //    {
    //        lvLog.Items.Clear();

    //        _logBuffer.ForEach(log =>
    //        {
    //            if (_showLevels.Contains(log.LogLevel) && ((string.IsNullOrWhiteSpace(log.MsgSource) && _showDevice.Contains(SOURCE_PROCESS)) || _showDevice.Contains(log.MsgSource)))
    //            {
    //                ListViewItem item = new ListViewItem($"{log.LogTime.ToString("HH:mm:ss.fff")}");
    //                item.SubItems.Add($"{log.MsgSource}[{log.ThreadId}]");
    //                item.SubItems.Add(log.Msg);

    //                item.ToolTipText = log.Msg;
    //                item.ForeColor = log.LogLevel.GetEnumSelectedFontColor();
    //                item.BackColor = log.LogLevel.GetEnumSelectedColor();

    //                lvLog.Items.Add(item);
    //            }
    //        });

    //        RefreshLvLayout();
    //    }

    //    private void lvLog_SizeChanged(object sender, EventArgs e)
    //    {
    //        RefreshLvLayout();
    //    }

    //    int width_1stCol = 80;

    //    public event Action<LogMsg> OnLogMsgOutput;

    //    private void RefreshLvLayout()
    //    {
    //        if (lvLog.Columns.Count <= 0)
    //            return;

    //        lvLog.Columns[0].Width = width_1stCol;
    //        if (lvLog.Width <= lvLog.Height)
    //        {
    //            lvLog.Columns[1].Width = 0;
    //        }
    //        else
    //        {
    //            lvLog.Columns[1].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
    //        }
    //        lvLog.Columns[2].Width = lvLog.Width - width_1stCol - lvLog.Columns[1].Width - 10;

    //        if (lvLog.Items.Count > 0)
    //            lvLog.EnsureVisible(lvLog.Items.Count - 1);
    //    }

    //    private void tsmiClearLog_Click(object sender, EventArgs e)
    //    {
    //        lvLog.Items.Clear();
    //    }

    //    private void tsmiClearLog2_Click(object sender, EventArgs e)
    //    {
    //        lvLog.Items.Clear();
    //    }
    //}
}