using System;
using System.IO;
using SGModule.Common.Helper;
using UnityEngine;

namespace SGModule.ConfigLoader {
    public class ConfigFileManager {
        private const int MaxErrorCount = 6;
        private const string ConfigFileNameKey = "ConfigFileName";
        private const string FirstLaunchKey = "FirstLaunch";

        private int _initConfigErrorCount;

        private bool HasExceededMaxErrors => _initConfigErrorCount > MaxErrorCount;
        private static bool IsFirstLaunch => !PlayerPrefs.HasKey(FirstLaunchKey);
        private static string SavedConfigFileName => PlayerPrefs.GetString(ConfigFileNameKey);

        private static void SetFirstLaunch() {
            PlayerPrefs.SetInt(FirstLaunchKey, 1);
        }

        private static void SetSavedConfigFileName(string name) {
            PlayerPrefs.SetString(ConfigFileNameKey, name);
        }

        private void IncrementErrorCount() {
            _initConfigErrorCount++;
        }

        // 检查是否需要下载新配置，基于传入的期望配置文件名setting
        private static bool HasNewConfig(string expectedSetting) {
            if (string.IsNullOrEmpty(SavedConfigFileName)) {
                return true;
            }

            return !SavedConfigFileName.Equals(expectedSetting);
        }

        private void FirstLaunchCopyConfig(Action<bool> callback) {
            SetFirstLaunch();

            FileNetworkManager.Instance.CopyStreamingAssetsToPersistentDataPath(result => {
                var isSuccess = false;
                if (result) {
                    var names = FileNetworkManager.Instance.GetFileNamesFromPersistentDataPath(FileNetworkManager.FolderName);
                    if (names.Length > 0) {
                        SetSavedConfigFileName(names[0]);
                        isSuccess = true;
                    }
                }
                else {
                    Log.ConfigLoader.Error("拷贝文件失败 请检查Configs文件夹是否有配置文件");
                }

                if (!isSuccess) {
                    IncrementErrorCount();
                }

                callback?.Invoke(isSuccess);
            });
        }

        private void DownloadConfig(string cdnUrl, string setting, Action<bool, string> callback) {
            var url = $"{cdnUrl}/config/{setting}";
            Log.ConfigLoader.Info($"开始下载配置文件 {url}", false);
            FileNetworkManager.Instance.ReadData(url, result => {
                if (!string.IsNullOrEmpty(result)) {
                    SetSavedConfigFileName(setting);
                    FileNetworkManager.Instance.WriteToPersistentData(FileNetworkManager.Instance.GetConfigFOlderPath(), setting, result);
                    callback?.Invoke(true, result);
                }
                else {
                    Log.ConfigLoader.Error("下载配置文件失败");
                    IncrementErrorCount();
                    callback?.Invoke(false, null);
                }
            });
        }

        private void ReadLocalConfig(Action<bool, string> callback) {
            var savedCfgName = SavedConfigFileName;
            Log.ConfigLoader.Info($"开始读取本地配置文件 {savedCfgName}", false);
            if (string.IsNullOrEmpty(savedCfgName)) {
                IncrementErrorCount();
                callback?.Invoke(false, null);
                return;
            }

            var path = Path.Combine(FileNetworkManager.Instance.GetConfigFOlderPath(), savedCfgName);
            FileNetworkManager.Instance.ReadData(path, result => {
                if (!string.IsNullOrEmpty(result)) {
                    callback?.Invoke(true, result);
                }
                else {
                    Log.ConfigLoader.Error("读取本地数据异常");
                    IncrementErrorCount();
                    callback?.Invoke(false, null);
                }
            });
        }

        /// <summary>
        ///     配置文件检查与加载流程
        /// </summary>
        public void CheckAndLoadConfig(ConfigInitOptions initOptions, Action<string> onConfigLoaded, Action<ConfigLoaderState> callback) {
            if (HasExceededMaxErrors) {
                callback?.Invoke(ConfigLoaderState.Failed);
                return;
            }

            if (IsFirstLaunch) {
                FirstLaunchCopyConfig(success => {
                    if (!success) {
                        IncrementErrorCount();
                    }

                    CheckAndLoadConfig(initOptions, onConfigLoaded, callback);
                });
                return;
            }

            if (HasNewConfig(initOptions.Setting)) {
                DownloadConfig(initOptions.CdnUrl, initOptions.Setting, (success, json) => {
                    if (success) {
                        ReloadConfig(json, onConfigLoaded, callback);
                    }
                    else {
                        ReadLocalConfig((readSuccess, localJson) => {
                            if (readSuccess) {
                                ReloadConfig(localJson, onConfigLoaded, callback);
                            }
                            else {
                                callback?.Invoke(ConfigLoaderState.Failed);
                            }
                        });
                    }
                });
                return;
            }

            ReadLocalConfig((success, json) => {
                if (success) {
                    ReloadConfig(json, onConfigLoaded, callback);
                }
                else {
                    FirstLaunchCopyConfig(result => {
                        if (!result) {
                            IncrementErrorCount();
                        }

                        CheckAndLoadConfig(initOptions, onConfigLoaded, callback);
                    });
                }
            });
        }

        private static void ReloadConfig(string json, Action<string> onConfigLoaded, Action<ConfigLoaderState> callback) {
            if (string.IsNullOrWhiteSpace(json)) {
                callback?.Invoke(ConfigLoaderState.JsonEmptyError);
                return;
            }

            onConfigLoaded?.Invoke(json);
            callback?.Invoke(ConfigLoaderState.Successful);
        }
    }
}
