using System;
using System.Collections;
using System.Collections.Generic;
using Newtonsoft.Json;
using SGModule.Common.Base;
using SGModule.Common.Extensions;
using SGModule.Common.Helper;
using UnityEngine;

namespace SGModule.DataStorage {
    /// <summary>
    ///     数据管理类，基于 Easy Save 实现，提供 JSON 导出功能。
    /// </summary>
    public class DataManager : SingletonMonoBehaviour<DataManager> {
        private const float InitialAutoSaveInterval = 15f; // 初始自动保存间隔
        private const int SaveThreshold = 20; // 自动保存调用计数阈值

        private static readonly DataStorage<long> _dataVersion = new("DataVersion", 1L);

        private readonly Dictionary<string, object> _cache = new(); // 数据缓存

        private readonly HashSet<string> _modifiedKeys = new(); // 记录最近修改的键

        private Dictionary<string, object> _cloudData = new(); //云存储数据
        private bool _hasUnsavedChanges; // 是否有未保存的修改

        private Action<string, long, bool> _saveCallback;
        private int _saveCallCount; // 保存调用计数
        private float _timer; // 自动保存计时器

        private void Start() {
            // ClearAllData();
            StartCoroutine(AutoSaveRoutine());
        }


        /// <summary>
        ///     Unity 应用暂停或失去焦点时触发保存。
        /// </summary>
        private void OnApplicationFocus(bool hasFocus) {
            if (!hasFocus) {
                SaveChange(true);
            }
        }

        /// <summary>
        ///     Unity 游戏退出时
        /// </summary>
        private void OnApplicationQuit() {
            SaveChange(true);
        }

        private IEnumerator AutoSaveRoutine() {
            var lastTime = Time.time;

            var wait = new WaitForSeconds(3f); // 每3秒检查一次
            while (true) {
                yield return wait;

                var currentTime = Time.time;
                _timer += currentTime - lastTime;
                lastTime = currentTime;
                if (_timer >= InitialAutoSaveInterval || _saveCallCount >= SaveThreshold) {
                    _timer = 0f;
                    _saveCallCount = 0;
                    SaveChange(false);
                }
            }
        }


        public void Init() {
            GMTool.Instance.AddItem(new GMToolItem(GUIType.Separator, () => "数据模块"));
            GMTool.Instance.AddItem(new GMToolItem(GUIType.Button, () => "清空数据", s => {
                ClearAllData();
            }));
        }

        /// <summary>
        ///     如果有未保存的修改，则执行保存。
        /// </summary>
        private void SaveChange(bool onQuit) {
            Log.DataStorage.Info($"SaveChange trigger. hasUnsavedChanges:{_hasUnsavedChanges}, onQuit:{onQuit}");
            if (!_hasUnsavedChanges) {
                return;
            }

            _dataVersion.Value++;
            _hasUnsavedChanges = false; // 重置修改标记

            FlushAutoSave();

            // 控制保存回调频率
            if (onQuit || _dataVersion.Value % 2 == 0) {
                Log.DataStorage.Info("SaveChange Callback trigger.");
                _saveCallback?.Invoke(ExportToJson(), _dataVersion.Value, onQuit);
            }
        }

        /// <summary>
        ///     同步缓存中的所有修改到磁盘。
        /// </summary>
        private void FlushAutoSave() {
            foreach (var key in _modifiedKeys) {
                if (_cache.TryGetValue(key, out var value)) {
                    ES3.Save(key, value);
                }
            }

            _modifiedKeys.Clear(); // 清空自动保存的修改记录
        }


        /// <summary>
        ///     保存数据到指定键，并更新缓存。
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="key">存储键</param>
        /// <param name="data">要保存的数据</param>
        public void SaveData<T>(string key, T data) {
            // 直接更新缓存
            _cache[key] = data;

            // 记录修改的键（避免重复添加）
            if (_modifiedKeys.Add(key)) {
                _hasUnsavedChanges = true;
            }

            _saveCallCount++; // 记录保存调用次数
        }

        /// <summary>
        ///     加载指定键的数据，优先从缓存中获取。
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="key">存储键</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>加载的数据</returns>
        public T LoadData<T>(string key, T defaultValue = default) {
            // 1. 缓存读取
            if (_cache.TryGetValue(key, out var cached)) {
                return cached is T t ? t : cached.As<T>() ?? defaultValue;
            }


            // 2. 云端数据读取
            if (_cloudData != null && _cloudData.TryGetValue(key, out var value)) {
                var val = value.As<T>();
                if (val != null) {
                    _cache[key] = val;
                    return val;
                }

                Log.DataStorage.Error($"云端数据类型不匹配: key={key}, value={value}, 目标类型={typeof(T)}, 实际类型={value?.GetType()}");
            }


            // 3. 从本地 ES3 读取
            if (ES3.KeyExists(key)) {
                try {
                    var result = ES3.Load<object>(key).As<T>();
                    if (result != null) {
                        _cache[key] = result;
                        return result;
                    }
                }
                catch (Exception e) {
                    Log.DataStorage.Error($"{key} 加载失败: {e.Message}");
                }
            }

            _cache[key] = defaultValue;
            return defaultValue;
        }


        /// <summary>
        ///     检查指定键是否存在（优先检查缓存）。
        /// </summary>
        /// <param name="key">存储键</param>
        /// <returns>是否存在</returns>
        public bool KeyExists(string key) {
            return _cache.ContainsKey(key) || ES3.KeyExists(key);
        }

