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


/*
    STEPS TO FOLLOW:
    1. There must be initialization of all PlayerPrefs for the game each time the game is started
    2. Add Missions from Menu Scene (MissionsManager.cs) to Game Scene (Missions.cs), with their respective Scripts considered
    3. When a mission is completed, trigger a function such as updateMission() or update_MonthlyMission() which will pass that mission's ID
    4. Within the specific triggered function, check if the mission ID is already stored, if not, then add the mission ID
    5. The mission ID is used to get the mission details such as XP, and then add the XP to the current player's recorded XP
    
*/


public class GameStatsManager : MonoBehaviour{
    Missions mission_component;
    PlayerData players_profile_details, playerData;
    private MissionProgress missionProgress;
    private Completed_Missions_toAnimate completed_missions_toAnimate;

    private const string Player_RewardsData = "Player_RewardsData";
    private const string player_missionData = "Player_MissionData";
    private const string player_completed_Missions_toAnimate = "Player_Completed_Missions_toAnimate";


    // Start is called before the first frame update
    void Start(){
        //NOTE: The code below should be within a function which will then be called whenever the game starts
        if (PlayerPrefs.HasKey(player_missionData)){
            missionProgress = LoadPlayer_MissionData();
        }


        if (PlayerPrefs.HasKey(player_completed_Missions_toAnimate)){
            completed_missions_toAnimate = LoadPlayerData_CompletedMission_toAnimate();
        }

        if (PlayerPrefs.HasKey(Player_RewardsData)){
            playerData = LoadPlayerData();
        }

        mission_component = GetComponent<Missions>();
    }


    string ListToString<T>(List<T> list){
        // Use string.Join to concatenate the elements of the list into a string
        return string.Join(", ", list);
    }


    // Function called when the Player start a match
    public void addMatch(){
        SaveManager.Instance.AddMatch();
    }


    // Function called at the start of every match
    public void winsCountedEachMatch(){
        ResetMissions = false;
        wins_added = 0;
        loss_added = 0;
    }


    // Function called when the Player wins a round
    private int wins_added;
    public void addWin(){
        SaveManager.Instance.AddWin();
    }


    // Function called when the Player loses a round
    private int loss_added;
    public void addLoss(){
        SaveManager.Instance.AddLoss();
    }


    // Function called when the Player finishes a match
    public void match_end(){
        Debug.Log("Match Over, Start the Animation for the Completed Missions");
        go_to_menu("Missions"); //Go to Missions UI in MenuScene
    }


    // Function called when the Player quits a match
    public void match_quit(){
        // Debug.Log("Match Over, Start the Animation for the Completed Missions");
        addMatch();

        go_to_menu("Home"); //Go to Missions UI in MenuScene
    }


    public void match_retry(){
        
    }


    // Updates the Player's RANK
    public string UpdateRank(int rank_num){
        string current_rank = "";

        switch (rank_num){
            //x represents Game wins
            case int x when ((x >= 0 && x < 80) || (x < 0)):
                current_rank = "Bronze";
                break;

            case int x when (x >= 80 && x < 140):
                current_rank = "Silver";
                break;

            case int x when (x >= 140 && x < 200):
                current_rank = "Gold";
                break;

            case int x when (x >= 200 && x < 260):
                current_rank = "Platinum";
                break;

            case int x when (x >= 260 && x < 320):
                current_rank = "Diamond";
                break;

            case int x when (x >= 320 && x < 400):
                current_rank = "Master";
                break;

            case int x when (x == 400):
                current_rank = "Apex Predator";
                break;
        }
        return current_rank;
    }



    //UPDATE MISSIONS BASED ON INPUT
    //Alter this, so that the function can be called with the missionID, mission_type as the parameters to it
    public void updateMission(int missionID_completed){
        SaveManager.Instance.AddCompletedMission(missionID_completed);
    }


