using BackEnd;
using System;
using System.Collections;


using UnityEngine;
using UnityEngine.UI;

public class UILoginManager : MonoBehaviour
{
    struct UserTokenJson
    {
        public string id;
        public string pw;
        public string language;
    }

    public Toggle MultiCharacter = null;

    public Toggle CustomAuth = null;

    public InputField Username = null;

    public InputField Password = null;

    public InputField Property = null;

    public Button LoginButton = null;

    // Start is called before the first frame update
    void Start()
    {
        if (LoginButton != null)
        {
            LoginButton.onClick.AddListener(Login);
        }
    }

    private Coroutine _LoginCoroutine = null;

    void Login()
    {
        if (_LoginCoroutine == null)
        {
            _LoginCoroutine = StartCoroutine(LoginCoroutine());
        }
    }

    IEnumerator LoginCoroutine()
    {
        if (Username == null || Password == null)
        {
            EndLogin();
            yield break;
        }

        string id = Username.text.Trim();
        string password = Password.text;

        if (id.Length == 0 || password.Length == 0)
        {
            EndLogin();
            yield break;
        }

        bool isCustomAuth = CustomAuth != null && CustomAuth.isOn;
        bool isMultiCharacter = MultiCharacter != null && MultiCharacter.isOn;

        UserTokenJson userTokenJson = new UserTokenJson();
        userTokenJson.id = id;
        userTokenJson.pw = password;

        if (isCustomAuth)
        {
            ConfigureLocation(true, ref userTokenJson);

            GameManager.Instance.UserToken = JsonUtility.ToJson(userTokenJson);
            GameManager.Instance.MyNickname = id;

            EndLogin();
            Debug.Log("채팅을 시작합니다");
            GameManager.Instance.StartBackendChat();
            yield break;
        }

        UILoadingManager.Instance?.Open();
        yield return null;

        if (!Backend.IsInitialized)
        {
            BackendReturnObject initializeResult = null;
            Backend.InitializeAsync(result => initializeResult = result);
            yield return new WaitUntil(() => initializeResult != null);

            if (!initializeResult.IsSuccess())
            {
                Debug.LogError("Backend 초기화 실패 : " + initializeResult);
                EndLogin();
                yield break;
            }
        }

#if UNITY_ANDROID
        Debug.Log("구글 해시 : " + Backend.Utils.GetGoogleHash());
#endif

        ConfigureLocation(false, ref userTokenJson);

        bool loginSuccess = false;
        yield return StartCoroutine(LoginOrSignUp(id, password, success => loginSuccess = success));

        if (!loginSuccess)
        {
            EndLogin();
            yield break;
        }

        GameManager.Instance.UserToken = string.Empty;

        if (isMultiCharacter)
        {
            if (Backend.NeedsElevation)
            {
                BackendReturnObject elevateResult = null;
                Backend.BMember.Elevate(result => elevateResult = result);
                yield return new WaitUntil(() => elevateResult != null);

                if (!elevateResult.IsSuccess())
                {
                    Debug.LogError("멀티 캐릭터 계정 승격 실패 : " + elevateResult);
                    EndLogin();
                    yield break;
                }

                Debug.Log("멀티 캐릭터 계정 승격 성공 : " + elevateResult);
            }

            if (!Backend.IsMultiAccountLogin)
            {
                Debug.LogError("멀티 캐릭터 account 컨텍스트 진입 실패"
                    + "\nIsLogin : " + Backend.IsLogin
                    + "\nIsMultiAccountLogin : " + Backend.IsMultiAccountLogin
                    + "\nIsMultiCharacterLogin : " + Backend.IsMultiCharacterLogin
                    + "\nNeedsElevation : " + Backend.NeedsElevation);
                EndLogin();
                yield break;
            }

            EndLogin();
            GameManager.Instance.ShowCharacterSelect();
            yield break;
        }

        if (Backend.IsMultiAccountLogin)
        {
            Debug.LogWarning("이미 멀티 캐릭터 계정으로 승격된 아이디입니다. 캐릭터 선택 화면으로 이동합니다.");
            EndLogin();
            GameManager.Instance.ShowCharacterSelect();
            yield break;
        }

        GameManager.Instance.MyNickname = Backend.GetBackendChatSettings().nickname;

        EndLogin();
        Debug.Log("채팅을 시작합니다");
        GameManager.Instance.StartBackendChat();
    }
    IEnumerator LoginOrSignUp(string id, string password, Action<bool> onComplete)
    {
        BackendReturnObject returnObject = null;
        Backend.BMember.CustomLogin(id, password, result => returnObject = result);
        yield return new WaitUntil(() => returnObject != null);

        if (returnObject.IsSuccess())
        {
            Debug.Log("로그인 성공 : " + returnObject);
            onComplete(true);
            yield break;
        }

        // 비밀번호 오류를 회원가입으로 처리하면 409만 발생하므로 여기서 중단한다.
        if (returnObject.GetStatusCode() == "401" && returnObject.GetMessage() == "bad customId")
        {
            Debug.LogError("로그인 실패 : " + returnObject);
            onComplete(false);
            yield break;
        }

        returnObject = null;
        Backend.BMember.CustomSignUp(id, password, result => returnObject = result);
        yield return new WaitUntil(() => returnObject != null);

        if (!returnObject.IsSuccess())
        {
            Debug.LogError("회원가입 실패 : " + returnObject);
            onComplete(false);
            yield break;
        }

        Debug.Log("회원가입 성공 : " + returnObject);

        // 멀티 프로젝트의 신규 가입은 곧바로 account 컨텍스트다.
        if (Backend.IsMultiAccountLogin)
        {
            Debug.Log("멀티 캐릭터 account 컨텍스트로 회원가입 완료");
            onComplete(true);
            yield break;
        }

        returnObject = null;
        Backend.BMember.UpdateNickname(id, result => returnObject = result);
        yield return new WaitUntil(() => returnObject != null);

        if (!returnObject.IsSuccess())
        {
            Debug.LogError("닉네임 변경 실패(회원가입은 성공) : " + returnObject);
            onComplete(false);
            yield break;
        }

        Debug.Log("닉네임 변경 성공 : " + returnObject);

        returnObject = null;
        Backend.BMember.CustomLogin(id, password, result => returnObject = result);
        yield return new WaitUntil(() => returnObject != null);

        if (!returnObject.IsSuccess())
        {
            Debug.LogError("회원가입 후 로그인 실패 : " + returnObject);
            onComplete(false);
            yield break;
        }

        Debug.Log("회원가입 후 로그인 성공 : " + returnObject);
        onComplete(true);
    }

    void EndLogin()
    {
        UILoadingManager.Instance?.Close();
        _LoginCoroutine = null;
    }

    void ConfigureLocation(bool isCustomAuth, ref UserTokenJson userTokenJson)
    {
        if (Property == null || Property.text.Length == 0)
        {
            return;
        }

        string[] properties = Property.text.Split(',');

        if (properties.Length != 4)
        {
            Debug.LogWarning("지역 설정은 city,country,region,language 형식이어야 합니다.");
            return;
        }

        string language = properties[3].Replace("\n", "").Replace(" ", "");

        if (isCustomAuth)
        {
            userTokenJson.language = language;
            return;
        }

        Backend.LocationProperties.CustomizeLocationProperties(properties[0], properties[1], properties[2], language);

        //Backend.LocationProperties.CustomizeLocationProperties("Seoul", "South Korea", "Seoul", "ko-KR");

        //Seoul, South Korea, Seoul, ko-KR
        //New York, United States, New York, en-US
        //Tokyo, Japan, Tokyo, ja-JP
        //Beijing, China, Beijing, zh-CN
    }
}
