using BDU.Logic;
using BDU.Models;
using BDU.Tools;
using BDU.Windows;
using Common.Attributes;
using GongSolutions.Wpf.DragDrop.Utilities;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
using static BDU.Models.ParameterModel;
using static Common.Attributes.ATSCommandAttribute;
using Path = System.IO.Path;

namespace BDU.Views
{
    /// <summary>
    /// CommandTreeView.xaml 的交互逻辑
    /// </summary>
    public partial class CommandTreeView : UserControl
    {

        #region 变量声明

        public static CommandTreeView? Instance { get; private set; }

        public ObservableCollection<Assembly> Assemblies { get; set; } = [];

        public ObservableCollection<SubProgramItem> SubPrograms { get; set; } = [];

        public ProgramModel Program => MainWindow.Instance.Program ?? new();

        private Dictionary<object, TreeViewItem> _treeViewItemMap = [];

        private TreeViewItem _subProgramRootNode;

        private readonly Dictionary<string, XmlDocument> _xmlDocumentCache = [];

        #endregion

        public CommandTreeView()
        {
            InitializeComponent();
            Instance = this;
            DataContext = this;
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            Directory.CreateDirectory(SystemConfig.Instance.DLLFilePath);
            Directory.CreateDirectory(SystemConfig.Instance.SubProgramFilePath);
            LoadAllAssemblies();
            LoadSubPrograms();
            LoadInstructionsToTreeView();
        }

        #region 辅助方法

