using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using _Combo;
using _Combo.Events;
using _Core;
using AOT;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Scripting;

[assembly: AlwaysLinkAssembly]
namespace Seayoo.ComboSDK.Windows.Lenovo
{
    [Preserve]
    public class LenovoManager : Singleton<LenovoManager>
    {
        private LenovoManager() { }
        private static LenovoManager _instance;
        private static LenovoLoginResult lenovoLoginResult;
        private static int loginResult;
        private static int payResult;
        private static Order orderInfo;

        public static LenovoManager GetInstance()
        {

            if (_instance == null)
            {
                if (_instance == null)
                {
                    _instance = new LenovoManager();
                }
            }
            return _instance;
        }

        public void Init()
        {
            bool initCallback = LGGameSDK.LGSDKInit(InitCallback);
            bool purchaseCallback = LGGameSDK.LGSDKSetPayCallback(SetPayCallback);
            TempDispatcher.Initialize();
        }
        public delegate bool InitCallbackDelegate(IntPtr in_param);

        [MonoPInvokeCallback(typeof(InitCallbackDelegate))]
        public static bool InitCallback(IntPtr in_param)
        {
            if(in_param == null)
            {
                return false;
            }
            else
            {
                string param = Marshal.PtrToStringAnsi(in_param);
                lenovoLoginResult = JsonConvert.DeserializeObject<LenovoLoginResult>(param);
                TempDispatcher.RunOnMainThread(() =>
                {
                    if(bool.TryParse(lenovoLoginResult.data.result, out bool result) && result)
                    {
                        var age = 0;
                        int.TryParse(lenovoLoginResult.age, out age);
                        var credential = new LenovoCredential()
                        {
                            st = lenovoLoginResult.data.token,
                            isAuthened = age > 0,
                            age = age
                        };
                        LoginSuccessEvent.Invoke(new LoginSuccessEvent {
                            credential = credential
                        });
                    }
                    else
                    {
                        // 升级渠道时，需要确认该返回值是否变更
                        if(lenovoLoginResult.reason == "loginwindow is closed by user!!")
                        {
                            LoginCancelEvent.Invoke();
                            return;
                        }
                        var error = new LoginError("lenovo_pc", thirdPartyMessage: lenovoLoginResult.reason);
                        LoginFailedEvent.Invoke(new LoginFailedEvent{
                            error = new InternalError(error)
                        });
                    }   
                });
                    
                return true;
            }
        }

        public delegate bool SetPayCallbackDelegate(IntPtr in_param);

        [MonoPInvokeCallback(typeof(SetPayCallbackDelegate))]
        public static bool SetPayCallback(IntPtr in_param)
        {
            if(in_param == null)
            {
                return false;
            }
            else
            {
                string param = Marshal.PtrToStringAnsi(in_param);
                var lenovoPayResult = JsonConvert.DeserializeObject<LenovoPurchaseResult>(param);
                if(payResult == 0)
                {
                    TempDispatcher.RunOnMainThread(() =>
                    {
                        if(lenovoPayResult.payCompleted)
                        {
                            PurchaseSuccessEvent.Invoke(new PurchaseSuccessEvent{ orderId = orderInfo.orderId});
                        }
                        else
                        {
                            var invalidError = new StoreError(orderInfo, "lenovo_pc");
                            PurchaseFailedEvent.Invoke(new PurchaseFailedEvent{ error = new InternalError(invalidError) });
                        }
                    });
                    
                }
                return true;
            }
        }

        public void Login()
        {
            LenovoLoginRequest lenovoLoginRequest = new LenovoLoginRequest{
                appid = GlobalParameters.Instance.LenovoPcAppId,
                cpid = GlobalParameters.Instance.LenovoPcCpId,
                bizid = GlobalParameters.Instance.LenovoPcBizId,
                key = GlobalParameters.Instance.LenovoPcKey
            };
            string json = JsonUtility.ToJson(lenovoLoginRequest);
            loginResult = LGGameSDK.LGSDKLogin(json);
            switch (loginResult)
            {
                case 0:
                    break;
                case 10:
                    var error = new LoginError("lenovo_pc", thirdPartyCode: 10);
                    Dictionary<string, object> paramz = new Dictionary<string, object> {
                        { "0", 10}
                    };
                    LoginFailedEvent.Invoke(new LoginFailedEvent {error = new InternalError(I18n.T("sdk_init_error", paramz), error)});
                    break;
                case 20:
                    break;
                case 30:
                    var invalidError = new LoginError("lenovo_pc", thirdPartyCode: 30, cause: new InvalidArgumentsError("login arguments"));
                    LoginFailedEvent.Invoke(new LoginFailedEvent {error = new InternalError(invalidError)});
                    break;
            }
        }

        public void Logout()
        {
            lenovoLoginResult = null;
        }

        public void Purchase(Order order, LenovoPurchaseRequest lenovoPurchaseRequest)
        {
            string json = JsonUtility.ToJson(lenovoPurchaseRequest);
            orderInfo = order;
            payResult = LGGameSDK.LGSDKPay(json);
            switch (payResult)
            {
                case 0:
                    break;
                case 30:
                    var invalidError = new StoreError(order, "lenovo_pc", thirdPartyCode: 30, cause: new InvalidArgumentsError("login arguments"));
                    PurchaseFailedEvent.Invoke(new PurchaseFailedEvent{
                        error = new InternalError(invalidError)
                    });
                    break;
            }
        }
    }
}