using System.Collections;
using System.Collections.Generic;

using BackEnd;

using UnityEngine;
using UnityEngine.UI;

public class UICharacterSelectManager : MonoBehaviour
{
    struct CharacterInfo
    {
        public string Uuid;
        public string InDate;
        public string Nickname;
    }

    public Transform SlotContent = null;

    public Button StartButton = null;

    public Button BackButton = null;

    public GameObject CreatePopup = null;

    public InputField CreateNicknameInput = null;

    public Button CreateConfirmButton = null;

    public Button CreateCancelButton = null;

    public GameObject DeleteConfirmPopup = null;

    public Text DeleteConfirmMessage = null;

    public Button DeleteConfirmButton = null;

    public Button DeleteCancelButton = null;

    public Text MessageText = null;

    private const int MAX_CHARACTERS = 20;

    private const int DEFAULT_SLOT_COUNT = 6;

    private readonly List<CharacterInfo> _Characters = new List<CharacterInfo>();

    private UICharacterSlot _SelectedSlot = null;

    private string _PendingSelectUuid = string.Empty;

    private Coroutine _ClearMessageCoroutine = null;

    private UICharacterSlot _PendingDeleteSlot = null;

    private bool _Busy = false;

    void Awake()
    {
        StartButton.onClick.AddListener(OnClickStart);
        BackButton.onClick.AddListener(OnClickBack);
        CreateConfirmButton.onClick.AddListener(OnClickCreateConfirm);
        CreateCancelButton.onClick.AddListener(OnClickCreateCancel);
        DeleteConfirmButton.onClick.AddListener(OnClickDeleteConfirm);
        DeleteCancelButton.onClick.AddListener(OnClickDeleteCancel);
    }

    void OnEnable()
    {
        CreatePopup.SetActive(false);
        DeleteConfirmPopup.SetActive(false);
        _PendingDeleteSlot = null;
        MessageText.text = string.Empty;

        StartCoroutine(RefreshCharacterList());
    }

    IEnumerator RefreshCharacterList()
    {
        BeginLoading();
        yield return null;
        yield return StartCoroutine(RefreshCharacterListInternal());
        EndLoading();
    }

    IEnumerator RefreshCharacterListInternal()
    {
        _Characters.Clear();
        ClearSelection();

        if (!Backend.IsInitialized)
        {
            Debug.LogWarning("Backend가 초기화되지 않았습니다. 로그인 화면을 거쳐 진입해야 합니다.");
            BuildSlots();
            ShowMessage("Login required.", false);
            yield break;
        }

        if (!Backend.IsMultiAccountLogin && !Backend.IsMultiCharacterLogin)
        {
            Debug.LogError("멀티 캐릭터 컨텍스트가 아닙니다."
                + "\nIsLogin : " + Backend.IsLogin
                + "\nIsMultiAccountLogin : " + Backend.IsMultiAccountLogin
                + "\nIsMultiCharacterLogin : " + Backend.IsMultiCharacterLogin
                + "\nNeedsElevation : " + Backend.NeedsElevation);
            BuildSlots();
            ShowMessage("Multi-character login required.", false);
            yield break;
        }

        BackendReturnObject returnObject = null;
        Backend.MultiCharacter.Character.GetCharacterList(result => returnObject = result);
        yield return new WaitUntil(() => returnObject != null);

        if (returnObject.IsSuccess())
        {
            Debug.Log("캐릭터 리스트 불러오기 : " + returnObject);

            LitJson.JsonData characters = returnObject.GetReturnValuetoJSON()["characters"];

            if (characters != null && characters.IsArray)
            {
                for (int i = 0; i < characters.Count; i++)
                {
                    CharacterInfo info = new CharacterInfo();
                    info.Uuid = characters[i]["uuid"].ToString();
                    info.InDate = characters[i]["inDate"].ToString();
                    info.Nickname = characters[i]["nickname"].ToString();

                    _Characters.Add(info);
                }
            }
        }
        else
        {
            Debug.LogError("캐릭터 리스트 불러오기 : " + returnObject);
            ShowMessage("Failed to load character list.", false);
        }

        BuildSlots();
    }

