using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SGModule.Common.Helper;

namespace SGModule.ConfigLoader {
    public static class ConfigParser {
        public static void ParseAllConfigs(ParseConfigOptions options) {
            var onParsed = options.OnParsed;
            var errorCallback = options.OnError;
            var onHandleUnmarkedConfig = options.OnHandleUnmarkedConfig;

            var configTypes = Assembly.GetExecutingAssembly().GetTypes()
                .Where(t => t.GetCustomAttribute<ConfigKeyAttribute>() != null);


            foreach (var type in configTypes) {
                var attr = type.GetCustomAttribute<ConfigKeyAttribute>();
                var key = attr.Key;


                if (!ConfigLoader.Instance.TryGetJsonValue(key, out var jsonData)) {
                    errorCallback?.Invoke(key, "未找到对应配置数据");
                    continue;
                }

                try {
                    var json = jsonData.ToString();
                    var targetType = attr.IsList ? typeof(List<>).MakeGenericType(type) : type;
                    var parsedInstance = JsonConvert.DeserializeObject(json, targetType);

                    if (parsedInstance == null) {
                        errorCallback?.Invoke(key, "解析返回空");
                        continue;
                    }

#if !GAME_RELEASE
                    RunFieldCheck(json, type, key, attr.IsList);
#endif

                    // 把结果交还给调用方
                    onParsed?.Invoke(targetType, parsedInstance);
                }
                catch (Exception ex) {
                    errorCallback?.Invoke(key, $"反序列化异常: {ex.Message}");
                    Log.ConfigLoader.Error($"配置 {key} 反序列化异常: {ex}");
                }
            }

            // 处理未标记的配置
            onHandleUnmarkedConfig?.Invoke();

            // 打印未使用的 jsonDict 中的 key
            var unusedKeys = ConfigLoader.Instance.GetUnusedKeys().ToList();
            if (unusedKeys.Count > 0) {
                Log.ConfigLoader.Warning($"未使用的配置表: {string.Join(", ", unusedKeys)};", false);
            }
        }


#if !GAME_RELEASE
        private static void RunFieldCheck(string json, Type type, string key, bool isList) {
            var objectsToCheck = new List<JObject>();

            try {
                if (isList) {
                    var jsonArray = JArray.Parse(json);
                    objectsToCheck.AddRange(jsonArray.OfType<JObject>());
                }
                else {
                    var singleObj = JObject.Parse(json);
                    objectsToCheck.Add(singleObj);
                }
            }
            catch (Exception ex) {
                Log.ConfigLoader.Warning($"[{key}] JSON 解析失败: {ex.Message}");
                return;
            }

            var classFields = type.GetFields(BindingFlags.Public | BindingFlags.Instance)
                .Select(f => f.Name)
                .ToHashSet();

            var allMissingFields = new HashSet<string>();
            var allExtraFields = new HashSet<string>();

            foreach (var obj in objectsToCheck) {
                var jsonKeys = obj.Properties().Select(p => p.Name).ToHashSet();

                allMissingFields.UnionWith(classFields.Except(jsonKeys));
                allExtraFields.UnionWith(jsonKeys.Except(classFields));
            }

            if (allMissingFields.Count > 0 || allExtraFields.Count > 0) {
                var msg = $"[{key}]";
                if (allMissingFields.Count > 0) {
                    msg += $" 缺少字段: {string.Join(", ", allMissingFields.OrderBy(f => f))};";
                }

                if (allExtraFields.Count > 0) {
                    msg += $" 多余字段: {string.Join(", ", allExtraFields.OrderBy(f => f))};";
                }

                var shortJson = json.Length > 1000 ? json.Substring(0, 1000) + "..." : json;
                Log.ConfigLoader.Warning($"[{key}] Json: {shortJson}", false);
                Log.ConfigLoader.Warning(msg, false);
            }
        }
#endif
    }
}
