using UnityEngine;
using UnityEngine.SceneManagement;

public class GameStateManager : MonoBehaviour
{
    public static GameStateManager Instance { get; private set; }

    [Header("Game State")]
    public bool hasActiveGame = false;
    public string currentSceneName = "";
    public int gameVersion = 1;

    [Header("Team Data")]
    public TeamCharacter[] savedTeam = new TeamCharacter[4];
    public bool teamSetupComplete = false;

    [Header("Progress Data")]
    public int currentLevel = 1;
    public int totalGoldEarned = 0;
    public int battlesWon = 0;
    public int battlesLost = 0;

    [Header("Map Data")]
    public bool hasGeneratedMap = false;
    public int mapSeed = 0;
    public int mapWidth = 100;
    public int mapHeight = 100;
    public float mapNoiseScale = 5f;
    public float mapOceanThreshold = 0.3f;
    public float mapMountainThreshold = 0.7f;
    public float mapForestThreshold = 0.5f;

    [Header("New Game Flags")]
    public bool isNewGame = false; // Flag to indicate this is a new game (not a load)

    private void Awake()
    {
        // Implement singleton pattern
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);

            // Restore new game flag from PlayerPrefs in case instance was recreated
            isNewGame = PlayerPrefs.GetInt("IsNewGame", 0) == 1;
            // Subscribe to scene loading events
            SceneManager.sceneLoaded += OnSceneLoaded;
        }
        else
        {
            Destroy(gameObject);
        }
    }

    private void OnDestroy()
    {
        if (Instance == this)
        {
            SceneManager.sceneLoaded -= OnSceneLoaded;
        }
    }

    private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        currentSceneName = scene.name;
        // Auto-save when moving between scenes (if we have an active game)
        if (hasActiveGame && currentSceneName != "TitleScreen")
        {
            AutoSave();
        }
    }

    public void StartNewGame()
    {
        // Reset all game state
        hasActiveGame = true;
        teamSetupComplete = false;
        currentLevel = 1;
        totalGoldEarned = 0;
        battlesWon = 0;
        battlesLost = 0;

        // Clear team data
        savedTeam = new TeamCharacter[4];

        // Clear map data
        hasGeneratedMap = false;
        mapSeed = Random.Range(0, 999999);

        // Set new game flag - this will force random team placement
        isNewGame = true;
        PlayerPrefs.SetInt("IsNewGame", 1); // Store in PlayerPrefs to persist across scenes
        PlayerPrefs.Save(); // Force immediate save

        // Clear any existing save data
        ClearSaveData();

        // Mark that we have a new game started
        PlayerPrefs.SetInt("GameSaved", 1);
        PlayerPrefs.Save();
    }

    public void SaveGame()
    {
        if (!hasActiveGame)
        {
            Debug.LogWarning("No active game to save!");
            return;
        }

        // Save basic game state
        PlayerPrefs.SetInt("GameSaved", 1);
        PlayerPrefs.SetInt("GameVersion", gameVersion);
        PlayerPrefs.SetString("CurrentScene", currentSceneName);
        PlayerPrefs.SetInt("TeamSetupComplete", teamSetupComplete ? 1 : 0);
        PlayerPrefs.SetInt("CurrentLevel", currentLevel);
        PlayerPrefs.SetInt("TotalGoldEarned", totalGoldEarned);
        PlayerPrefs.SetInt("BattlesWon", battlesWon);
        PlayerPrefs.SetInt("BattlesLost", battlesLost);

        // Save team data
        SaveTeamData();

        // Save map data
        SaveMapData();

        PlayerPrefs.Save();
    }

    public void LoadGame()
    {
        if (!PlayerPrefs.HasKey("GameSaved"))
        {
            Debug.LogWarning("No saved game found!");
            return;
        }

        // Load basic game state
        hasActiveGame = true;
        gameVersion = PlayerPrefs.GetInt("GameVersion", 1);
        currentSceneName = PlayerPrefs.GetString("CurrentScene", "MainTeamSelectScene");
        teamSetupComplete = PlayerPrefs.GetInt("TeamSetupComplete", 0) == 1;
        currentLevel = PlayerPrefs.GetInt("CurrentLevel", 1);
        totalGoldEarned = PlayerPrefs.GetInt("TotalGoldEarned", 0);
        battlesWon = PlayerPrefs.GetInt("BattlesWon", 0);
        battlesLost = PlayerPrefs.GetInt("BattlesLost", 0);

        // Clear new game flag - this is a load operation, use saved positions
        isNewGame = false;
        PlayerPrefs.SetInt("IsNewGame", 0); // Clear from PlayerPrefs too
        PlayerPrefs.Save(); // Force immediate save


        // Load team data
        LoadTeamData();

        // Load map data
        LoadMapData();
    }

    public void AutoSave()
    {
        if (hasActiveGame)
        {
            SaveGame();
        }
    }

    public void SaveTeam(TeamCharacter[] team)
    {
        if (team == null) return;

        for (int i = 0; i < Mathf.Min(team.Length, savedTeam.Length); i++)
        {
            if (team[i] != null)
            {
                savedTeam[i] = team[i].CreateCopy();
            }
        }

        teamSetupComplete = true;

        if (hasActiveGame)
        {
            SaveGame();
        }
    }

    public TeamCharacter[] GetSavedTeam()
    {
        return savedTeam;
    }

    private void SaveTeamData()
    {
        for (int i = 0; i < savedTeam.Length; i++)
        {
            string prefix = $"Character{i}_";

            if (savedTeam[i] != null)
            {
                PlayerPrefs.SetInt(prefix + "Exists", 1);
                PlayerPrefs.SetString(prefix + "Name", savedTeam[i].name);
                PlayerPrefs.SetInt(prefix + "IsMale", savedTeam[i].isMale ? 1 : 0);
                PlayerPrefs.SetInt(prefix + "Strength", savedTeam[i].strength);
                PlayerPrefs.SetInt(prefix + "Dexterity", savedTeam[i].dexterity);
                PlayerPrefs.SetInt(prefix + "Constitution", savedTeam[i].constitution);
                PlayerPrefs.SetInt(prefix + "Wisdom", savedTeam[i].wisdom);
                PlayerPrefs.SetInt(prefix + "Gold", savedTeam[i].gold);
                PlayerPrefs.SetInt(prefix + "Silver", savedTeam[i].silver);
                PlayerPrefs.SetInt(prefix + "Copper", savedTeam[i].copper);
                PlayerPrefs.SetString(prefix + "EquippedWeapon", savedTeam[i].equippedWeapon);
                PlayerPrefs.SetString(prefix + "EquippedArmor", savedTeam[i].equippedArmor);

                // Save inventory lists as comma-separated strings
                PlayerPrefs.SetString(prefix + "Weapons", string.Join(",", savedTeam[i].weapons));
                PlayerPrefs.SetString(prefix + "Armor", string.Join(",", savedTeam[i].armor));
                PlayerPrefs.SetString(prefix + "MiscItems", string.Join(",", savedTeam[i].miscItems));
            }
            else
            {
                PlayerPrefs.SetInt(prefix + "Exists", 0);
            }
        }
    }

    private void LoadTeamData()
    {
        savedTeam = new TeamCharacter[4];

        for (int i = 0; i < savedTeam.Length; i++)
        {
            string prefix = $"Character{i}_";

            if (PlayerPrefs.GetInt(prefix + "Exists", 0) == 1)
            {
                savedTeam[i] = new TeamCharacter();
                savedTeam[i].name = PlayerPrefs.GetString(prefix + "Name", "");
                savedTeam[i].isMale = PlayerPrefs.GetInt(prefix + "IsMale", 1) == 1;
                savedTeam[i].strength = PlayerPrefs.GetInt(prefix + "Strength", 10);
                savedTeam[i].dexterity = PlayerPrefs.GetInt(prefix + "Dexterity", 10);
                savedTeam[i].constitution = PlayerPrefs.GetInt(prefix + "Constitution", 10);
                savedTeam[i].wisdom = PlayerPrefs.GetInt(prefix + "Wisdom", 10);
                savedTeam[i].gold = PlayerPrefs.GetInt(prefix + "Gold", 25);
                savedTeam[i].silver = PlayerPrefs.GetInt(prefix + "Silver", 0);
                savedTeam[i].copper = PlayerPrefs.GetInt(prefix + "Copper", 0);
                savedTeam[i].equippedWeapon = PlayerPrefs.GetString(prefix + "EquippedWeapon", "");
                savedTeam[i].equippedArmor = PlayerPrefs.GetString(prefix + "EquippedArmor", "");

                // Load inventory lists
                string weaponsStr = PlayerPrefs.GetString(prefix + "Weapons", "");
                string armorStr = PlayerPrefs.GetString(prefix + "Armor", "");
                string miscStr = PlayerPrefs.GetString(prefix + "MiscItems", "");

                savedTeam[i].weapons = new System.Collections.Generic.List<string>();
                savedTeam[i].armor = new System.Collections.Generic.List<string>();
                savedTeam[i].miscItems = new System.Collections.Generic.List<string>();

                if (!string.IsNullOrEmpty(weaponsStr))
                    savedTeam[i].weapons.AddRange(weaponsStr.Split(','));
                if (!string.IsNullOrEmpty(armorStr))
                    savedTeam[i].armor.AddRange(armorStr.Split(','));
                if (!string.IsNullOrEmpty(miscStr))
                    savedTeam[i].miscItems.AddRange(miscStr.Split(','));
            }
        }
    }

    private void ClearSaveData()
    {
        // Clear main save indicators
        PlayerPrefs.DeleteKey("GameSaved");
        PlayerPrefs.DeleteKey("GameVersion");
        PlayerPrefs.DeleteKey("CurrentScene");
        PlayerPrefs.DeleteKey("TeamSetupComplete");
        PlayerPrefs.DeleteKey("CurrentLevel");
        PlayerPrefs.DeleteKey("TotalGoldEarned");
        PlayerPrefs.DeleteKey("BattlesWon");
        PlayerPrefs.DeleteKey("BattlesLost");

        // Note: We DON'T clear "IsNewGame" here because it should persist until team placement is done

        // Clear team data
        for (int i = 0; i < 4; i++)
        {
            string prefix = $"Character{i}_";
            PlayerPrefs.DeleteKey(prefix + "Exists");
            PlayerPrefs.DeleteKey(prefix + "Name");
            PlayerPrefs.DeleteKey(prefix + "IsMale");
            PlayerPrefs.DeleteKey(prefix + "Strength");
            PlayerPrefs.DeleteKey(prefix + "Dexterity");
            PlayerPrefs.DeleteKey(prefix + "Constitution");
            PlayerPrefs.DeleteKey(prefix + "Wisdom");
            PlayerPrefs.DeleteKey(prefix + "Gold");
            PlayerPrefs.DeleteKey(prefix + "Silver");
            PlayerPrefs.DeleteKey(prefix + "Copper");
            PlayerPrefs.DeleteKey(prefix + "EquippedWeapon");
            PlayerPrefs.DeleteKey(prefix + "EquippedArmor");
            PlayerPrefs.DeleteKey(prefix + "Weapons");
            PlayerPrefs.DeleteKey(prefix + "Armor");
            PlayerPrefs.DeleteKey(prefix + "MiscItems");
        }

        // Clear map data
        PlayerPrefs.DeleteKey("MapSeed");
        PlayerPrefs.DeleteKey("MapWidth");
        PlayerPrefs.DeleteKey("MapHeight");
        PlayerPrefs.DeleteKey("MapNoiseScale");
        PlayerPrefs.DeleteKey("MapOceanThreshold");
        PlayerPrefs.DeleteKey("MapMountainThreshold");
        PlayerPrefs.DeleteKey("MapForestThreshold");
        PlayerPrefs.DeleteKey("HasGeneratedMap");

        PlayerPrefs.Save();
    }

    // Method to check if we're currently in a game
    public bool IsInGame()
    {
        return hasActiveGame && currentSceneName != "TitleScreen";
    }

    // Method to return to title screen
    public void ReturnToTitle()
    {
        SceneManager.LoadScene("TitleScreen");
    }

    private void SaveMapData()
    {
        PlayerPrefs.SetInt("MapSeed", mapSeed);
        PlayerPrefs.SetInt("MapWidth", mapWidth);
        PlayerPrefs.SetInt("MapHeight", mapHeight);
        PlayerPrefs.SetFloat("MapNoiseScale", mapNoiseScale);
        PlayerPrefs.SetFloat("MapOceanThreshold", mapOceanThreshold);
        PlayerPrefs.SetFloat("MapMountainThreshold", mapMountainThreshold);
        PlayerPrefs.SetFloat("MapForestThreshold", mapForestThreshold);
        PlayerPrefs.SetInt("HasGeneratedMap", hasGeneratedMap ? 1 : 0);
    }

    private void LoadMapData()
    {
        mapSeed = PlayerPrefs.GetInt("MapSeed", Random.Range(0, 999999));
        mapWidth = PlayerPrefs.GetInt("MapWidth", 100);
        mapHeight = PlayerPrefs.GetInt("MapHeight", 100);
        mapNoiseScale = PlayerPrefs.GetFloat("MapNoiseScale", 5f);
        mapOceanThreshold = PlayerPrefs.GetFloat("MapOceanThreshold", 0.3f);
        mapMountainThreshold = PlayerPrefs.GetFloat("MapMountainThreshold", 0.7f);
        mapForestThreshold = PlayerPrefs.GetFloat("MapForestThreshold", 0.5f);
        hasGeneratedMap = PlayerPrefs.GetInt("HasGeneratedMap", 0) == 1;
    }

    public void GenerateNewMap()
    {
        mapSeed = Random.Range(0, 999999);
        hasGeneratedMap = true;
        SaveMapData();
    }

    public bool HasSavedMap()
    {
        return PlayerPrefs.HasKey("MapSeed");
    }

    /// <summary>
    /// Check if this is a new game that should force random team placement
    /// </summary>
    public bool IsNewGameForceRandom()
    {
        // Check both the instance variable and PlayerPrefs in case of timing issues
        bool instanceFlag = isNewGame;
        bool playerPrefsFlag = PlayerPrefs.GetInt("IsNewGame", 0) == 1;

        bool result = instanceFlag || playerPrefsFlag;

        return result;
    }

    /// <summary>
    /// Clear the new game flag after initial team placement is complete
    /// </summary>
    public void ClearNewGameFlag()
    {
        isNewGame = false;
        PlayerPrefs.SetInt("IsNewGame", 0); // Clear from PlayerPrefs too
        PlayerPrefs.Save();
    }
}
