using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.SceneManagement;



/*
    ***** LOAD ALL PLAYERPREFS FOR DIFFERENT ASPECTS OF THE GAME
            5 PlayerPrefs:
                1. Announcements
                2. Animate Completed Missions
                3. Mission
                4. Rewards
                5. Settings
*/


//PLAYERPREFS for Animate Completed Missions, Missions, Rewards, and Settings
#region
    //PlayerPrefs to handle Animation of Completed Missions
    [System.Serializable]
    public class Completed_Missions_toAnimate{
        public int current_week; //records the week the player is at
        public List<int> completed_missions_toAnimate_data; //records ID's of completed missions
        public int animation_status;
    }


    //MISSIONS PlayerPrefs
    #region
        //Progress of missions
        [System.Serializable]
        public class MissionProgress{
            public string start_date; //The first date when the game was first opened by user
            public int current_week; //records the week the player is at
            public int current_month; //records the week the player is at
            public List<int> completed_missions; //records ID's of completed missions
            public List<string> completed_missions_inprogress; //For missions that span for more than 1 match, e.g Win 2 matches in a row
        }

        //Information about Individual missions, Weekly missions
        [System.Serializable]
        public class MissionInfo{
            public int missionID;
            public string missionTitle;
            public string missionDescription;
            public int missionXP;
            public int missionProgressCount; //Keeps track of missions that requires count, such as Ads
            public int month;
            public int week;
        }

    #endregion



    //REWARDS PlayerPrefs
    #region
        //Player Details for the Game
        [System.Serializable]
        public class PlayerData{
            public int xp; //Player's XP
            public string rank; //Player's rank
            public string prevRank; //Records Player's rank to compare if it changes/Player ranks up
            public int overall_matches; //Match played
            public int win_streak; //Number of win streaks, streaks cause rank to level up
            public int loss_streak; //Number of loss streaks, streaks cause rank to level down
            public int overall_wins; //Number of overall wins
            public int overall_losses; //Number of overall losses
            public int rank_level; //Player's rank level, such as Level 1 Bronze, Level 2 Bronze etc.
            public int prevrank_level;  //Records Player's rank level to compare if it changes/Player ranks up
            public int rank_game; //Keeps count of rank level, if reaches certain limit, then increments rank_level
            public int eliminations;
            public int deaths;
            public int revives;
        }
    #endregion



    //SETTINGS PlayerPrefs Data Details
    #region 
        // Details on GameObject position in the UI
        [System.Serializable]
        public class ControlSettings{
            public float positionX;
            public float positionY;
            public float scaleWidth;
            public float scaleHeight;
        }

        [System.Serializable]
        public class GameSettings{
            public ControlSettings leftControl;
            public ControlSettings blockControl;
            public ControlSettings dodgeControl;

            public ControlSettings rightControl;
            public ControlSettings punchControl;
            public ControlSettings kickControl;

            // New controls/buttons
            public ControlSettings weaponPickupButton;
            public ControlSettings specialMoveButton;
            public ControlSettings shieldButton;
            public ControlSettings splintButton;

            public float leftControlScaleValue;
            public float rightControlScaleValue;
            public float kickControlScaleValue;
            public float punchControlScaleValue;

            public float GameplayVolume_value;
            public float UIVolume_value;
            public float MusicVolume_value;
            public float SFXVolume_value;

            public string[] audioVolumes; //0. GameplayVolume, 1. UIVolume, 2. MusicVolume, 3. SFXVolume
        }
    #endregion
#endregion



public class GameInitialize : MonoBehaviour{
    private static bool isInitialized = false;
    public static GameInitialize Instance { get; private set; }
    [SerializeField] private string authSceneName = "AuthenticationScene";
    [SerializeField] private string menuSceneName = "MenuScene";
    [Tooltip("Force skip auth and go straight to menu after splash")] [SerializeField]
    private bool forceMenuDuringDevelopment = true;

