using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using UnityEngine;

namespace Data
{


    public struct PackAbout
    {
        public string name;
        public string description;
        public string author;
        public string version;
        public string packID;

        public string[] necessary;
        public string[] after;
        public string[] before;

        /// <summary>
        /// 使用静态方法从 XML 文档创建 PackAbout 实例。
        /// </summary>
        /// <param name="doc">XML 文档。</param>
        /// <returns>初始化的 PackAbout 实例。</returns>
        public static PackAbout FromXDocument(XDocument doc)
        {
            var aboutElement = doc.Element("About");
            if (aboutElement == null)
            {
                throw new ArgumentException("XML 文档无效，根节点为空或不是 'About'。");
            }
            PackAbout result = new();

            result.name = aboutElement.Element("name")?.Value ?? "Unknown";
            result.description = aboutElement.Element("description")?.Value ?? "Unknown";
            result.author = aboutElement.Element("author")?.Value ?? "Unknown"; 
            result.version = aboutElement.Element("version")?.Value ?? "Unknown";
            result.packID = aboutElement.Element("packID")?.Value ?? "Unknown";
            
            XElement sortElement = aboutElement.Element("sort");
            if (sortElement != null)
            {
                result.before = GetElementValues(sortElement.Element("before"));
                result.after = GetElementValues(sortElement.Element("after"));
                result.necessary = GetElementValues(sortElement.Element("necessary"));
            }
            else
            {
                result.before = System.Array.Empty<string>();
                result.after = System.Array.Empty<string>();
                result.necessary = System.Array.Empty<string>();
            }

            return result;
        }

        /// <summary>
        /// 获取指定 XElement 下所有子元素的值并返回为字符串数组。
        /// </summary>
        /// <param name="element">父 XElement。</param>
        /// <returns>字符串数组。</returns>
        private static string[] GetElementValues(XElement element)
        {
            if (element == null || !element.HasElements)
            {
                return System.Array.Empty<string>();
            }

            return element.Elements()
                          .Select(e => e.Value.Trim())
                          .ToArray();
        }
    }

    public class DefinePack
    {
        public string packID;
        public PackAbout packAbout;
        /// <summary>
        /// define类别及其定义
        /// </summary>
        public Dictionary<string,List<Define>> defines;

        private const string CoreNamespace = "Data.";
        
        
        public bool LoadPack(string packPath)
        {
            var packDatas=Utils.FileHandler.LoadXmlFromPath(packPath);
            var aboutXmls=FindDocumentsWithRootName(packDatas,"About");
            if (aboutXmls == null || aboutXmls.Count < 1)
            {
                Debug.LogError("包缺少配置文件，加载跳过");
                return false;
            }
            var aboutXml=aboutXmls[0];
            packAbout=PackAbout.FromXDocument(aboutXml);
            packID=packAbout.packID;
            if (aboutXmls.Count > 1)
            {
                Debug.LogWarning($"{packAbout.name}包拥有多个配置文件，系统选择了加载序的第一个，请避免这种情况");
            }
            
            var defineXmls=FindDocumentsWithRootName(aboutXmls, "Define");
            foreach (var defineXml in defineXmls)
            {
                LoadDefines(defineXml);
            }
            
            return true;
        }

        private void LoadDefines(XDocument defineDoc)
        {
            var rootElement = defineDoc.Root;
            if(rootElement==null||rootElement.Name != "Define")
                return;
            
            foreach (var element in rootElement.Elements())
            {
                var className = element.Name.ToString();
                if (string.IsNullOrEmpty(className))
                    continue;
                var def = LoadDefineClass(element);
                if (def == null)
                    continue;
                if (!defines.ContainsKey(className))
                    defines.Add(className,new List<Define>());
                defines[className].Add(def);
            }
        }

        private Define LoadDefineClass(XElement defineDoc)
        { 
            var className = defineDoc.Name.ToString();
            var assembly = Assembly.GetExecutingAssembly();

            Type type;
            if (!className.Contains('.'))
            {
                // 尝试拼接默认命名空间   
                var fullClassName = CoreNamespace + className;
                type = assembly.GetType(fullClassName);

                // 如果拼接命名空间后仍找不到，尝试直接查找（可能是全局命名空间下的类）
                if (type == null)
                {
                    type = assembly.GetType(className);
                }
            }
            else
            {
                // 直接查找
                type = assembly.GetType(className);
            }

            if (type == null)
            {
                Debug.LogError($"未定义的类型: {className}");
                return null;
            }

            var constructor = type.GetConstructor(Type.EmptyTypes);
            if (constructor == null)
            {
                Debug.LogError($"{className} 必须包含无参构造函数");
                return null;
            }

            // 3. 创建实例
            object instance;
            try
            {
                instance = Activator.CreateInstance(type);
            }
            catch (Exception ex)
            {
                Debug.LogError($"创建 {className} 实例失败: {ex.Message}");
                return null;
            }

            // 4. 检查是否继承自 Define
            if (instance is not Define define)
            {
                Debug.LogError($"{className} 必须继承自 Define");
                return null;
            }

            if (define.Init(defineDoc))
            {
                return define;
            }
            // 获取类的所有字段（不包括私有字段）
            var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);

            // 遍历字段并尝试从 XElement 中赋值
            foreach (var field in fields)
            {
                // 查找对应的 XElement 子元素
                var element = defineDoc.Element(field.Name);
                if (element != null)
                {
                    try
                    {
                        // 将子元素的值转换为目标类型并赋值
                        object value = Convert.ChangeType(element.Value, field.FieldType);
                        field.SetValue(define, value);
                    }
                    catch (Exception ex)
                    {
                        Debug.LogWarning($"Error setting field {field.Name}: {ex.Message}");
                    }
                }
            }
            return define;
        }
        
        /// <summary>
        /// 从 List<c>XDocument</c> 中查找指定根元素名称的文档。
        /// </summary>
        /// <param name="xmlDocuments">XML 文档列表。</param>
        /// <param name="rootName">目标根元素名称。</param>
        /// <returns>符合条件的 XML 文档列表。</returns>
        public static List<XDocument> FindDocumentsWithRootName(List<XDocument> xmlDocuments, string rootName)
        {
            // Using LINQ to Objects for a more concise solution
            var result = xmlDocuments
                .Where(doc => doc.Root != null && doc.Root.Name.LocalName == rootName)
                .ToList();

            return result;
        }
    }
}