using UIShare.UIViewModel;
using UIShare.GlobalVariable;
using Common.Attributes;
using Logger;
using Microsoft.IdentityModel.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
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.Input;
using System.Xml;
using Model;
using static UIShare.UIViewModel.ParameterVM;
using UIShare.ViewModelBase;
using NLog;

namespace TestingModule.ViewModels
{
    public class CommandTreeViewModel:NavigateViewModelBase,IDisposable
    {
        #region 属性
        private string _SearchText;

        public string SearchText
        {
            get => _SearchText;
            set => SetProperty(ref _SearchText, value);
        }
        private ObservableCollection<InstructionNodeVM> _instructionTree = new();
        public ObservableCollection<InstructionNodeVM> InstructionTree
        {
            get => _instructionTree;
            set => SetProperty(ref _instructionTree, value);
        }

        public ProgramVM Program
        {
            get => _ScopedContext.Program;
            set
            {
                if (_ScopedContext.Program != value)
                {
                    _ScopedContext.Program = value;
                    RaisePropertyChanged();
                }
            }
        }

        public ObservableCollection<Assembly> Assemblies
        {
            get => _ScopedContext.Assemblies;
            set
            {
                if (_ScopedContext.Assemblies != value)
                {
                    _ScopedContext.Assemblies = value;
                    RaisePropertyChanged();
                }
            }
        }

        private ObservableCollection<SubProgramItemVM> _subPrograms = new();
        public ObservableCollection<SubProgramItemVM> SubPrograms
        {
            get => _subPrograms;
            set => SetProperty(ref _subPrograms, value);
        }

        private Dictionary<object, InstructionNodeVM> _treeNodeMap = new();
        public Dictionary<object, InstructionNodeVM> TreeNodeMap
        {
            get => _treeNodeMap;
            set => SetProperty(ref _treeNodeMap, value);
        }

        private Dictionary<string, XmlDocument> _xmlDocumentCache = new();

        public Dictionary<string, XmlDocument> XmlDocumentCache
        {
            get => _xmlDocumentCache;
            set => SetProperty(ref _xmlDocumentCache, value);
        }
        #endregion
        public ICommand LoadedCommand { get; set; }
        public ICommand SearchEnterCommand { get; set; }
        public ICommand TreeDoubleClickCommand { get; set; }
        public ICommand ReloadCommand { get; set; } 
        private ScopedContext _ScopedContext { get; set; }
        private readonly SystemConfig _systemConfig;
        private readonly GlobalInfo _globalInfo;

        public CommandTreeViewModel(IContainerProvider containerProvider, ScopedContext scopedContext, SystemConfig systemConfig, GlobalInfo globalInfo) : base(containerProvider)
        {
            _ScopedContext = scopedContext;
            _systemConfig = systemConfig;
            _globalInfo = globalInfo;
            LoadedCommand = new DelegateCommand(Loaded);
            SearchEnterCommand = new DelegateCommand(Search);
            TreeDoubleClickCommand = new DelegateCommand<object>(TreeDoubleClick);
            ReloadCommand = new DelegateCommand(Reload);
        }

        public void Dispose()
        {
            try
            {
                _ScopedContext = null!;
                InstructionTree?.Clear();
                SubPrograms?.Clear();
                TreeNodeMap?.Clear();
                XmlDocumentCache?.Clear();
                InstructionTree = null!;
                SubPrograms = null!;
                TreeNodeMap = null!;
                XmlDocumentCache = null!;
            }
            catch (Exception ex)
            {
                LoggerHelper.Error($"清理指令树缓存失败: {ex.Message}");
            }
        }
        #region 委托命令
        private void Reload()
        {
            LoadAllAssemblies();
            LoadSubPrograms();
            LoadInstructionsToTreeView();
        }
        private void TreeDoubleClick(object obj)
        {
            if (!_globalInfo.IsAdmin) return;
            if(obj is InstructionNodeVM Node)
            {
                if(Node.Children.Count == 0)
                {
                    int index = _ScopedContext.SelectedStep?.Index >= 0 ? _ScopedContext.SelectedStep.Index : -1;
                    if (Node.Tag is MethodInfo method)
                    {
                        AddMethodToProgram(method, index);
                    }
                    else if(Node.Tag is string tag)
                    {
                        switch (tag)
                        {
                            case "循环开始":
                                AddLoopStartStep(index);
                                break;
                            case "循环结束":
                                AddLoopEndStep(index);
                                break;
                        }
                    }
                    else if(Node.Tag is SubProgramItemVM subProgram)
                    {
                        AddSubProgramToProgram(subProgram, index);
                    }
                }
            }
        }
        private void Search()
        {
            
        }

