using System;
using System.IO;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json.Linq;
using Roy;

namespace ScrewsMaster
{
    public class ConfigSystem : BaseSystem
    {

        public const string ConfigFileNameKey = "configFileName";

        public static List<GameUrls> light_weblist = new List<GameUrls>();
        public static List<GameUrls> dark_weblist = new List<GameUrls>();
        public static string web_through_str;
        private static readonly Dictionary<Type, object> ConfigData = new Dictionary<Type, object>();
        private LoginModel _loginModel;

        private int _initConfigErrorCount;

        public ConfigSystem(bool isAutoInit = true)
        {
            if (isAutoInit)
            {
                Init();
            }
        }

        public sealed override void Init()
        {
            base.Init();
            AddListener();
        }

        private void AddListener()
        {
            NetworkDispatcher.Instance.AddListener(NetworkMsg.GetConfig, OnGetConfig);
        }

        private void RemoveListener()
        {
            NetworkDispatcher.Instance.RemoveListener(NetworkMsg.GetConfig, OnGetConfig);
        }

        private void OnGetConfig(object obj)
        {
            _initConfigErrorCount = 0;
            var reqData = new RespLoginFunnelData
            {
                type = "loadBegin",
                payload = ""
            };
            NetworkKit.PostFunnelLogin(reqData);//加载开始打点

            OnRequestGetConfig();
        }

        private void OnRequestGetConfig()
        {
            _loginModel = GameHelper.GetLoginModel();

            if (_initConfigErrorCount > 6)
            {
                GameHelper.ShowTips("Configuration file failed to load, please try again later");
                return;
            }

            // if (IsFirstLaunch())
            // {
            //     FirstLaunchCopyConfig();// 进行首次启动的操作
            //     return;
            // }

            bool needDownloadConfigFile = HasNewConfig();
            //需要下载配置的话等待下载更新
            if (needDownloadConfigFile)
            {
                DownloadConfig();
                return;
            }

            ReadLocalConfig();
        }

        /// <summary>
        /// 判断是首次打开游戏
        /// </summary>
        /// <returns></returns>
        public bool IsFirstLaunch()
        {
            return !PlayerPrefs.HasKey("FirstLaunch");
        }

        /// <summary>
        /// 设置首次启动游戏
        /// </summary>
        private void SetFirstLaunch()
        {
            PlayerPrefs.SetInt("FirstLaunch", 1);
        }

        /// <summary>
        /// 首次启动游戏拷贝配置文件到PersistentData目录下
        /// </summary>
        private void FirstLaunchCopyConfig()
        {
            SetFirstLaunch();
            FileNetworkManager.GetInstance.CopyStreamingAssetsToPersistentDataPath((result) =>
            {
                var isSuccess = false;
                if (result)
                {
                    var names = FileNetworkManager.GetInstance.GetFileNamesFromPersistentDataPath(FileNetworkManager.FolderName);
                    if (names.Length > 0)
                    {
                        PlayerPrefs.SetString(ConfigFileNameKey, names[0]);//项目当前文件中的配置版本
                        isSuccess = true;
                    }
                }
                else
                {
                    Debug.LogError("拷贝文件失败");
                }

                if (isSuccess)
                {
                    OnRequestGetConfig();
                }
                else
                {
                    _initConfigErrorCount++;
                }
            });
        }

        /// <summary>
        /// 下载配置文件
        /// </summary>
        private void DownloadConfig()
        {
            var cdnConfigFileName = _loginModel.setting;
            FileNetworkManager.GetInstance.ReadData($"{NetworkKit.CDNUrl}config/{cdnConfigFileName}", (result) =>
            {
                if (!string.IsNullOrEmpty(result))
                {
                    PlayerPrefs.SetString(ConfigFileNameKey, cdnConfigFileName);//更新当前配置文件文件名
                    FileNetworkManager.GetInstance.WriteToPersistentData(FileNetworkManager.GetInstance.GetConfigFOlderPath(), cdnConfigFileName, result);
                    ReloadConfig(result);
                    SaveingPotHelper.ResetHistory();
                }
                else
                {
                    _initConfigErrorCount++;
                    Debug.LogError("下载配置文件失败");
                    ReadLocalConfig();
                }

            });
        }

