using System;
using System.Collections;
using System.Collections.Generic;
using SGModule.Common;
using SGModule.Common.Helper;
using UnityEngine;
using UnityEngine.Events;

namespace SGModule.NetKit {
    public static class TrackKit {
        private static string _traceID;
        private static readonly Dictionary<string, bool> _statusDic = new();

        //登录前的打点数据，没有token无法正确发送，登录成功后重新发一遍
        private static readonly Queue<TrackData> _waitLoginSuccessTrackQueue = new();

        private static void PostTrack(TrackData trackData, UnityAction<bool, TrackData> callback = null) {
            if (!LoginKit.Instance.LoginSuccess) {
                _waitLoginSuccessTrackQueue.Enqueue(trackData);
                return;
            }

            NetKit.Instance.Post<TrackData>("/event/incrN", trackData,
                response => {
                    callback?.Invoke(response.IsSuccess, response.Data);
                });
        }

        /// <summary>
        ///     发送未发送的打点数据
        /// </summary>
        /// <returns></returns>
        public static IEnumerator NoSentTrackProcessing() {
            //处理未发送的打点数据
            while (_waitLoginSuccessTrackQueue.Count > 0) {
                var trackData = _waitLoginSuccessTrackQueue.Dequeue();
                PostTrack(trackData);

                yield return new WaitForSeconds(1f);
            }

            _waitLoginSuccessTrackQueue.Clear();
        }


        public static void SendEvent(string @event, string property = "", int n = 1) {
            // 检查Key是否注册
            if (!TrackEvent.Contains(@event)) {
                Log.NetKit.Warning($"Not found event key: {@event}");
                return;
            }

            if (!TrackProperty.Contains(property)) {
                Log.NetKit.Warning($"Not found property key: {property}");
                return;
            }

            var data = new TrackData { Event = @event, Property = property, N = n };

            Log.NetKit.Info($"Sending track {data.Event} | {data.Property} | {data.N}");

            PostTrack(data);
        }


        #region 登录漏斗

        private static readonly Dictionary<LoginFunnelEventType, string> _loginFunnelEventMap = new() {
            { LoginFunnelEventType.Bootstrap, "bootstrap" },
            { LoginFunnelEventType.AfSend, "afSend" },
            { LoginFunnelEventType.AfRecv, "afRecv" },
            { LoginFunnelEventType.LoginSend, "loginSend" },
            { LoginFunnelEventType.LoginRecv, "loginRecv" },
            { LoginFunnelEventType.LoadBegin, "loadBegin" },
            { LoginFunnelEventType.LoadFinish, "loadFinish" },
            { LoginFunnelEventType.EnterButtonShow, "enterButtonShow" },
            { LoginFunnelEventType.EnterButtonClick, "enterButtonClick" },
            { LoginFunnelEventType.EnterHall, "enterHall" },
        };

        /// <summary>
        ///     登录漏斗打点
        /// </summary>
        /// <param name="loginFunnelEventType"></param>
        /// <param name="message"></param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static void TrackLoginFunnel(LoginFunnelEventType loginFunnelEventType, string message = "") {
            if (!_loginFunnelEventMap.TryGetValue(loginFunnelEventType, out var trackName)) {
                throw new ArgumentOutOfRangeException(nameof(loginFunnelEventType), loginFunnelEventType, null);
            }

            if (_statusDic.TryGetValue(trackName, out var status)) {
                if (status) {
                    return;
                }
            }

            _statusDic.Add(trackName, true);

            PostFunnelLogin(trackName, message);
        }


        private static void PostFunnelLogin(string type, string payload) {
            if (type == "bootstrap") {
                var timestamp = DateTime.Now.ToUniversalTime().Ticks - 621355968000000000;
                _traceID = timestamp.ToString();
            }

            var requestData = new RespLoginFunnelData {
                Uid = LoginKit.Instance.LoginModel?.Uid ?? -1,
                TraceID = _traceID,
                DeviceID = DeviceHelper.GetDeviceID(),
                PackName = ConfigManager.GameConfig.packageName,
                Version = Application.version,
                Channel = LoginKit.Instance.Channel,
                Type = type,
                Payload = payload
            };

            NetKit.Instance.Post("event/funnelLogin", requestData, withToken: false);
        }

        #endregion
    }

    public enum LoginFunnelEventType {
        Bootstrap,
        AfSend,
        AfRecv,
        LoginSend,
        LoginRecv,
        LoadBegin,
        LoadFinish,
        EnterButtonShow,
        EnterButtonClick,
        EnterHall
    }
}
