using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Newtonsoft.Json;
using SGModule.Common.Base;
using SGModule.Common.Extensions;
using SGModule.Common.Helper;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;

namespace SGModule.Net {
    // 网络请求核心类
    public abstract class NetCore<TC> : SingletonMonoBehaviour<TC> where TC : MonoBehaviour {
        private const int Timeout = 15;
        private NetCoreModel _config;
        private bool _isInit;
        private int _requestCounter;
        private string _requestHost;

        private new void Awake() {
            InternalInit();
        }

        protected abstract string Encrypt(string text, string key);
        protected abstract string Decrypt(string text, string key);
        protected abstract TokenManager.RefreshTokenDelegate RefreshTokenHandler();
        protected abstract TokenManager.ReauthenticateDelegate ReauthenticateHandler();

        protected abstract NetCoreModel ProvideConfig();

        private void InternalInit() {
            NetChecker.Instance.Init();
            TokenManager.Instance.InitHandlers(RefreshTokenHandler(), ReauthenticateHandler());

            _config = ProvideConfig();
            if (_config == null) {
                Log.Net.Error("网络配置为空,请检查！！！！");
                return;
            }

            _isInit = true;
            _requestHost = _config.RequestHost;

            Log.Net.Info($"Host is: {_config.RequestHost}");

            if (_config.ConnMode == ConnectionMode.WebSocket) {
                WebSocketService.Instance.Init(GetWsUrl());
            }
        }


        private string GetApiUrl() {
            return $"https://{_requestHost}/api/";
        }

        private string GetWsUrl() {
            return $"wss://{_requestHost}/ws/";
        }

        /// <summary>
        ///     Post请求(异步)
        /// </summary>
        /// <param name="path">请求路径</param>
        /// <param name="requestData">请求参数</param>
        /// <param name="onCompleted">请求回调</param>
        /// <param name="withToken">是否带Token</param>
        /// <param name="headers">额外的请求头</param>
        protected IEnumerator PostAsync<T>(string path, object requestData = null, UnityAction<ResponseData<T>> onCompleted = null, bool withToken = true, Dictionary<string, string> headers = null) {
            var done = false;

            Post<T>(path, requestData, response => {
                onCompleted?.Invoke(response);
                done = true;
            }, withToken, true, headers);

            yield return new WaitUntil(() => done);
        }

        /// <summary>
        ///     Post请求(泛型)
        /// </summary>
        /// <param name="path">请求路径</param>
        /// <param name="requestData">请求参数</param>
        /// <param name="onCompleted">请求回调</param>
        /// <param name="withToken">是否带Token</param>
        /// <param name="useCoroutine">是否使用协程</param>
        /// <param name="headers">额外的请求头</param>
        /// <typeparam name="T">返回数据中Data的类型</typeparam>
        protected void Post<T>(string path, object requestData = null, UnityAction<ResponseData<T>> onCompleted = null, bool withToken = true, bool useCoroutine = true, Dictionary<string, string> headers = null) {
            if (useCoroutine) {
                StartCoroutine(PostInternal(path, requestData, onCompleted, withToken, headers));
            }
            else {
                SendWebRequest(path, requestData, withToken, headers);
            }
        }


        /// <summary>
        ///     发出请求 所有的请求最终都会从这里发出
        /// </summary>
        /// <param name="path">请求路径</param>
        /// <param name="requestData">请求参数</param>
        /// <param name="onCompleted">请求回调</param>
        /// <param name="withToken">是否带Token</param>
        /// <param name="headers">额外的请求头</param>
        /// <typeparam name="T">返回数据中Data的类型</typeparam>
        /// <returns></returns>
        private IEnumerator PostInternal<T>(string path, object requestData, UnityAction<ResponseData<T>> onCompleted, bool withToken = true, Dictionary<string, string> headers = null) {
            var response = new ResponseData<T>();

            if (!_isInit) {
                Log.Net.Error("NetworkKit模块未完成初始化 请检查！！！ ");
                response.Code = -1;
                response.Msg = "NetworkKit module has not been initialized yet";
                onCompleted?.Invoke(response);
                yield break;
            }

            // 1. 网络检查
            var isNetworkOk = false;
            yield return NetChecker.Instance.WaitUntilNetworkConnected(15, 1f, result => isNetworkOk = result);
            if (!isNetworkOk) {
                response.Code = -1;
                response.Msg = "Network status abnormal.";
                onCompleted?.Invoke(response);
                yield break;
            }

            // 2. Token 处理（根据 withToken 参数）
            if (withToken) {
                string token = null;
                yield return TokenManager.Instance.GetToken(result => token = result);

                if (string.IsNullOrEmpty(token)) {
                    response.Code = -1;
                    response.Msg = "Token acquisition failed.";
                    onCompleted?.Invoke(response);
                    yield break;
                }

                // 合并原有 header
                headers ??= new Dictionary<string, string>();

                headers["x-token"] = token;
            }


            yield return SendRequest(path, requestData, onCompleted, headers);
        }