    // 채워진 카드 + 빈 슬롯. 기본 6개(화면에 5개 + 오른쪽 살짝 걸침 → 스크롤 가능 UX), 상한 전까지 항상 빈 슬롯 1개 이상 제공.
    void BuildSlots()
    {
        foreach (Transform child in SlotContent)
        {
            child.gameObject.SetActive(false);
            Destroy(child.gameObject);
        }

        int filled = _Characters.Count;
        int empties = filled >= MAX_CHARACTERS ? 0 : Mathf.Max(1, DEFAULT_SLOT_COUNT - filled);
        int total = filled + empties;

        for (int i = 0; i < total; i++)
        {
            GameObject slotObject = Instantiate(Resources.Load<GameObject>("Prefabs/CharacterSlot"), SlotContent);
            UICharacterSlot slot = slotObject.GetComponent<UICharacterSlot>();

            if (i < filled)
            {
                slotObject.name = _Characters[i].Nickname;
                slot.SetCharacter(_Characters[i].Uuid, _Characters[i].InDate, _Characters[i].Nickname, OnSlotSelected, OnSlotDelete);

                // 생성 직후 자동 선택
                if (_PendingSelectUuid.Length > 0 && _Characters[i].Uuid == _PendingSelectUuid)
                {
                    OnSlotSelected(slot);
                }
            }
            else
            {
                slotObject.name = "Empty";
                slot.SetEmpty(OnClickEmptySlot);
            }
        }

        _PendingSelectUuid = string.Empty;
    }

    void OnSlotSelected(UICharacterSlot slot)
    {
        if (_SelectedSlot != null)
        {
            _SelectedSlot.SetSelected(false);
        }

        _SelectedSlot = slot;
        _SelectedSlot.SetSelected(true);

        StartButton.interactable = true;
    }

    void ClearSelection()
    {
        if (_SelectedSlot != null)
        {
            _SelectedSlot.SetSelected(false);
        }

        _SelectedSlot = null;

        StartButton.interactable = false;
    }

    void OnClickEmptySlot()
    {
        if (_Characters.Count >= MAX_CHARACTERS)
        {
            ShowMessage("Character limit reached. (" + MAX_CHARACTERS + ")", false);
            return;
        }

        CreateNicknameInput.text = string.Empty;
        CreatePopup.SetActive(true);
        CreateNicknameInput.ActivateInputField();
    }

    void OnClickCreateConfirm()
    {
        if (_Busy)
        {
            return;
        }

        string nickname = CreateNicknameInput.text.Trim();

        if (nickname.Length == 0)
        {
            ShowMessage("Enter a nickname.", false);
            return;
        }

        CreatePopup.SetActive(false);
        StartCoroutine(CreateCharacter(nickname));
    }

    IEnumerator CreateCharacter(string nickname)
    {
        BeginLoading();
        yield return null;

        if (!Backend.LocationProperties.IsLoadLocation)
        {
            BackendReturnObject locationResult = null;
            Backend.LocationProperties.UpdateLocationProperties(result => locationResult = result);
            yield return new WaitUntil(() => locationResult != null);

            if (!locationResult.IsSuccess() && locationResult.GetStatusCode() != "204")
            {
                Debug.LogWarning("위치 정보 로드 실패, 수동 설정으로 대체 : " + locationResult);
                Backend.LocationProperties.CustomizeLocationProperties("Seoul", "KR", "Seoul", "ko-KR");
            }
        }

        BackendReturnObject returnObject = null;
        Backend.MultiCharacter.Character.CreateCharacter(nickname, result => returnObject = result);
        yield return new WaitUntil(() => returnObject != null);

        if (!returnObject.IsSuccess())
        {
            Debug.LogError("캐릭터 생성 : " + returnObject);

            string statusCode = returnObject.GetStatusCode();

            if (statusCode == "409")
            {
                ShowMessage("Nickname already in use.", false);
            }
            else if (statusCode == "403")
            {
                ShowMessage("Character limit reached. (" + MAX_CHARACTERS + ")", false);
            }
            else
            {
                ShowMessage("Failed to create character.", false);
            }

            EndLoading();
            yield break;
        }

        Debug.Log("캐릭터 생성 : " + returnObject);
        _PendingSelectUuid = returnObject.GetReturnValuetoJSON()["uuid"].ToString();
        ShowMessage("Character created.", true);

        yield return StartCoroutine(RefreshCharacterListInternal());
        EndLoading();
    }

    void OnClickCreateCancel()
    {
        CreatePopup.SetActive(false);
    }

    void OnSlotDelete(UICharacterSlot slot)
    {
        if (_Busy)
        {
            return;
        }

        _PendingDeleteSlot = slot;
        DeleteConfirmMessage.text = "Delete '" + slot.Nickname + "'?\nThis cannot be undone.";
        DeleteConfirmPopup.SetActive(true);
    }

    void OnClickDeleteCancel()
    {
        _PendingDeleteSlot = null;
        DeleteConfirmPopup.SetActive(false);
    }