        private void Loaded()
        {
            LoadAllAssemblies();
            LoadSubPrograms();
            LoadInstructionsToTreeView();
        }
        #endregion
        #region 加载指令
        /// <summary>
        /// 加载指定目录下的所有DLL
        /// </summary>
        private void LoadAllAssemblies()
        {
            Assemblies.Clear();

            foreach (var dllPath in Directory.GetFiles(_systemConfig.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)
                    //    {
                    //        LoggerHelper.WarnWithNotify($"加载XML注释失败: {Path.GetFileName(xmlPath)} - {xmlEx.Message}");
                    //    }
                    //}
                }
                catch (Exception ex)
                {
                    LoggerHelper.WarnWithNotify(_globalInfo.CurrentScope, $"无法加载程序集 {Path.GetFileName(dllPath)}: {ex.Message}");
                }
            }
        }
        // 子程序加载方法
        private void LoadSubPrograms()
        {
            SubPrograms.Clear();

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

            foreach (var filePath in Directory.GetFiles(_systemConfig.SubProgramFilePath, "*.adp"))
            {
                try
                {
                    SubPrograms.Add(new SubProgramItemVM
                    {
                        Name = Path.GetFileNameWithoutExtension(filePath),
                        FilePath = filePath
                    });
                }
                catch (Exception ex)
                {
                    LoggerHelper.WarnWithNotify(_globalInfo.CurrentScope, $"加载子程序错误: {filePath} - {ex.Message}");
                }
            }
        }
        /// <summary>
        /// 加载指令集到TreeView
        /// </summary>
        private void LoadInstructionsToTreeView()
        {
            InstructionTree.Clear();
            var controlRootNode = new InstructionNodeVM
            {
                Name = "系统指令",
                Tag = "ControlRoot"
            };
            InstructionTree.Add(controlRootNode);

            // 循环开始
            controlRootNode.Children.Add(new InstructionNodeVM
            {
                Name = "循环开始",
                Tag = "循环开始"
            });

            // 循环结束
            controlRootNode.Children.Add(new InstructionNodeVM
            {
                Name = "循环结束",
                Tag = "循环结束"
            });

            // ----------------------
            // 子程序 根节点
            // ----------------------
            var subProgramRoot = new InstructionNodeVM
            {
                Name = "子程序",
                Tag = "SubProgramRoot"
            };
            InstructionTree.Add(subProgramRoot);

            foreach (var subProgram in SubPrograms)
            {
                subProgramRoot.Children.Add(new InstructionNodeVM
                {
                    Name = subProgram.Name,
                    Tag = subProgram,
                });
            }

            // ----------------------
            // 动态 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<ADPCommandAttribute>() != 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)
                {
                    LoggerHelper.ErrorWithNotify(_globalInfo.CurrentScope, $"加载类型错误: {assembly.FullName} - {ex.Message}");
                }

                if (validTypes.Count > 0)
                {
                    var assemblyNode = new InstructionNodeVM
                    {
                        Name = assembly.GetName().Name,
                        Tag = assembly
                    };
                    InstructionTree.Add(assemblyNode);
                    TreeNodeMap[assembly] = assemblyNode;

                    foreach (var type in validTypes)
                    {
                        //拦截没有在设备列表中的设备类型
                        //if (_systemConfig.DeviceList.Where(x=>x.Remark==type.Name).ToList().Count==0 && type.FullName.Contains("DeviceCommand.Devices"))
                        //{
                        //    continue;
                        //}
                       
                        var typeNode = new InstructionNodeVM
                        {
                            Name = type.Name,
                            Tag = type,
                        };
                        assemblyNode.Children.Add(typeNode);
                        TreeNodeMap[type] = typeNode;

                        var allMethods = new HashSet<MethodInfo>();
                        GetPublicMethods(type, allMethods);

                        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}"));

                            var methodNode = new InstructionNodeVM
                            {
                                Name = $"{method.Name}({paramText})",
                                Tag = method,
                            };

                            typeNode.Children.Add(methodNode);
                            TreeNodeMap[method] = methodNode;
                        }
                    }
                }
            }
        }

        #endregion
        #region 辅助方法
        /// <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 | BindingFlags.DeclaredOnly)
                .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);
                }
            }
        }
        #endregion
        #region 指令添加

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

                // 添加输入参数
                foreach (var param in method.GetParameters())
                {
                    newStep.Method.Parameters.Add(new ParameterVM
                    {
                        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 ParameterVM
                    {
                        Name = "Result",
                        Type = actualType, // 使用实际类型
                        Category = ParameterCategory.Output
                    });
                }
                else if (returnType != typeof(void))
                {
                    // 同步方法正常添加
                    newStep.Method.Parameters.Add(new ParameterVM
                    {
                        Name = "Result",
                        Type = returnType,
                        Category = ParameterCategory.Output
                    });
                }

                // 添加到程序
                if(_ScopedContext.SelectedStepList == "主程序")
                {
                    if(insertIndex >= 0 && insertIndex <= Program.StepCollection.Count) Program.StepCollection.Insert(insertIndex, newStep);
                    else Program.StepCollection.Add(newStep);                }
                else
                {
                    if (insertIndex >= 0 && insertIndex <= Program.ErrorStepCollection.Count) Program.ErrorStepCollection.Insert(insertIndex, newStep);
                    else  Program.ErrorStepCollection.Add(newStep);
                }
            }
            catch (Exception ex)
            {
                LoggerHelper.ErrorWithNotify(_globalInfo.CurrentScope, $"添加方法失败: {method.Name} - {ex.Message}");
            }
        }

        private void AddSubProgramToProgram(SubProgramItemVM subProgram, int insertIndex = -1)
        {
            try
            {
                var newStep = new StepVM
                {
                    Name = subProgram.Name,
                    StepType = "子程序"
                };
                var jsonstr = File.ReadAllText($"{subProgram.FilePath}");
                var tmp = JsonConvert.DeserializeObject<ProgramVM>(jsonstr);
                if (tmp != null)
                {
                    newStep.SubProgram = tmp;
                }
                // 添加到程序
                if (_ScopedContext.SelectedStepList == "主程序")
                {
                    if (insertIndex >= 0 && insertIndex <= Program.StepCollection.Count) Program.StepCollection.Insert(insertIndex, newStep);
                    else Program.StepCollection.Add(newStep);
                }
                else
                {
                    if (insertIndex >= 0 && insertIndex <= Program.ErrorStepCollection.Count) Program.ErrorStepCollection.Insert(insertIndex, newStep);
                    else Program.ErrorStepCollection.Add(newStep);
                }
            }
            catch (Exception ex)
            {
                LoggerHelper.ErrorWithNotify(_globalInfo.CurrentScope, $"添加子程序失败: {subProgram.Name} - {ex.Message}"); ;
            }
        }

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

            // 添加到程序
            if (_ScopedContext.SelectedStepList == "主程序")
            {
                if (insertIndex >= 0) Program.StepCollection.Insert(insertIndex, newStep);
                else Program.StepCollection.Add(newStep);
            }
            else
            {
                if (insertIndex >= 0) Program.ErrorStepCollection.Insert(insertIndex, newStep);
                else Program.ErrorStepCollection.Add(newStep);
            }
        }

        private void AddLoopEndStep(int insertIndex = -1)
        {
            // 查找最近的未匹配循环开始
            StepVM? 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 StepVM
            {
                Name = "循环结束",
                StepType = "循环结束",
                LoopStartStepId = lastUnmatchedLoopStart?.ID
            };

            // 添加到程序
            if (_ScopedContext.SelectedStepList == "主程序")
            {
                if (insertIndex >= 0) Program.StepCollection.Insert(insertIndex, newStep);
                else Program.StepCollection.Add(newStep);
            }
            else
            {
                if (insertIndex >= 0) Program.ErrorStepCollection.Insert(insertIndex, newStep);
                else Program.ErrorStepCollection.Add(newStep);
            }
        }

        

        #endregion

    }
}