        /// <summary>
        /// 读取本地配置文件
        /// </summary>
        private void ReadLocalConfig()
        {
            string savedCfgName = PlayerPrefs.GetString(ConfigFileNameKey);
            var path = Path.Combine(FileNetworkManager.GetInstance.GetConfigFOlderPath(), savedCfgName);
            FileNetworkManager.GetInstance.ReadData(path, (result) =>
            {
                if (!string.IsNullOrEmpty(result))
                {
                    ReloadConfig(result);
                }
                else
                {
                    _initConfigErrorCount++;
                    Debug.LogError("读取本地数据异常");
                    // DownloadConfig();

                    //读取本地配置文件失败，重新从默认位置拷贝原始配置文件到配置文件夹下
                    FirstLaunchCopyConfig();
                }
            });
        }

        /// <summary>
        /// 重新加载配置
        /// </summary>
        /// <param name="json"></param>
        private void ReloadConfig(string json)
        {
            var reqData = new RespLoginFunnelData
            {
                type = "loadFinish",
                payload = ""
            };
            NetworkKit.PostFunnelLogin(reqData);//加载完成打点

            ParseConfig(json);
            UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.NetLoadingUI_Close);
            AppDispatcher.Instance.Dispatch(AppMsg.LoginInit);

            CtrlDispatcher.Instance.Dispatch(CtrlMsg.Game_StartBefore);
        }

        /// <summary>
        /// 检查是否有新的配置
        /// </summary>
        /// <returns></returns>
        private bool HasNewConfig()
        {
            var cdnConfigFileName = _loginModel.setting;

            if (!PlayerPrefs.HasKey(ConfigFileNameKey)) return true;

            string savedCfgName = PlayerPrefs.GetString(ConfigFileNameKey);
            bool needDownloadConfigFile = false;

            if (!string.IsNullOrEmpty(cdnConfigFileName))
            {
                //如果本地Player Prefs里没有保存配置文件名
                if (string.IsNullOrEmpty(savedCfgName))
                {
                    needDownloadConfigFile = true;
                }
                else
                {
                    //与CDN上的对比名称
                    if (!savedCfgName.Equals(cdnConfigFileName))
                    {
                        needDownloadConfigFile = true;
                    }
                }
            }

            return needDownloadConfigFile;
        }

        private void ParseConfig(string json)
        {
            if (json == null)
            {
                return;
            }
            if (!json.StartsWith("{"))
            {
                json = Base64Kit.Decode(json, NetworkManager.packName);
            }
            var dictionary = SerializeUtil.ToObject<Dictionary<string, object>>(json);
            ParseGameConfig(dictionary);
            // ParseQuestionConfig(dictionary);

            // GameDispatcher.Instance.Dispatch(GameMsg.UpdateHotFixProgress, 100);
        }

        #region 游戏配置