        private IEnumerator SendRequest<T>(
            string path,
            object requestData,
            UnityAction<ResponseData<T>> onCompleted = null,
            Dictionary<string, string> headers = null) {
            var requestId = GetNextRequestId();

            var requestJson = SerializeHelper.ToJsonIndented(requestData ?? new object());

            var unityWebRequest = CreatePostRequest(path, requestJson, headers);

            Log.Net.Info($"[Req:{requestId}] | Path: {path} | Body: {requestJson}");

            yield return unityWebRequest.SendWebRequest(); //发送请求

            var response = new ResponseData<T>();

            if (unityWebRequest.result is not UnityWebRequest.Result.Success) {
                Log.Net.Error($"[Resp:{requestId}] | Path: {path} | Error: {unityWebRequest.error}");
                response.Code = -1;
                response.Msg = unityWebRequest.error;
            }
            else {
                var receiveContent = unityWebRequest.downloadHandler.text;

                if (!receiveContent.IsNullOrWhiteSpace()) {
                    receiveContent = Decrypt(UnquoteString(receiveContent), _requestHost);
                }


                var raw = SerializeHelper.ToObject<ResponseData<object>>(receiveContent);

                if (raw?.Code == 0) {
                    Log.Net.Info($"[Resp:{requestId}] | Path: {path} | Result: {receiveContent}");

                    // 处理字符串类型的情况
                    if (typeof(T) == typeof(string)) {
                        response.Data = (T) (object) (raw.Data?.ToString() ?? "");
                    }
                    else {
                        response.Data = SerializeHelper.ToObject<T>(JsonConvert.SerializeObject(raw.Data));
                    }
                }
                else {
                    Log.Net.Warning($"[Resp:{requestId}] | Path: {path} | Result: {receiveContent}");

                    response.Code = raw?.Code ?? -2;
                    response.Msg = raw?.Msg ?? "未知错误";
                }
            }

            onCompleted?.Invoke(response);

            unityWebRequest.Dispose();
        }

        private UnityWebRequest CreatePostRequest(string path, string requestJson, Dictionary<string, string> headers = null) {
            path = Encrypt(path, _requestHost);
            requestJson = Encrypt(requestJson, _requestHost);

            var fullUrl = GetApiUrl() + path;

            var request = new UnityWebRequest(fullUrl, UnityWebRequest.kHttpVerbPOST) {
                uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(requestJson)),
                downloadHandler = new DownloadHandlerBuffer(),
                timeout = Timeout
            };

            SetRequestHeaders(request, headers);

            return request;
        }

        private void SetRequestHeaders(UnityWebRequest request, Dictionary<string, string> headers) {
            request.SetRequestHeader("Content-Type", "application/json;charset=utf-8");
            if (headers == null) {
                return;
            }

            foreach (var kvp in headers.Where(kvp => kvp.Value != null)) {
                request.SetRequestHeader(kvp.Key, kvp.Value);
            }
        }

        private int GetNextRequestId() {
            return Interlocked.Increment(ref _requestCounter);
        }

        // 去除双引号（如果存在）
        private static string UnquoteString(string input) {
            if (!string.IsNullOrEmpty(input) && input.Length >= 2 &&
                input[0] == '"' && input[input.Length - 1] == '"') {
                return input.Substring(1, input.Length - 2);
            }

            return input;
        }


        private void SendWebRequest(string url, object requestData = null, bool withToken = false, Dictionary<string, string> header = null) {
            if (withToken) {
                // 合并原有 header
                header ??= new Dictionary<string, string>();
                header["x-token"] = TokenManager.Instance.CachedToken;
            }

            var requestId = GetNextRequestId();

            var requestJson = SerializeHelper.ToJsonIndented(requestData ?? new object());

            var unityWebRequest = CreatePostRequest(url, requestJson, header);

            Log.Net.Info($"[Req:{requestId}] | Path: {url} | Body: {requestJson}");

            unityWebRequest.SendWebRequest(); //发送请求
        }
    }
}