    // Function called when Player chooses to Retry
    public void ResetMissions_onRetry(){
        MissionProgress missionProgressReset = LoadPlayer_MissionData();
        Completed_Missions_toAnimate missionAnimateReset = LoadPlayerData_CompletedMission_toAnimate();
        playerData = LoadPlayerData();

        //Overall Player Loss (OPL), Overall Player Wins (OPW), Wins In Match (WIM), Losses In Match (LIM) 
        Debug.LogError($"R1 OPW = {playerData.overall_wins}, OPL = {playerData.overall_losses}, WIM = {wins_added}, LIM = {loss_added}");

        if (playerData.overall_wins != 0){
            playerData = LoadPlayerData();
            playerData.overall_wins = playerData.overall_wins - wins_added;
            
            if (playerData.overall_wins < 0){
                playerData.overall_wins = 0;
            }
            
            SavePlayerData(playerData);
        }

        if (playerData.overall_losses != 0){
            playerData = LoadPlayerData();
            playerData.overall_losses = playerData.overall_losses - loss_added;

            if (playerData.overall_losses < 0){
                playerData.overall_losses = 0;
            }

            SavePlayerData(playerData);
        }

        //Reset Player XP for the Completed Missions, Reverse the match
        foreach (int missionID in missionAnimateReset.completed_missions_toAnimate_data){
            playerData = LoadPlayerData(); //Load
            missionProgressReset = LoadPlayer_MissionData();

            missionProgressReset.completed_missions.Remove(missionID); //Remove the mission from recorded completed missions
            if (playerData.xp != 0){
                playerData.xp = playerData.xp - mission_component.getmission_XP(missionID, 0); //Reduce XP
            }

            if (playerData.xp < 0){
                playerData.xp = 0;
            }
    
            SavePlayerData(playerData); //Save
            SavePlayer_MissionData(missionProgressReset);
        }

        //Reset Missions to Animate
        missionAnimateReset.completed_missions_toAnimate_data = new List<int> { };
        missionAnimateReset.animation_status = 0;
        SavePlayer_Completed_Missions_toAnimate(missionAnimateReset);

        //Reset Completed Missions
        // missionProgressReset = LoadPlayer_MissionData();
        // missionProgressReset.completed_missions = new List<int>();
        // SavePlayer_MissionData(missionProgressReset);

        playerData = LoadPlayerData();
        playerData.prevRank = playerData.rank;
        string player_rank = UpdateRank(playerData.rank_game);
        playerData.rank = player_rank;
        SavePlayerData(playerData);

        //Overall Player Loss (OPL), Overall Player Wins (OPW), Wins In Match (WIM), Losses In Match (LIM) 
        Debug.LogError($"R2 OPW = {playerData.overall_wins}, OPL = {playerData.overall_losses}, WIM = {wins_added}, LIM = {loss_added}, CM = {ListToString(missionProgressReset.completed_missions)}");

        ResetMissions = true; //Quit functions have been done
    }


    // Function called when the Player Quits, Reset the Missions completed and XP gained from the match
    private bool ResetMissions;
    public void ResetCompletedMissions(){
        Debug.Log("ResetCompletedMissions");
        MissionProgress missionProgressReset = LoadPlayer_MissionData();
        Completed_Missions_toAnimate missionAnimateReset = LoadPlayerData_CompletedMission_toAnimate();
        playerData = LoadPlayerData();

        //Overall Player Loss (OPL), Overall Player Wins (OPW), Wins In Match (WIM), Losses In Match (LIM) 
        Debug.LogError($"R1 OPW = {playerData.overall_wins}, OPL = {playerData.overall_losses}, WIM = {wins_added}, LIM = {loss_added}");

        if (playerData.overall_wins != 0){
            playerData = LoadPlayerData();
            playerData.overall_wins = playerData.overall_wins - wins_added;
            
            if (playerData.overall_wins < 0){
                playerData.overall_wins = 0;
            }
            
            SavePlayerData(playerData);
        }

        if (playerData.overall_losses != 0){
            playerData = LoadPlayerData();
            playerData.overall_losses = playerData.overall_losses - loss_added;

            if (playerData.overall_losses < 0){
                playerData.overall_losses = 0;
            }

            SavePlayerData(playerData);
        }

        //Reset Player XP for the Completed Missions, Reverse the match
        foreach (int missionID in missionAnimateReset.completed_missions_toAnimate_data){
            playerData = LoadPlayerData(); //Load
            missionProgressReset = LoadPlayer_MissionData();

            missionProgressReset.completed_missions.Remove(missionID); //Remove the mission from recorded completed missions
            if (playerData.xp != 0){
                playerData.xp = playerData.xp - mission_component.getmission_XP(missionID, 0); //Reduce XP
            }

            if (playerData.xp < 0){
                playerData.xp = 0;
            }
    
            SavePlayerData(playerData); //Save
            SavePlayer_MissionData(missionProgressReset);
        }
    
        //Reset Missions to Animate
        missionAnimateReset.completed_missions_toAnimate_data = new List<int> { };
        missionAnimateReset.animation_status = 1;
        SavePlayer_Completed_Missions_toAnimate(missionAnimateReset);

        //Reset Completed Missions
        // missionProgressReset = LoadPlayer_MissionData();
        // missionProgressReset.completed_missions = new List<int>();
        // SavePlayer_MissionData(missionProgressReset);

        for (int i=0; i<=2; i++){
            addLoss();
            // playerData = LoadPlayerData();
            // playerData.overall_losses = playerData.overall_losses + 1;
            // SavePlayerData(playerData);
        }

        playerData = LoadPlayerData();
        playerData.prevRank = playerData.rank;
        string player_rank = UpdateRank(playerData.rank_game);
        playerData.rank = player_rank;
        SavePlayerData(playerData);

        //Overall Player Loss (OPL), Overall Player Wins (OPW), Wins In Match (WIM), Losses In Match (LIM) 
        Debug.LogError($"R2 OPW = {playerData.overall_wins}, OPL = {playerData.overall_losses}, WIM = {wins_added}, LIM = {loss_added}, CM = {ListToString(missionProgressReset.completed_missions)}");

        ResetMissions = true; //Quit functions have been done
    }