        private void ParseGameConfig(IReadOnlyDictionary<string, object> dictionary)
        {
            LoadConfig<CommonModel>(dictionary, "Common");
            LoadConfigList<TurntableModel, Turntable>(dictionary, "turntable");
            LoadConfigList<LangDisplayModel, LangDisplay>(dictionary, "langDisplay");
            LoadConfigList<RewardNumModel, RewardNum>(dictionary, "rewardNum");
            LoadConfigList<AchieveModel, Achieve>(dictionary, "achieve");
            LoadConfigList<DurationtasksModel, Durationtasks>(dictionary, "Durationtasks");
            LoadConfigList<PaidcoinsModel, Paidcoins>(dictionary, "Paidcoins");
            LoadConfigList<PassingTaskModel, PassingTask>(dictionary, "PassingTasks");
            LoadConfigList<PassportrewardsModel, Passportrewards>(dictionary, "Passportrewards");
            LoadConfigList<SmallrewardNumModel, SmallrewardNum>(dictionary, "SmallrewardNum");
            LoadConfigList<LargerewardNumModel, LargerewardNum>(dictionary, "LargerewardNum");
            LoadConfigList<PaymentTypeModel, PaymentType>(dictionary, "paymentType");
            LoadConfigList<MakeupModel, Makeup>(dictionary, "makeup");
            LoadConfigList<MakeupModel_2, Makeup_2>(dictionary, "makeup_2");
            LoadConfigList<PaidgiftModel, Paidgift>(dictionary, "Paidgift");
            // LoadConfig<GameUrlsConstModel>(dictionary, "GameUrlsConst");
            // LoadConfigList<GameUrlsModel, GameUrls>(dictionary, "GameUrls");
            LoadConfigList<LevelDataModel, LevelData>(dictionary, "LevelData");
            LoadConfigList<LevelDataModel_2, LevelData>(dictionary, "LevelData_2");
            LoadConfigList<LevelDataModel_3, LevelData>(dictionary, "LevelData_3");
            LoadConfigList<PrizeWheelDataModel, PrizeWheelData>(dictionary, "PrizeWheelData");
            LoadConfigList<exBrPoolModel, exBrPool>(dictionary, "exBrPool");
            LoadConfigList<exBrPoolModel_2, exBrPool_2>(dictionary, "exBrPool");
            LoadConfigList<MultigiftModel, Multigift>(dictionary, "Multigift");

            if (dictionary.TryGetValue("SignDailyReward", out var signDailyReward))
            {
                var signDailyRewardModel = new SignDailyRewardModel();

                signDailyRewardModel.dataList = SerializeUtil.ToObject<List<SignDailyReward>>(signDailyReward.ToString());

                ConfigData[typeof(SignDailyRewardModel)] = signDailyRewardModel;
            }

            if (GetConfigFormName(dictionary, "exBrPool", out var exBrPool))
            {
                var exBrPoolModel = new exBrPoolModel
                { dataList = SerializeUtil.ToObject<List<exBrPool>>(exBrPool) };
                ConfigData[typeof(exBrPoolModel)] = exBrPoolModel;
                GetConfig<exBrPoolModel>().config_name_list = GetConfig<exBrPoolModel>().dataList[0].user_name.Split(",").ToList();
                GetConfig<exBrPoolModel>().config_money_list = GetConfig<exBrPoolModel>().dataList[0].amount.Split(",").ToList();
            }
            if (GetConfigFormName(dictionary, "exBrPool_2", out var exBrPool_2))
            {
                var exBrPoolModel_2 = new exBrPoolModel_2
                { dataList = SerializeUtil.ToObject<List<exBrPool_2>>(exBrPool_2) };
                ConfigData[typeof(exBrPoolModel_2)] = exBrPoolModel_2;
                GetConfig<exBrPoolModel_2>().config_name_list = GetConfig<exBrPoolModel_2>().dataList[0].user_name.Split(",").ToList();
                GetConfig<exBrPoolModel_2>().config_money_list = GetConfig<exBrPoolModel_2>().dataList[0].amount.Split(",").ToList();
            }
            if (dictionary.TryGetValue("GameUrls", out var GameUrls))
            {
                light_weblist.Clear();
                dark_weblist.Clear();
                web_through_str = "";
                List<GameUrls> alllist = new List<GameUrls>();
                alllist = SerializeUtil.ToObject<List<GameUrls>>(GameUrls.ToString());
                List<int> type_list = new List<int>();
                for (int i = 0; i < alllist.Count; i++)
                {

                    if (alllist[i].webType == 2)
                    {
                        if (GameHelper.IsGiftSwitch() && (alllist[i].isMagic == 1)) light_weblist.Add(alllist[i]);
                        else if (!GameHelper.IsGiftSwitch() && (alllist[i].isMagic == 0)) light_weblist.Add(alllist[i]);
                    }
                    else
                    {
                        dark_weblist.Add(alllist[i]);
                        if (!type_list.Contains(alllist[i].wvType))
                        {
                            web_through_str += alllist[i].wvthrough;
                            web_through_str += "|";
                            type_list.Add(alllist[i].wvType);
                        }
                    }

                }
                web_through_str.Remove(web_through_str.Length - 1);
                var gameUrlsModel = new GameUrlsModel
                {
                    dataList = light_weblist
                };
                ConfigData[typeof(GameUrlsModel)] = gameUrlsModel;
            }
        }