    void OnClickDeleteConfirm()
    {
        if (_Busy || _PendingDeleteSlot == null)
        {
            return;
        }

        UICharacterSlot slot = _PendingDeleteSlot;
        _PendingDeleteSlot = null;
        DeleteConfirmPopup.SetActive(false);

        StartCoroutine(DeleteCharacter(slot));
    }

    IEnumerator DeleteCharacter(UICharacterSlot slot)
    {
        BeginLoading();
        yield return null;

        BackendReturnObject returnObject = null;
        Backend.MultiCharacter.Character.DeleteCharacter(slot.Uuid, slot.InDate, result => returnObject = result);
        yield return new WaitUntil(() => returnObject != null);

        if (!returnObject.IsSuccess())
        {
            Debug.LogError("캐릭터 삭제 : " + returnObject);
            ShowMessage("Failed to delete character.", false);
            EndLoading();
            yield break;
        }

        Debug.Log("캐릭터 삭제 : " + returnObject);
        ShowMessage("Character deleted.", true);

        yield return StartCoroutine(RefreshCharacterListInternal());
        EndLoading();
    }

    void OnClickStart()
    {
        if (_Busy || _SelectedSlot == null)
        {
            return;
        }

        StartCoroutine(SelectCharacter(_SelectedSlot));
    }

    IEnumerator SelectCharacter(UICharacterSlot slot)
    {
        BeginLoading();
        yield return null;

        BackendReturnObject returnObject = null;
        Backend.MultiCharacter.Character.SelectCharacter(slot.Uuid, slot.InDate, result => returnObject = result);
        yield return new WaitUntil(() => returnObject != null);

        if (!returnObject.IsSuccess())
        {
            Debug.LogError("캐릭터 로그인 실패 : " + returnObject);

            if (returnObject.GetStatusCode() == "404")
            {
                ShowMessage("Character no longer exists.", false);
                yield return StartCoroutine(RefreshCharacterListInternal());
            }
            else
            {
                ShowMessage("Failed to select character.", false);
            }

            EndLoading();
            yield break;
        }

        Debug.Log("캐릭터 로그인 성공 : " + returnObject);

        if (!Backend.IsMultiCharacterLogin)
        {
            Debug.LogError("SelectCharacter 성공 후 character 컨텍스트로 전환되지 않았습니다.");
            ShowMessage("Failed to enter character context.", false);
            EndLoading();
            yield break;
        }

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

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

    void OnClickBack()
    {
        if (!_Busy)
        {
            StartCoroutine(Logout());
        }
    }

    IEnumerator Logout()
    {
        BeginLoading();
        yield return null;

        BackendReturnObject returnObject = null;
        Backend.BMember.Logout(result => returnObject = result);
        yield return new WaitUntil(() => returnObject != null);

        if (returnObject.IsSuccess())
        {
            Debug.Log("멀티 캐릭터 로그아웃 성공 : " + returnObject);
        }
        else
        {
            Debug.LogWarning("멀티 캐릭터 로그아웃 실패 : " + returnObject);
        }

        GameManager.Instance.UserToken = string.Empty;
        GameManager.Instance.MyNickname = string.Empty;

        EndLoading();
        gameObject.SetActive(false);
        GameManager.Instance.LoginPopup.SetActive(true);
    }


    void BeginLoading()
    {
        _Busy = true;
        StartButton.interactable = false;
        BackButton.interactable = false;
        CreateConfirmButton.interactable = false;
        CreateCancelButton.interactable = false;
        DeleteConfirmButton.interactable = false;
        DeleteCancelButton.interactable = false;
        UILoadingManager.Instance?.Open();
    }

    void EndLoading()
    {
        UILoadingManager.Instance?.Close();
        _Busy = false;
        StartButton.interactable = _SelectedSlot != null;
        BackButton.interactable = true;
        CreateConfirmButton.interactable = true;
        CreateCancelButton.interactable = true;
        DeleteConfirmButton.interactable = true;
        DeleteCancelButton.interactable = true;
    }

    void ShowMessage(string message, bool success)
    {
        MessageText.text = message;
        MessageText.color = success ? new Color(0.18f, 0.55f, 0.24f, 1.0f) : new Color(0.78f, 0.16f, 0.16f, 1.0f);

        if (_ClearMessageCoroutine != null)
        {
            StopCoroutine(_ClearMessageCoroutine);
        }

        _ClearMessageCoroutine = StartCoroutine(ClearMessageAfterDelay());
    }

    IEnumerator ClearMessageAfterDelay()
    {
        yield return new WaitForSeconds(2.5f);

        MessageText.text = string.Empty;
        _ClearMessageCoroutine = null;
    }
}