        /// <summary>
        ///     删除指定键的数据，并更新缓存。
        /// </summary>
        /// <param name="key">存储键</param>
        public void DeleteKey(string key) {
            _cache.Remove(key);
            _modifiedKeys.Remove(key); // 删除自动保存记录

            if (ES3.KeyExists(key)) {
                ES3.DeleteKey(key);
            }
        }

        /// <summary>
        ///     清空存储文件。
        /// </summary>
        public void ClearAllData() {
            if (!ES3.FileExists()) {
                return;
            }

            ES3.DeleteFile();
            _cache.Clear();
            _modifiedKeys.Clear(); // 清空自动保存记录
        }


        /// <summary>
        ///     将存储文件中的所有键值对导出为 JSON 字符串
        /// </summary>
        private static string ExportToJson() {
            if (!ES3.FileExists()) {
                Log.DataStorage.Warning("ES3 Save file does not exist.");
                return null;
            }

            var allKeys = ES3.GetKeys();
            var dataDict = new Dictionary<string, object>();

            foreach (var key in allKeys) {
                // 添加空值检查
                if (key == null) {
                    Log.DataStorage.Warning("Found null key in ES3 storage, skipping...");
                    continue;
                }
        
                // 验证键的格式
                if (string.IsNullOrEmpty(key.Trim())) {
                    Log.DataStorage.Warning($"Found empty or whitespace key in ES3 storage, skipping...");
                    continue;
                }
        
                if (DataKeyDic.Get(key)?.CloudSave != true) {
                    continue;
                }

                try {
                    var value = ES3.Load(key);
                    if (value != null) {
                        dataDict[key] = value;
                    } else {
                        Log.DataStorage.Warning($"Loaded null value for key: {key}, skipping...");
                    }
                }
                catch (Exception e) {
                    Log.DataStorage.Error($"Failed to load key {key}: {e.Message}");
                    // 不重新抛出异常，继续处理其他键
                    continue;
                }
            }

            // 使用 Newtonsoft.Json 序列化为 JSON 字符串
            return JsonConvert.SerializeObject(dataDict);
        }



        /// <summary>
        ///     从 JSON 字符串导入数据
        /// </summary>
        public void ImportFromJson(string json, long version) {
            Log.DataStorage.Info($"云端数据版本: {version},本地数据版本: {_dataVersion.Value} ,数据: {json}");
            _cloudData.Clear();
            
            if (string.IsNullOrEmpty(json) || version < 0) {
                Log.DataStorage.Warning("Invalid json or version for import");
                return;
            }
            
            if (version >= _dataVersion.Value) {
                _cloudData = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);

                // 验证并过滤空键
                if (_cloudData != null) {
                    var validCloudData = new Dictionary<string, object>();
                    foreach (var kv in _cloudData) {
                        if (kv.Key != null) {
                            validCloudData[kv.Key] = kv.Value;
                        } else {
                            Log.DataStorage.Warning("Found null key in imported JSON, skipping...");
                        }
                    }
                    _cloudData = validCloudData;
                }
                
                // 本地数据比云端的版低, 将云端数据保存到本地
                if (version > _dataVersion.Value) {
                    RestoreCloudDataToES3();
                    _dataVersion.Value = version;
                }

                return;
            }

            // 本地数据比云端的版本高, 触发保存回调上传本地数据到云端
            _saveCallback?.Invoke(ExportToJson(), _dataVersion.Value, false);
        }

        private void RestoreCloudDataToES3() {
            if (_cloudData == null) {
                Log.DataStorage.Warning("Cloud data is null, skipping restore");
                return;
            }
            
            foreach (var kv in _cloudData) {
                // 确保键不为空
                if (kv.Key == null) {
                    Log.DataStorage.Warning("Found null key in cloud data, skipping...");
                    continue;
                }
                
                var type = DataKeyDic.Get(kv.Key)?.Type;
                if (type == null) {
                    Log.DataStorage.Warning($"云端数据 key={kv.Key} 未注册类型，跳过保存");
                    continue;
                }
                
                try {
                    ES3.Save(kv.Key, kv.Value.As(targetType: type));
                }
                catch (Exception e) {
                    Log.DataStorage.Error($"Failed to save cloud data key {kv.Key}: {e.Message}");
                }
            }
        }


        /// <summary>
        ///     添加保存时回调
        /// </summary>
        /// <param name="saveCallback"></param>
        public void AddSaveCallback(Action<string, long, bool> saveCallback) {
            _saveCallback += saveCallback;
        }

        /// <summary>
        ///     清空保存时回调
        /// </summary>
        public void ClearSaveCallback() {
            _saveCallback = null;
        }

        /// <summary>
        ///     移除保存回调
        /// </summary>
        /// <param name="saveCallback"></param>
        public void RemoveSaveCallback(Action<string, long, bool> saveCallback) {
            _saveCallback -= saveCallback;
        }


        /// <summary>
        ///     打印存储文件的所有键值（调试用）。
        /// </summary>
        public void DebugAllKeys() {
            Log.DataStorage.Info("DebugAllKeys Start");
            foreach (var key in ES3.GetKeys()) {
                Log.DataStorage.Info($"Key: {key}, Value: {ES3.Load<object>(key)}");
            }

            Log.DataStorage.Info("DebugAllKeys End");
        }

        /// <summary>
        ///     调试用：打印缓存中的所有数据。
        /// </summary>
        public void DebugCache() {
            Log.DataStorage.Info("DebugCache Start");
            foreach (var kvp in _cache) {
                Log.DataStorage.Info($"Cache Key: {kvp.Key}, Value: {kvp.Value}");
            }

            Log.DataStorage.Info("DebugCache End");
        }
    }
}
