using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using asap.core;
using Newtonsoft.Json.Linq;
using UnityEngine;
using AppsFlyerSDK;

namespace tysdk
{
    public partial class TYSdkFacade : MonoBehaviour
    {
        public class AccountInfo
        {
            public int userId;
            public string token;
            public string jwtToken;
            public string strUserId => userId.ToString();
        }

        private static AccountInfo _accountInfo;
        public AccountInfo TYAccountInfo => _accountInfo;

        private static IDictionary<string, Action<ITYSdkCallback>> callbacks = new Dictionary<string, Action<ITYSdkCallback>>();

        private static TYSdkFacade _instance;
        public static TYSdkFacade Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new GameObject("TYSdkFacade").AddComponent<TYSdkFacade>();
                    DontDestroyOnLoad(_instance.gameObject);
                }
                return _instance;
            }
        }
        
        public void Init()
        {
            //AppsFlyer.setIsDebug(true);
#if UNITY_IOS
            AppsFlyer.initSDK("rSySeWtvKabfbPZE7Lmx7C","6505145935");
#elif UNITY_ANDROID
            AppsFlyer.initSDK("rSySeWtvKabfbPZE7Lmx7C", null);
            UnityBridgeFunc.InitSDK();
#endif
            AppsFlyer.startSDK();
        }

        public void InitAfterLogin()
        {
            AppsFlyer.setCustomerUserId(_accountInfo.strUserId);
        }


        /*================================================

                                 _                             _   
                                / \   ___ ___ ___  _   _ _ __ | |_ 
                               / _ \ / __/ __/ _ \| | | | '_ \| __|
                              / ___ \ (_| (_| (_) | |_| | | | | |_ 
                             /_/   \_\___\___\___/ \__,_|_| |_|\__|

        =================================================*/


        public bool IsLoggedIn => _accountInfo != null;

        public void Logout()
        {
            UnityEngine.Debug.Log("Logout");
            UnityBridgeFunc.UnityLoginOut();
            _accountInfo = null;
        }

        public void LogoutByChannel()
        {
            UnityEngine.Debug.Log("LogoutByChannel");
            UnityBridgeFunc.UnityLoginOut();
            _accountInfo = null;
        }

        public async Task<LoginInfo> Login(EAccoutType accoutType)
        {
#if UNITY_EDITOR 
            await Task.Yield();
            var deviceId = UnityEngine.Device.SystemInfo.deviceUniqueIdentifier.Split('-')[0].Substring(0,8);

            var userId = (int)ulong.Parse(deviceId, System.Globalization.NumberStyles.HexNumber);

            _accountInfo = new AccountInfo()
            {
                userId = userId,
            };

            return new LoginInfo()
            {
                isSuccess = true,
                userId = userId
            };

#elif UNITY_ANDROID || UNITY_IOS

            var taskSource = new TaskCompletionSource<LoginInfo>();
            callbacks.Add("LoginResult", (ITYSdkCallback callback) =>
            {
                taskSource.SetResult((LoginInfo)callback);
            });

            UnityBridgeFunc.UnityLogin(accoutType);

            return await taskSource.Task;

#endif

        }

        public void LoginResult(string json)
        {
            Debug.Log("[TYSdkFacade] Login callback:");
            var result = new LoginInfo();
            var data = JObject.Parse(json);
            var code = (int)data["code"];
            result.code = code;

            if (code == 0)
            {
                var loginData = data["respObj"]["result"];

                _accountInfo = new AccountInfo()
                {
                    userId = (int)loginData["userId"],
                    token = (string)loginData["token"],
                    jwtToken = (string)loginData["jwttoken"],
                };


                result.isSuccess = true;
                result.userId = _accountInfo.userId;
                SetUserInfo();
            }

            if (callbacks.TryGetValue("LoginResult", out var action))
            {
                action.Invoke(result);
                callbacks.Remove("LoginResult");
            }
        }

        private void SetUserInfo()
        {
            if (_accountInfo == null) return;
            var strUserId = _accountInfo.strUserId;

            UnityBridgeFunc.SetGaUserInfo(strUserId);
            UnityBridgeFunc.UnitySetAdBoxUserInfo(strUserId);
            UnityBridgeFunc.UnityInitADSConfig();
        }
    }
}