        /// <summary>
        /// 加载指定目录下的所有DLL
        /// </summary>
        private void LoadAllAssemblies()
        {
            Assemblies.Clear();

            foreach (var dllPath in Directory.GetFiles(SystemConfig.Instance.DLLFilePath, "*.dll"))
            {
                try
                {
                    var assembly = Assembly.LoadFrom(dllPath);
                    Assemblies.Add(assembly);

                    // 加载对应的XML注释文件
                    string xmlPath = Path.ChangeExtension(dllPath, ".xml");
                    if (File.Exists(xmlPath))
                    {
                        try
                        {
                            XmlDocument xmlDoc = new XmlDocument();
                            xmlDoc.Load(xmlPath);
                            _xmlDocumentCache[assembly.FullName!] = xmlDoc;
                        }
                        catch (Exception xmlEx)
                        {
                            Log.Warning($"加载XML注释失败: {Path.GetFileName(xmlPath)} - {xmlEx.Message}");
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.Warning($"无法加载程序集 {Path.GetFileName(dllPath)}: {ex.Message}");
                }
            }
        }

        // 添加获取注释的方法
        private string? GetMethodDocumentation(MethodInfo method)
        {
            if (method.DeclaringType == null) return null;

            try
            {
                string assemblyName = method.DeclaringType.Assembly.FullName!;
                if (!_xmlDocumentCache.TryGetValue(assemblyName, out XmlDocument? xmlDoc)) return null;

                // 生成XML文档中的成员ID
                string memberName = $"M:{method.DeclaringType.FullName}.{method.Name}";
                var parameters = method.GetParameters();
                if (parameters.Length > 0)
                {
                    memberName += "(" + string.Join(",", parameters.Select(p => p.ParameterType.FullName?.Replace('+', '.'))) + ")";
                }

                // 查找注释节点
                XmlNode memberNode = xmlDoc.SelectSingleNode($"//member[@name='{memberName}']")!;
                if (memberNode == null) return null;

                // 获取摘要（summary）
                var summaryNode = memberNode.SelectSingleNode("summary");
                string documentation = "";

                if (summaryNode != null)
                {
                    documentation += CleanXmlContent(summaryNode.InnerXml);
                }

                // 获取参数注释（param）
                var paramNodes = memberNode.SelectNodes("param");
                if (paramNodes != null && paramNodes.Count > 0)
                {
                    documentation += "\n\n参数:";
                    foreach (XmlNode paramNode in paramNodes)
                    {
                        string? paramName = paramNode.Attributes?["name"]?.Value;
                        if (!string.IsNullOrEmpty(paramName))
                        {
                            documentation += $"\n  • {paramName}: {CleanXmlContent(paramNode.InnerXml)}";
                        }
                    }
                }

                // 获取返回值注释（returns）
                var returnsNode = memberNode.SelectSingleNode("returns");
                if (returnsNode != null)
                {
                    documentation += $"\n\n返回值: {CleanXmlContent(returnsNode.InnerXml)}";
                }

                return string.IsNullOrWhiteSpace(documentation)
                    ? null
                    : System.Net.WebUtility.HtmlDecode(documentation.Trim());
            }
            catch (Exception ex)
            {
                Log.Warning($"获取注释失败: {method.Name} - {ex.Message}");
                return null;
            }
        }

        // 辅助方法：清理XML内容
        private string CleanXmlContent(string xmlContent)
        {
            return xmlContent
                .Replace("<see cref=\"", "")
                .Replace("\"/>", "")
                .Replace("<para>", "\n")
                .Replace("</para>", "")
                .Replace("<seealso", "")
                .Replace("/>", "")
                .Replace("<c>", "")    // 处理代码标签
                .Replace("</c>", "")
                .Replace("<code>", "")
                .Replace("</code>", "")
                .Trim();
        }

        // 子程序加载方法
        private void LoadSubPrograms()
        {
            SubPrograms.Clear();

            if (!Directory.Exists(SystemConfig.Instance.SubProgramFilePath))
            {
                Directory.CreateDirectory(SystemConfig.Instance.SubProgramFilePath);
                return;
            }

            foreach (var filePath in Directory.GetFiles(SystemConfig.Instance.SubProgramFilePath, "*.ats"))
            {
                try
                {
                    SubPrograms.Add(new SubProgramItem
                    {
                        Name = Path.GetFileNameWithoutExtension(filePath),
                        FilePath = filePath
                    });
                }
                catch (Exception ex)
                {
                    Log.Warning($"加载子程序错误: {filePath} - {ex.Message}");
                }
            }
        }

        // ATS/Views/CommandTreeView.xaml.cs - 修正 LoadInstructionsToTreeView 方法

        /// <summary>
        /// 加载指令集到TreeView
        /// </summary>
        private void LoadInstructionsToTreeView()
        {
            InstructionTreeView.Items.Clear();
            _treeViewItemMap.Clear(); // 清空旧的映射

            // 添加控制指令节点
            var controlRootNode = new TreeViewItem
            {
                Header = "系统指令",
                Tag = "ControlRoot"
            };
            InstructionTreeView.Items.Add(controlRootNode);

            // 添加循环开始节点
            var loopStartNode = new TreeViewItem
            {
                Header = "循环开始",
                Tag = "循环开始"
            };
            controlRootNode.Items.Add(loopStartNode);

            // 添加循环结束节点
            var loopEndNode = new TreeViewItem
            {
                Header = "循环结束",
                Tag = "循环结束"
            };
            controlRootNode.Items.Add(loopEndNode);

            // 创建子程序根节点
            _subProgramRootNode = new TreeViewItem
            {
                Header = "子程序",
                Tag = "SubProgramRoot"
            };
            InstructionTreeView.Items.Add(_subProgramRootNode);

            // 添加子程序节点
            foreach (var subProgram in SubPrograms)
            {
                var subProgramNode = new TreeViewItem
                {
                    Header = subProgram.Name,
                    Tag = subProgram,
                    ToolTip = subProgram.FilePath
                };
                _subProgramRootNode.Items.Add(subProgramNode);
            }

            // 添加dll中的方法指令 - 按分类组织
            foreach (var assembly in Assemblies)
            {
                List<Type> validTypes = new List<Type>();

                try
                {
                    // 类型过滤条件
                    var types = assembly.GetTypes().Where(t =>
                        t.IsPublic &&
                        !t.IsNested &&
                        (t.IsClass || t.IsValueType) &&
                        (!t.IsAbstract || t.IsSealed) &&
                        t.GetCustomAttribute<ATSCommandAttribute>() != null);

                    foreach (var type in types)
                    {
                        if (type.GetCustomAttribute<BrowsableAttribute>()?.Browsable == false)
                            continue;

                        // 检查类型是否有有效方法（包括继承的方法）
                        var allMethods = new HashSet<MethodInfo>();
                        GetPublicMethods(type, allMethods);

                        if (allMethods.Count > 0)
                        {
                            validTypes.Add(type);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.Error($"加载类型错误: {assembly.FullName} - {ex.Message}");
                }

                // 只有当程序集包含有效类型时才添加节点
                if (validTypes.Count > 0)
                {
                    var assemblyNode = new TreeViewItem
                    {
                        Header = assembly.GetName().Name,
                        Tag = assembly
                    };
                    InstructionTreeView.Items.Add(assemblyNode);
                    _treeViewItemMap[assembly] = assemblyNode;

                    // 按分类组织类型 - 修改这部分逻辑
                    foreach (var type in validTypes)
                    {
                        // 获取该类型的所有 DeviceCategoryAttribute 实例
                        var categoryAttributes = type.GetCustomAttributes<DeviceCategoryAttribute>().ToArray();

                        // 获取所有分类名称，如果没有则归为 "未分类"
                        string[] categories = categoryAttributes.Length > 0 ?
                            categoryAttributes.Select(attr => attr.Category).ToArray() :
                            new[] { "未分类" };

                        // 获取该类型的所有公共方法，供后续在不同分类下复用
                        var allMethods = new HashSet<MethodInfo>();
                        GetPublicMethods(type, allMethods);

                        // 为该类型的每个分类创建节点
                        foreach (var category in categories)
                        {
                            // 检查该程序集下是否已存在该分类节点
                            var categoryNode = assemblyNode.Items.OfType<TreeViewItem>()
                                .FirstOrDefault(item => item.Header?.ToString() == category);

                            // 如果不存在，则创建新的分类节点
                            if (categoryNode == null)
                            {
                                categoryNode = new TreeViewItem
                                {
                                    Header = category,
                                    Tag = $"Category_{category}"
                                };
                                assemblyNode.Items.Add(categoryNode);
                            }

                            // 为当前分类创建一个 typeNode 实例
                            var typeNode = new TreeViewItem
                            {
                                Header = type.Name,
                                Tag = type, // Tag 仍然指向原始类型，方便后续处理
                                ToolTip = type.FullName
                            };
                            // 添加到当前分类节点
                            categoryNode.Items.Add(typeNode);
                            // 重要：将这个 *特定的* TreeViewItem 实例映射到 *原始的* Type 对象
                            // 这样在双击时可以通过 SelectedItem.Tag 找到原始 Type
                            // 如果有多个分类，最后添加的那个分类下的 typeNode 会覆盖前面的映射
                            // 如果需要精确映射到具体哪个分类下的节点，需要更复杂的结构
                            _treeViewItemMap[type] = typeNode;

                            // 为当前分类下的 typeNode 创建方法节点
                            foreach (var method in allMethods)
                            {
                                // 跳过特殊名称方法（属性访问器等）
                                if (method.IsSpecialName) continue;
                                // 跳过系统对象方法
                                if (method.DeclaringType == typeof(object)) continue;
                                // 跳过特定名称的系统方法
                                string[] ignoreMethods = { "GetType", "ToString", "Equals", "GetHashCode" };
                                if (ignoreMethods.Contains(method.Name)) continue;
                                // 跳过不可浏览的方法
                                if (method.GetCustomAttribute<BrowsableAttribute>()?.Browsable == false) continue;
                                // 对于静态类，只显示静态方法
                                if (type.IsAbstract && type.IsSealed && !method.IsStatic) continue;

                                var parameters = method.GetParameters();
                                var paramText = string.Join(", ", parameters.Select(p => $"{p.ParameterType.Name} {p.Name}"));

                                // 获取方法注释
                                string summary = GetMethodDocumentation(method) ?? "";
                                string tooltipContent = $"{method.DeclaringType?.FullName}.{method.Name}";
                                if (!string.IsNullOrEmpty(summary)) tooltipContent = $"{tooltipContent}\n\n{summary}";

                                // 为当前分类下的 typeNode 创建一个 methodNode 实例
                                var methodNode = new TreeViewItem
                                {
                                    Header = $"{method.Name}({paramText})",
                                    Tag = new MethodInfoWrapper(method),
                                    ToolTip = tooltipContent
                                };
                                // 添加到当前分类下的 typeNode
                                typeNode.Items.Add(methodNode);
                                // 重要：将这个 *特定的* TreeViewItem 实例映射到 *原始的* MethodInfo 对象
                                // 如果有多个分类，最后添加的那个分类下的 methodNode 会覆盖前面的映射
                                // 如果需要精确映射到具体哪个分类下的节点，需要更复杂的结构
                                _treeViewItemMap[method] = methodNode;
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 递归获取类型的所有公共方法（包括继承的方法），但跳过被重写的方法
        /// </summary>
        /// <param name="type">要处理的目标类型</param>
        /// <param name="methods">存储方法的集合</param>
        private void GetPublicMethods(Type type, HashSet<MethodInfo> methods)
        {
            // 获取当前类型的所有公共方法（包括继承的）
            var allMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
                .Where(m => !m.IsSpecialName &&
                            m.DeclaringType != typeof(object))
                .ToList();

            // 按方法签名分组
            var groupedMethods = allMethods
                .GroupBy(m => new { m.Name, Parameters = string.Join(",", m.GetParameters().Select(p => p.ParameterType.FullName)) });

            foreach (var group in groupedMethods)
            {
                // 从组中选择声明类型最接近当前类型（即继承层次最深）的方法
                MethodInfo? selectedMethod = null;
                int minDepth = int.MaxValue;

                foreach (var method in group)
                {
                    // 计算声明类型的深度
                    int depth = 0;
                    Type? current = type;
                    Type declaringType = method.DeclaringType!;

                    while (current != null && current != declaringType)
                    {
                        depth++;
                        current = current.BaseType;
                    }

                    // 如果找到声明类型且在继承链上
                    if (current == declaringType)
                    {
                        if (selectedMethod == null || depth < minDepth)
                        {
                            selectedMethod = method;
                            minDepth = depth;
                        }
                    }
                }

                if (selectedMethod != null)
                {
                    methods.Add(selectedMethod);
                }
            }
        }

        private void ReOrderProgramList()
        {
            for (int i = 0; i < Program.StepCollection.Count; i++)
            {
                Program.StepCollection[i].Index = i + 1;
            }
        }

        private void UnselectTreeViewItems(ItemsControl itemsControl)
        {
            for (int i = 0; i < itemsControl.Items.Count; i++)
            {
                var item = itemsControl.Items[i];
                if (itemsControl.ItemContainerGenerator.ContainerFromItem(item) is TreeViewItem container)
                {
                    container.IsSelected = false;
                    UnselectTreeViewItems(container);
                }
            }
        }

        #region 指令添加

        private void AddMethodToProgram(MethodInfo method, int insertIndex = -1)
        {
            try
            {
                var newStep = new StepModel
                {
                    Name = method.Name,
                    StepType = "方法",
                    Method = new MethodModel
                    {
                        FullName = method.DeclaringType?.FullName,
                        Name = method.Name
                    }
                };

                // 添加输入参数
                foreach (var param in method.GetParameters())
                {
                    newStep.Method.Parameters.Add(new ParameterModel
                    {
                        Name = param.Name!,
                        Type = param.ParameterType,
                        Category = ParameterCategory.Input
                    });
                }

                // 添加输出参数（返回值）
                Type returnType = method.ReturnType;
                if (returnType == typeof(Task))
                {
                    // 不添加输出参数（无返回值）
                }
                else if (returnType.IsGenericType &&
                        returnType.GetGenericTypeDefinition() == typeof(Task<>))
                {
                    // 提取实际返回类型（如 Task<bool> -> bool）
                    Type actualType = returnType.GetGenericArguments()[0];
                    newStep.Method.Parameters.Add(new ParameterModel
                    {
                        Name = "Result",
                        Type = actualType, // 使用实际类型
                        Category = ParameterCategory.Output
                    });
                }
                else if (returnType != typeof(void))
                {
                    // 同步方法正常添加
                    newStep.Method.Parameters.Add(new ParameterModel
                    {
                        Name = "Result",
                        Type = returnType,
                        Category = ParameterCategory.Output
                    });
                }

                // 添加到程序
                if (insertIndex >= 0 && insertIndex <= Program.StepCollection.Count)
                {
                    Program.StepCollection.Insert(insertIndex, newStep);
                }
                else
                {
                    Program.StepCollection.Add(newStep);
                }

                ReOrderProgramList();
            }
            catch (Exception ex)
            {
                Log.Error($"添加方法失败: {method.Name} - {ex.Message}");
            }
        }

        private void AddSubProgramToProgram(SubProgramItem subProgram, int insertIndex = -1)
        {
            try
            {
                var newStep = new StepModel
                {
                    Name = subProgram.Name,
                    StepType = "子程序"
                };
                var jsonstr = File.ReadAllText($"{subProgram.FilePath}");
                var tmp = JsonConvert.DeserializeObject<ProgramModel>(jsonstr);
                if (tmp != null)
                {
                    if (tmp.Devices != null && tmp.Devices.Count > 0)
                    {
                        foreach (var device in tmp.Devices)
                        {
                            _ = DeviceConnect.InitAndConnectDevice(tmp, device);
                        }
                    }
                    newStep.SubProgram = tmp;
                }
                // 添加到程序
                if (insertIndex >= 0 && insertIndex <= Program.StepCollection.Count)
                {
                    Program.StepCollection.Insert(insertIndex, newStep);
                }
                else
                {
                    Program.StepCollection.Add(newStep);
                }

                ReOrderProgramList();
            }
            catch (Exception ex)
            {
                Log.Error($"添加子程序失败: {subProgram.Name} - {ex.Message}");
            }
        }

        private void AddLoopStartStep(int insertIndex = -1)
        {
            var newStep = new StepModel
            {
                Name = "循环开始",
                StepType = "循环开始",
                LoopCount = 1,
                Method = new() { Parameters = [new() { Name = "循环次数", Type = typeof(int), Category = ParameterCategory.Input }] }
            };

            if (insertIndex >= 0)
            {
                Program.StepCollection.Insert(insertIndex, newStep);
            }
            else
            {
                Program.StepCollection.Add(newStep);
            }

            ReOrderProgramList();
        }

        private void AddLoopEndStep(int insertIndex = -1)
        {
            // 查找最近的未匹配循环开始
            StepModel? lastUnmatchedLoopStart = null;
            for (int i = Program.StepCollection.Count - 1; i >= 0; i--)
            {
                if (Program.StepCollection[i].StepType == "循环开始")
                {
                    bool isMatched = Program.StepCollection.Any(s => s.StepType == "循环结束" && s.LoopStartStepId == Program.StepCollection[i].ID);

                    if (!isMatched)
                    {
                        lastUnmatchedLoopStart = Program.StepCollection[i];
                        break;
                    }
                }
            }

            var newStep = new StepModel
            {
                Name = "循环结束",
                StepType = "循环结束",
                LoopStartStepId = lastUnmatchedLoopStart?.ID
            };

            if (insertIndex >= 0)
            {
                Program.StepCollection.Insert(insertIndex, newStep);
            }
            else
            {
                Program.StepCollection.Add(newStep);
            }

            ReOrderProgramList();
        }

        #endregion

        #endregion

        #region 私有类

        private class MethodInfoWrapper
        {
            public MethodInfo Method { get; }

            public MethodInfoWrapper(MethodInfo method)
            {
                Method = method;
            }
        }

        #endregion

        private void InstructionTreeView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (MainWindow.Instance.User.Role < 1)
            {
                MessageBox.Show("当前登录用户无权限");
                return;
            }
            if (InstructionTreeView.SelectedItem is TreeViewItem selectedItem)
            {
                int insertIndex = -1;
                if (StepsManager.Instance!.SelectedIndex >= 0)
                {
                    insertIndex = StepsManager.Instance.SelectedIndex + 1;
                }

                if (selectedItem.Tag is string tagString)
                {
                    if (tagString == "循环开始")
                    {
                        AddLoopStartStep(insertIndex);
                    }
                    else if (tagString == "循环结束")
                    {
                        AddLoopEndStep(insertIndex);
                    }
                }
                else if (selectedItem.Tag is MethodInfoWrapper wrapper)
                {
                    AddMethodToProgram(wrapper.Method, insertIndex);
                }
                else if (selectedItem.Tag is MethodInfo methodInfo)
                {
                    AddMethodToProgram(methodInfo, insertIndex);
                }
                else if (selectedItem.Tag is SubProgramItem subProgram)
                {
                    AddSubProgramToProgram(subProgram, insertIndex);
                }

                StepsManager.Instance.SelectedIndex = insertIndex;
                UnselectTreeViewItems(InstructionTreeView);
            }
        }

        private void RelodCommand_Click(object sender, RoutedEventArgs e)
        {
            LoadAllAssemblies();
            LoadSubPrograms();
            LoadInstructionsToTreeView();
        }

        // 在类中添加变量
        private Dictionary<TreeViewItem, Brush> _originalBrushes = new();
        private HashSet<TreeViewItem> _matchedItems = new();

        // 添加搜索方法
        private void SearchTreeView(string searchText)
        {
            // 清除上次搜索结果
            ClearSearchHighlighting();

            if (string.IsNullOrWhiteSpace(searchText)) ClearSearchButton_Click(null, null);

            searchText = searchText.Trim().ToLower();

            // 遍历所有节点
            foreach (var item in InstructionTreeView.Items.OfType<TreeViewItem>())
            {
                SearchTreeViewItem(item, searchText);
            }

            // 展开所有包含匹配项的节点
            foreach (var matchedItem in _matchedItems.ToList())
            {
                ExpandParents(matchedItem);
            }
        }

        private void SearchTreeViewItem(TreeViewItem item, string searchText)
        {
            // 检查当前节点是否匹配
            bool isMatch = false;

            if (string.IsNullOrEmpty(searchText))
            {

            }
            else if (item.Header is string headerText && headerText.Split("(")[0].ToLower().Contains(searchText))
            {
                isMatch = true;
            }

            if (isMatch)
            {
                // 保存原始背景色并设置高亮
                if (!_originalBrushes.ContainsKey(item))
                {
                    _originalBrushes[item] = item.Background;
                }
                item.Background = Brushes.Yellow;
                _matchedItems.Add(item);
            }

            // 递归搜索子节点
            foreach (var childItem in item.Items.OfType<TreeViewItem>())
            {
                SearchTreeViewItem(childItem, searchText);
            }
        }

        private void ClearSearchHighlighting()
        {
            foreach (var item in _matchedItems)
            {
                if (_originalBrushes.TryGetValue(item, out var originalBrush))
                {
                    item.Background = originalBrush;
                }
                else
                {
                    item.ClearValue(TreeViewItem.BackgroundProperty);
                }
            }

            _matchedItems.Clear();
            _originalBrushes.Clear();
        }

        private void ExpandParents(TreeViewItem item)
        {
            var parent = ItemsControl.ItemsControlFromItemContainer(item) as TreeViewItem;
            while (parent != null)
            {
                parent.IsExpanded = true;
                parent = ItemsControl.ItemsControlFromItemContainer(parent) as TreeViewItem;
            }
        }

        // 添加事件处理方法
        private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(SearchTextBox.Text))
            {
                ClearSearchHighlighting();
            }
        }

        private void SearchTextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                SearchTreeView(SearchTextBox.Text);
            }
        }

        private void ClearSearchButton_Click(object sender, RoutedEventArgs e)
        {
            SearchTextBox.Clear();
            ClearSearchHighlighting();
        }
    }
}