    private Coroutine authRoutine;
    private bool subscribedToSplash;
    private bool waitingForGameManager;

    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }

        if (!isInitialized)
        {
            isInitialized = true;
            Instance = this;
            // Move to root before DontDestroyOnLoad (required for it to work)
            transform.SetParent(null);
            DontDestroyOnLoad(gameObject);
            TryStartAuthFlow();
        }
        else
        {
            Destroy(gameObject);
        }
    }

    private void Start()
    {
        if (GameManager.Instance == null && !waitingForGameManager)
        {
            waitingForGameManager = true;
            StartCoroutine(WaitForGameManagerAndStart());
        }
    }

    private void TryStartAuthFlow()
    {
        var gm = GameManager.Instance;
        if (gm == null)
        {
            if (!waitingForGameManager)
            {
                waitingForGameManager = true;
                StartCoroutine(WaitForGameManagerAndStart());
            }
            return;
        }

        waitingForGameManager = false;

        // Development override: skip subscribing & auth checks entirely.
        if (forceMenuDuringDevelopment)
        {
            Debug.Log("[GameInitialize] forceMenuDuringDevelopment active: skipping auth flow & loading menu when splash ends (or immediately if already finished).");
            if (gm.HasSplashFinished)
            {
                TriggerSceneLoad(menuSceneName);
            }
            else if (!subscribedToSplash)
            {
                gm.SplashSequenceCompleted += () => TriggerSceneLoad(menuSceneName);
                subscribedToSplash = true; // still mark to avoid duplicate subscription
            }
            return;
        }

        if (gm.HasSplashFinished)
        {
            BeginAuthCheck();
        }
        else if (!subscribedToSplash)
        {
            gm.SplashSequenceCompleted += HandleSplashSequenceCompleted;
            subscribedToSplash = true;
        }
    }

    private IEnumerator WaitForGameManagerAndStart()
    {
        while (GameManager.Instance == null)
        {
            yield return null;
        }

        waitingForGameManager = false;
        TryStartAuthFlow();
    }

    private void HandleSplashSequenceCompleted()
    {
        if (GameManager.Instance != null && subscribedToSplash)
        {
            GameManager.Instance.SplashSequenceCompleted -= HandleSplashSequenceCompleted;
        }

        subscribedToSplash = false;
        BeginAuthCheck();
    }

    public void BeginAuthCheck()
    {
        if (authRoutine != null)
        {
            StopCoroutine(authRoutine);
        }

        authRoutine = StartCoroutine(CheckAuthAndRedirectRoutine());
    }

    private IEnumerator CheckAuthAndRedirectRoutine()
    {
    string targetScene = forceMenuDuringDevelopment ? menuSceneName : authSceneName; // still computed (kept for future toggle at runtime)
        string token = PlayerPrefs.GetString("AuthToken", null);

    if (!forceMenuDuringDevelopment && !string.IsNullOrEmpty(token))
        {
            var walletSystem = CoinWalletSystem.Instance;
            if (walletSystem != null)
            {
                var initTask = walletSystem.InitializeWallet();
                while (!initTask.IsCompleted)
                {
                    yield return null;
                }

                if (initTask.Status == System.Threading.Tasks.TaskStatus.RanToCompletion && initTask.Result)
                {
                    Debug.Log("Authentication successful. Loading menu.");
                    targetScene = menuSceneName;
                }
                else
                {
                    string reason = initTask.IsFaulted ? initTask.Exception?.GetBaseException()?.Message ?? "Wallet initialization faulted." : "Failed to initialize wallet.";
                    RedirectToAuth(reason);
                    authRoutine = null;
                    yield break;
                }
            }
            else
            {
                Debug.LogWarning("CoinWalletSystem instance not found. Proceeding to menu.");
                targetScene = menuSceneName;
            }
        }
        else
        {
            Debug.Log("No auth token found. Redirecting to authentication.");
            RedirectToAuth("No auth token found.");
            authRoutine = null;
            yield break;
        }

        if (forceMenuDuringDevelopment)
        {
            // Should have been short-circuited earlier, but safeguard here.
            Debug.Log("[GameInitialize] (Late) development override still active; forcing menu.");
            targetScene = menuSceneName;
        }
        TriggerSceneLoad(targetScene);
        authRoutine = null;
    }

    private void RedirectToAuth(string reason)
    {
        Debug.Log($"Redirecting to auth: {reason}");
        ClearStoredToken();
        TriggerSceneLoad(authSceneName);
    }

    private void TriggerSceneLoad(string sceneName)
    {
        if (GameManager.Instance != null)
        {
            GameManager.Instance.LoadSceneWithLoading(sceneName);
        }
        else
        {
            SceneManager.LoadScene(sceneName);
        }
    }

    private void ClearStoredToken()
    {
        PlayerPrefs.DeleteKey("AuthToken");
        PlayerPrefs.Save();
    }

    public void OnSuccessfulAuthentication(string token)
    {
        PlayerPrefs.SetString("AuthToken", token);
        PlayerPrefs.Save();
        BeginAuthCheck();
    }

    public void SetUserAuthenticated(bool authenticated)
    {
        if (forceMenuDuringDevelopment)
        {
            Debug.Log("[GameInitialize] Ignoring SetUserAuthenticated call because forceMenuDuringDevelopment is TRUE.");
            return;
        }
        if (!authenticated) RedirectToAuth("User logged out.");
    }

    private void OnDestroy()
    {
        if (GameManager.Instance != null && subscribedToSplash)
        {
            GameManager.Instance.SplashSequenceCompleted -= HandleSplashSequenceCompleted;
        }

        if (Instance == this)
        {
            Instance = null;
            isInitialized = false;
        }
    }
}