        private void LoadConfig<T>(IReadOnlyDictionary<string, object> dictionary, string key)
        {
            if (ParseConfig(dictionary, key, out T data))
            {
                ConfigData[typeof(T)] = data;
            }
        }

        private void LoadConfigList<T, TD>(IReadOnlyDictionary<string, object> dictionary, string key)
            where T : IDataList<TD>, new()
        {
            if (ParseConfig(dictionary, key, out List<TD> dataList))
            {
                ConfigData[typeof(T)] = new T { dataList = dataList };
            }
        }

        private bool ParseConfig<T>(IReadOnlyDictionary<string, object> dictionary, string key, out T obj)
        {
            obj = default;
            if (!GetConfigFormName(dictionary, key, out var config))
            {
                Debug.LogWarning($"Excel Not find Sheet: {key}");
                return false;
            }

            try
            {
                var tempObj = SerializeUtil.ToObject<T>(config);
                if (tempObj != null)
                {
#if UNITY_EDITOR
                    CheckMissFields(key, tempObj, config);
#endif
                    obj = tempObj;
                    return true;
                }
            }
            catch (Exception ex)
            {
                // 在此处添加异常处理逻辑，例如日志记录
                Debug.LogError("Error deserializing config data for type " + typeof(T).Name + ": " + ex.Message);
            }

            return false;
        }

        private void CheckMissFields<T>(string key, T tempObj, string configValue)
        {
            var missingFields = new List<string>();

            if (tempObj is IEnumerable<object> tempArray)
            {
                missingFields = CheckMissingFieldsInArray(tempArray.FirstOrDefault()?.GetType(), configValue);
            }
            else
            {
                missingFields = CheckMissingFields(tempObj.GetType(), configValue);
            }

            if (missingFields.Count > 0)
            {
                Debug.LogWarning($"Excel Sheet: {key} Missing fields in JSON: " + string.Join(", ", missingFields.Distinct()));
            }
        }

        public static List<string> CheckMissingFieldsInArray(Type objType, string jsonString)
        {
            var missingFields = new List<string>();
            var jsonArray = JArray.Parse(jsonString);

            foreach (var item in jsonArray)
            {
                missingFields.AddRange(CheckMissingFields(objType, item.ToString()));
            }

            return missingFields;
        }

        public static List<string> CheckMissingFields(Type objType, string jsonString)
        {
            var missingFields = new List<string>();

            try
            {
                var jsonObject = SerializeUtil.ToObject<Dictionary<string, object>>(jsonString);
                var fields = objType.GetFields(BindingFlags.Public | BindingFlags.Instance);

                foreach (var field in fields)
                {
                    if (!jsonObject.ContainsKey(field.Name))
                    {
                        missingFields.Add(field.Name);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.Log("Error checking missing fields for type " + objType.Name + ": " + ex.Message);
            }

            return missingFields;
        }

        private bool GetConfigFormName(IReadOnlyDictionary<string, object> dictionary, string formName, out string config)
        {
            config = null;
            var lastName = formName + _loginModel.ConfigType;
            var isHaveConfig = dictionary.ContainsKey(lastName);
            if (!isHaveConfig)
            {
                if (_loginModel.ConfigType == "")
                {
                    return false;
                }
                lastName = formName;
            }

            Debug.Log($"lastName============= {lastName}");
            var isHaveGameUrlsConst = dictionary.TryGetValue(lastName, out var gameUrlsConst);
            config = isHaveGameUrlsConst ? gameUrlsConst.ToString() : null;
            return isHaveGameUrlsConst;
        }
        #endregion

        public static T GetConfig<T>()
        {
            return ConfigData.TryGetValue(typeof(T), out var value) ? (T)value : default;
        }

        public override void Dispose()
        {
            base.Dispose();
            RemoveListener();
        }
    }
}