using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Channels;
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.Windows.Threading;
using System.Xml.Linq;
using static System.Net.Mime.MediaTypeNames;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace Ramitta
{
    public partial class winTreeList : UserControl, INotifyPropertyChanged
    {
        #region 初始化
        public event PropertyChangedEventHandler? PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public winTreeList()
        {
            InitializeComponent();
            Nodes = new ObservableCollection<TreeNode>();
        }
        #endregion
        #region 公共属性
        /// <summary>
        /// 获取或设置树形列表的节点集合
        /// </summary>
        public ObservableCollection<TreeNode> Nodes
        {
            get { return (ObservableCollection<TreeNode>)GetValue(NodesProperty); }
            set { SetValue(NodesProperty, value); }
        }

        public static readonly DependencyProperty NodesProperty =
            DependencyProperty.Register("Nodes", typeof(ObservableCollection<TreeNode>),
                typeof(winTreeList), new PropertyMetadata(null, OnNodesChanged));

        private static void OnNodesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = (winTreeList)d;
            control.treeView.ItemsSource = control.Nodes;
        }

        #endregion

        #region 公共方法
        #region 增
        public LabelTreeNode AddLabelNode(string text, TreeNode? parent = null)
        {
            var label = new Label()
            {
                Content = text
            };

            var node = new LabelTreeNode
            {
                Text = text,
                obj = label
            };

            AddNode(node, parent);
            return node;
        }
        public CheckboxTreeNode AddCheckboxNode(string text, string? tag = null, bool isChecked = false, TreeNode? parent = null)
        {
            var checkbox = new CheckBox()
            {
                IsChecked = isChecked,
                Content = text,
                Tag = tag ?? text,
                ToolTip = tag ?? text,
                Foreground = Brushes.White,
                VerticalAlignment = VerticalAlignment.Center
            };

            var node = new CheckboxTreeNode
            {
                Text = text,
                obj = checkbox
            };

            AddNode(node, parent);
            return node;
        }
        public ComboboxTreeNode AddComboboxNode(string text, List<string>? items = null, TreeNode? parent = null)
        {
            var combobox = new ComboBox()
            {
                SelectedIndex = 0,
                VerticalAlignment = VerticalAlignment.Center,
                MinWidth = 100
            };

            var node = new ComboboxTreeNode
            {
                Text = text,
                obj = combobox
            };

            AddNode(node, parent);
            return node;
        }
        #endregion
        #region 查
        public List<xTreeNode> FindAllTreeNodes<xTreeNode>(
            IEnumerable<TreeNode>? nodes,
            Func<TreeNode, bool> predicate = null)
            where xTreeNode : class
        {
            var result = new List<xTreeNode>();

            if (nodes == null)
                nodes = Nodes;

            foreach (var node in nodes)
            {
                // 检查当前节点是否匹配类型和条件
                if (node is xTreeNode targetNode &&
                    (predicate == null || predicate(node)))
                {
                    result.Add(targetNode);
                }

                // 递归查找子节点
                if (node.Children.Count > 0)
                {
                    var childResults = FindAllTreeNodes<xTreeNode>(node.Children, predicate);
                    result.AddRange(childResults);
                }
            }
            return result;
        }

        #endregion
        #region 删
        /// <summary>
        /// 从树中删除指定节点
        /// </summary>
        /// <param name="nodeToRemove">要删除的节点</param>
        /// <returns>是否成功删除</returns>
        public bool RemoveNode(TreeNode nodeToRemove)
        {
            if (nodeToRemove == null)
                return false;

            // 如果节点有父节点，从父节点的 Children 中删除
            if (nodeToRemove.Parent != null)
            {
                return nodeToRemove.Parent.Children.Remove(nodeToRemove);
            }
            // 如果是根节点，从 Nodes 集合中删除
            else
            {
                return Nodes.Remove(nodeToRemove);
            }
        }

        /// <summary>
        /// 批量删除多个节点
        /// </summary>
        /// <param name="nodesToRemove">要删除的节点列表</param>
        public void RemoveNodes(IEnumerable<TreeNode> nodesToRemove)
        {
            foreach (var node in nodesToRemove.ToList()) // 使用 ToList() 避免修改集合时的枚举错误
            {
                RemoveNode(node);
            }
        }
        #endregion

        #region 序列化
        public JObject JsonPrint(IEnumerable<TreeNode>? nodes = null, int loop = 0)
        {
            // 如果传入的节点为空，使用默认的 Nodes 集合
            if (nodes == null) nodes = Nodes;

            JObject resultObject = new JObject();

            foreach (var node in nodes)
            {
                JObject nodeObject = new JObject();

                // 为当前节点添加基本信息
                nodeObject["Type"] = node.GetType().Name;
                nodeObject["Text"] = node.Text; // 添加文本内容

                // 使用模式匹配简化类型检查
                switch (node)
                {
                    case CheckboxTreeNode checkboxNode:
                        nodeObject["IsChecked"] = checkboxNode.obj.IsChecked?.ToString() ?? "false";
                        nodeObject["Tag"] = checkboxNode.obj.Tag?.ToString() ?? string.Empty;
                        break;

                    case ComboboxTreeNode comboboxNode:
                        nodeObject["SelectedItem"] = comboboxNode.obj.SelectedItem?.ToString() ?? string.Empty;
                        nodeObject["SelectedIndex"] = comboboxNode.obj.SelectedIndex;
                        // 添加所有选项
                        var items = new JArray();
                        foreach (var item in comboboxNode.obj.Items)
                        {
                            items.Add(item.ToString());
                        }
                        nodeObject["Items"] = items;
                        break;

                    case LabelTreeNode labelNode:
                        nodeObject["Content"] = labelNode.obj.Content?.ToString() ?? string.Empty;
                        break;
                }

                // 处理子节点 - 使用更合适的属性名
                if (node.Children.Count > 0)
                {
                    JObject childrenObject = JsonPrint(node.Children, loop + 1);
                    nodeObject["Children"] = childrenObject; // 改为更合适的属性名
                }

                // 使用唯一键名避免重复键问题
                string key = node.Text;
                int counter = 1;
                while (resultObject.ContainsKey(key))
                {
                    key = $"{node.Text}_{counter}";
                    counter++;
                }

                resultObject.Add(key, nodeObject);
            }

            return resultObject;
        }

        public void JsonParse(string jsonContent)
        {
            // 清空现有数据
            Clear();

            if (string.IsNullOrWhiteSpace(jsonContent))
                return;

            try
            {
                JObject rootObject = JObject.Parse(jsonContent);
                ParseNodes(rootObject, null);
            }
            catch (Exception ex)
            {
                // 处理解析异常，可以根据需要记录日志或抛出异常
                Debug.WriteLine($"JSON解析失败: {ex.Message}");
                throw new ArgumentException("无效的JSON格式", ex);
            }
        }

        private void ParseNodes(JObject jObject, TreeNode parent)
        {
            foreach (var property in jObject.Properties())
            {
                JObject nodeObject = property.Value as JObject;
                if (nodeObject == null)
                    continue;

                // 获取节点类型
                string nodeType = nodeObject["Type"]?.ToString() ?? "";
                string text = nodeObject["Text"]?.ToString() ?? "";

                TreeNode newNode = null;

                // 根据类型创建相应的节点
                switch (nodeType)
                {
                    case nameof(LabelTreeNode):
                        newNode = CreateLabelTreeNode(nodeObject, text);
                        break;

                    case nameof(CheckboxTreeNode):
                        newNode = CreateCheckboxTreeNode(nodeObject, text);
                        break;

                    case nameof(ComboboxTreeNode):
                        newNode = CreateComboboxTreeNode(nodeObject, text);
                        break;

                    default:
                        break;
                }

                if (newNode != null)
                {
                    // 添加到树中
                    if (parent == null)
                    {
                        Nodes.Add(newNode);
                    }
                    else
                    {
                        newNode.Parent = parent;
                        parent.Children.Add(newNode);
                    }

                    // 递归处理子节点
                    if (nodeObject["Children"] is JObject childrenObject)
                    {
                        ParseNodes(childrenObject, newNode);
                    }
                }
            }
        }

        private LabelTreeNode CreateLabelTreeNode(JObject nodeObject, string text)
        {
            var labelNode = new LabelTreeNode
            {
                Text = text,
                obj = new Label
                {
                    Content = nodeObject["Content"]?.ToString() ?? text
                }
            };
            return labelNode;
        }

        private CheckboxTreeNode CreateCheckboxTreeNode(JObject nodeObject, string text)
        {
            bool isChecked = bool.TryParse(nodeObject["IsChecked"]?.ToString(), out var result) && result;
            string tag = nodeObject["Tag"]?.ToString() ?? text;

            var checkboxNode = new CheckboxTreeNode
            {
                Text = text,
                obj = new CheckBox
                {
                    Content = text,
                    IsChecked = isChecked,
                    Tag = tag,
                    ToolTip = tag,
                    VerticalAlignment = VerticalAlignment.Center
                }
            };
            return checkboxNode;
        }

        private ComboboxTreeNode CreateComboboxTreeNode(JObject nodeObject, string text)
        {
            var comboboxNode = new ComboboxTreeNode
            {
                Text = text,
                obj = new ComboBox
                {
                    VerticalAlignment = VerticalAlignment.Center,
                    MinWidth = 100
                }
            };

            // 添加选项
            if (nodeObject["Items"] is JArray itemsArray)
            {
                foreach (var item in itemsArray)
                {
                    comboboxNode.obj.Items.Add(item.ToString());
                }
            }

            // 设置选中项
            int selectedIndex = nodeObject["SelectedIndex"]?.Value<int>() ?? 0;
            if (selectedIndex >= 0 && selectedIndex < comboboxNode.obj.Items.Count)
            {
                comboboxNode.obj.SelectedIndex = selectedIndex;
            }

            return comboboxNode;
        }
        #endregion

        #region 动力学
        public void Clear()
        {
            Nodes.Clear();
        }
        public void ExpandAll()
        {
            foreach (var node in Nodes)
            {
                ExpandNode(node);
            }
        }
        public void CollapseAll()
        {
            foreach (var node in Nodes)
            {
                CollapseNode(node);
            }
        }

        public void ExpandNode(TreeNode node)
        {
            var container = treeView.ItemContainerGenerator.ContainerFromItem(node) as TreeViewItem;
            if (container != null)
            {
                container.IsExpanded = true;
            }

            foreach (var child in node.Children)
            {
                ExpandNode(child);
            }
        }

        public void CollapseNode(TreeNode node)
        {
            var container = treeView.ItemContainerGenerator.ContainerFromItem(node) as TreeViewItem;
            if (container != null)
            {
                container.IsExpanded = false;
            }

            foreach (var child in node.Children)
            {
                CollapseNode(child);
            }
        }
        #endregion
        #endregion

        #region 私有方法
        private void AddNode(TreeNode node, TreeNode parent)
        {
            if (parent == null)
            {
                node.Parent = null;
                Nodes.Add(node);
            }
            else
            {
                node.Parent = parent;
                parent.Children.Add(node);
            }
        }
        private IEnumerable<TreeNode> GetAllNodes(IEnumerable<TreeNode>? nodes=null)
        {
            if (nodes == null) nodes = null;
            foreach (var node in nodes)
            {
                yield return node;
                foreach (var child in GetAllNodes(node.Children))
                {
                    yield return child;
                }
            }
        }
        #endregion
    }

    #region 数据模型
    public abstract class TreeNode : INotifyPropertyChanged
    {
        private string _text;
        private ObservableCollection<TreeNode> _children;
        private TreeNode _parent;

        #region 初始化结构
        public event PropertyChangedEventHandler? PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public TreeNode()
        {
            _children = new ObservableCollection<TreeNode>();
        }
        #endregion
        public string Text
        {
            get => _text;
            set
            {
                if (_text != value)
                {
                    _text = value;
                    OnPropertyChanged(nameof(Text));
                }
            }
        }
        public ObservableCollection<TreeNode> Children
        {
            get => _children;
            set
            {
                if (_children != value)
                {
                    _children = value;
                    OnPropertyChanged(nameof(Children));
                }
            }
        }

        public TreeNode Parent
        {
            get => _parent;
            set
            {
                if (_parent != value)
                {
                    // 防止设置自己为自己的父节点
                    if (value == this)
                        throw new InvalidOperationException("不能将节点设置为自己的父节点");

                    // 防止循环引用（检查祖先链）
                    var current = value;
                    while (current != null)
                    {
                        if (current == this)
                            throw new InvalidOperationException("检测到循环引用");
                        current = current.Parent;
                    }

                    _parent = value;
                    OnPropertyChanged(nameof(Parent));
                }
            }
        }
    }
    public class LabelTreeNode : TreeNode
    {
        private Label _obj;

        public Label obj
        {
            get => _obj;
            set
            {
                if (_obj != value)
                {
                    _obj = value;
                    OnPropertyChanged(nameof(obj));
                }
            }
        }
    }
    public class ComboboxTreeNode : TreeNode
    {
        private ComboBox _obj;

        public ComboBox obj
        {
            get => _obj;
            set
            {
                if (_obj != value)
                {
                    _obj = value;
                    OnPropertyChanged(nameof(obj));
                }
            }
        }
    }
    public class CheckboxTreeNode : TreeNode
    {
        private CheckBox _obj;

        public CheckBox obj
        {
            get => _obj;
            set
            {
                if (_obj != value)
                {
                    _obj = value;
                    OnPropertyChanged(nameof(obj));
                }
            }
        }
    }
    #endregion
}