    // Update is called once per frame
    void Update(){
        
    }


    //Change Scenes
    public string sceneToActivate = "MenuScene";
    public void go_to_menu(string uiSubcomponentToActivate){
        //Show Loading UI
        GameManager.Instance.ShowLoadingUI();
        GameManager.Instance.gameObject.GetComponent<LoadingScreen>().UI_to_show_AfterLoading(1, "MenuScene");
        SceneManager.sceneLoaded += (scene, mode) => OnSceneLoaded(scene, mode, uiSubcomponentToActivate);
        GameManager.Instance.gameObject.GetComponent<LoadingScreen>().InitializeLoading();

    }

    // Function called when the new scene is loaded
    private void OnSceneLoaded(Scene scene, LoadSceneMode mode, string uiSubcomponentToActivate){
        if (scene.name == sceneToActivate){
            GameObject uiObject = GameObject.Find("UI");
            if (uiObject != null){
                ShowCompletedMissionsAnimation(uiObject, uiSubcomponentToActivate);
            }
            else{
                Debug.LogError("UI GameObject not found in MenuScene!");
            }
        }
    }


    private void ShowCompletedMissionsAnimation(GameObject parent, string uiSubcomponentToActivate){
        foreach (Transform child in parent.transform){
            if ((child.name != "ModeSelection")){
                child.gameObject.SetActive(false);
            }
        }

        if (uiSubcomponentToActivate == "Home"){
            GameObject UI_to_be_shown = parent.transform.Find(uiSubcomponentToActivate).gameObject;
            UI_to_be_shown.SetActive(true); //When the Menu scene is activated, show this UI

            if (ResetMissions == false){
                ResetCompletedMissions();
            }

        }else{
            //Sets Missions UI to true
            Completed_Missions_toAnimate missionAnimateReset = LoadPlayerData_CompletedMission_toAnimate();
            missionAnimateReset.animation_status = 0;
            SavePlayer_Completed_Missions_toAnimate(missionAnimateReset);

            GameObject UI_to_be_shown = parent.transform.Find(uiSubcomponentToActivate).gameObject;
            UI_to_be_shown.SetActive(true); //When the Menu scene is activated, show this UI

        }
    }


    // ***** PLAYERPREFS
    //Serializes and Saves mission progress to PlayerPrefs.
    private void SavePlayer_MissionData(MissionProgress data){
        string jsonData = JsonUtility.ToJson(data);
        PlayerPrefs.SetString(player_missionData, jsonData); // Details stored as "PlayerData"
        PlayerPrefs.Save();
    }

    //Loads mission progress from PlayerPrefs.
    MissionProgress LoadPlayer_MissionData(){
        string jsonData = PlayerPrefs.GetString(player_missionData, "{}"); // Details were stored as "PlayerData"
        return JsonUtility.FromJson<MissionProgress>(jsonData);
    }

    //Saves PlayerData to PlayerPrefs.
    private void SavePlayerData(PlayerData data){
        string jsonData = JsonUtility.ToJson(data);
        PlayerPrefs.SetString(Player_RewardsData, jsonData); // Details stored as "PlayerData"
        PlayerPrefs.Save();
    }

    //Load player data from PlayerPrefs
    PlayerData LoadPlayerData(){
        string jsonData = PlayerPrefs.GetString(Player_RewardsData, "{}"); // Details were stored as "PlayerData"
        return JsonUtility.FromJson<PlayerData>(jsonData);
    }

    //Saves PlayerData to PlayerPrefs.
    private void SavePlayer_Completed_Missions_toAnimate(Completed_Missions_toAnimate data){
        string jsonData = JsonUtility.ToJson(data);
        PlayerPrefs.SetString(player_completed_Missions_toAnimate, jsonData); // Details stored as "PlayerData"
        PlayerPrefs.Save();
    }

    Completed_Missions_toAnimate LoadPlayerData_CompletedMission_toAnimate(){
        string jsonData = PlayerPrefs.GetString(player_completed_Missions_toAnimate, "{}"); // Details were stored as "PlayerData"
        return JsonUtility.FromJson<Completed_Missions_toAnimate>(jsonData);
    }
}
