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

#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif

public class GameLauncher : MonoBehaviour
{
    public enum GamePhase { Before, Shooting, After }

    [Serializable]
    public class GameConfigData
    {
        public string questionsUrl;
        
        // NOUVEAU SYSTÈME : Un seul fichier de dialogues
        public string dialoguesUrl;
        
        // ANCIEN SYSTÈME : Trois fichiers séparés (rétrocompatibilité)
        public string dialogueBeforeUrl;
        public string dialogueSuccessUrl;
        public string dialogueFailUrl;
    }
    
    [Serializable]
    public class GameConfigWrapper
    {
        public GameConfigData gameConfig;
    }

    void Awake()
    {
        Debug.Log("[GameLauncher] 🚀 Awake() appelé");
    }

    private void Start()
    {
        Debug.Log("[GameLauncher] 🚀 Start() appelé");
        // NOUVEAU : Charger d'abord la config, puis agir selon la phase
        StartCoroutine(LoadConfigAndExecutePhase());
    }
    
    private IEnumerator LoadConfigAndExecutePhase()
    {
        Debug.Log("[GameLauncher] ═══════════════════════════════════════");
        Debug.Log("[GameLauncher] 🔍 DIAGNOSTIC AU DÉMARRAGE");
        Debug.Log($"[GameLauncher] GameDataManager.Instance null: {GameDataManager.Instance == null}");
        if (GameDataManager.Instance != null)
        {
            Debug.Log($"[GameLauncher] GameDataManager.HasData: {GameDataManager.Instance.HasData}");
            Debug.Log($"[GameLauncher] GameDataManager.IsLoading: {GameDataManager.Instance.IsLoading}");
            if (GameDataManager.Instance.CurrentGameData != null)
            {
                Debug.Log($"[GameLauncher] CurrentGameData.background: {GameDataManager.Instance.CurrentGameData.background?.url}");
                Debug.Log($"[GameLauncher] CurrentGameData.questions: {GameDataManager.Instance.CurrentGameData.questions?.Length ?? 0}");
            }
        }
        Debug.Log("[GameLauncher] ═══════════════════════════════════════");
        
        string configUrl = PlayerPrefs.GetString("GameConfigUrl");
        string phase = PlayerPrefs.GetString("GamePhase", "Before");
        
        // NOUVEAU : Vérifier si des données API sont disponibles via GameDataManager
        if (GameDataManager.Instance != null && GameDataManager.Instance.HasData)
        {
            Debug.Log("[GameLauncher] ✅ Données API disponibles via GameDataManager - Utilisation des données de l'API");
            yield return StartCoroutine(ExecutePhaseWithApiData(phase));
            yield break;
        }
        
        Debug.Log("[GameLauncher] ⚠️ Pas de données API - Chargement depuis le fichier local");
        
        if (string.IsNullOrEmpty(configUrl))
        {
            Debug.LogError("[GameLauncher] Aucune URL de config trouvée dans PlayerPrefs");
            yield break;
        }
        
        // Charger le JSON de configuration du jeu
        using (var www = UnityWebRequest.Get(configUrl))
        {
            yield return www.SendWebRequest();
            
            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"[GameLauncher] Erreur chargement config: {www.error}");
                yield break;
            }
            
            GameConfigData config = null;
            try
            {
                var wrapper = JsonUtility.FromJson<GameConfigWrapper>(www.downloadHandler.text);
                config = wrapper.gameConfig;
            }
            catch (Exception e)
            {
                Debug.LogError($"[GameLauncher] Erreur parsing config: {e.Message}");
                yield break;
            }
            
            if (config == null)
            {
                Debug.LogError("[GameLauncher] Config est null après parsing");
                yield break;
            }
            
            // Charger les questions (commun aux deux systèmes)
            string questionsUrl = string.IsNullOrEmpty(config.questionsUrl) ? "" : 
                GeneralConfigManager.Instance.GetQuestionsUrl(config.questionsUrl);
            PlayerPrefs.SetString("QuestionsUrl", questionsUrl);
            
            // NOUVEAU SYSTÈME : Charger depuis un fichier de dialogues groupés
            if (!string.IsNullOrEmpty(config.dialoguesUrl))
            {
                yield return StartCoroutine(LoadGroupedDialogues(config.dialoguesUrl, phase));
            }
            // ANCIEN SYSTÈME : Rétrocompatibilité avec 3 fichiers séparés
            else
            {
                // Construire les URLs complètes via GeneralConfigManager
                string beforeUrl = string.IsNullOrEmpty(config.dialogueBeforeUrl) ? "" : 
                    GeneralConfigManager.Instance.GetDialogueUrl(config.dialogueBeforeUrl);
                string successUrl = string.IsNullOrEmpty(config.dialogueSuccessUrl) ? "" : 
                    GeneralConfigManager.Instance.GetDialogueUrl(config.dialogueSuccessUrl);
                string failUrl = string.IsNullOrEmpty(config.dialogueFailUrl) ? "" : 
                    GeneralConfigManager.Instance.GetDialogueUrl(config.dialogueFailUrl);
                
                // Stocker les URLs complètes de dialogue pour plus tard
                PlayerPrefs.SetString("DialogueBeforeUrl", beforeUrl);
                PlayerPrefs.SetString("DialogueSuccessUrl", successUrl);
                PlayerPrefs.SetString("DialogueFailUrl", failUrl);
                
                // Exécuter la phase appropriée
                switch (phase)
                {
                    case "Before":
                        StartBeforeDialogue(beforeUrl);
                        break;
                    case "Shooting":
                        StartGameBasedOnType();
                        break;
                    case "After":
                        StartAfterDialogue();
                        break;
                }
            }
        }
    }
    
    /// <summary>
    /// Exécute la phase de jeu en utilisant les données de l'API (GameDataManager)
    /// </summary>
    private IEnumerator ExecutePhaseWithApiData(string phase)
    {
        APIGameData gameData = GameDataManager.Instance.CurrentGameData;
        
        Debug.Log($"[GameLauncher] 📊 Données API:");
        Debug.Log($"[GameLauncher] - Background: {gameData.background?.type} - {gameData.background?.url}");
        Debug.Log($"[GameLauncher] - Questions: {gameData.questions?.Length ?? 0}");
        Debug.Log($"[GameLauncher] - Zones: {gameData.zones?.Length ?? 0}");
        Debug.Log($"[GameLauncher] - Dialogue Intro: {(gameData.dialogues?.intro != null ? "✅" : "❌")}");
        Debug.Log($"[GameLauncher] - Dialogue Success: {(gameData.dialogues?.success != null ? "✅" : "❌")}");
        Debug.Log($"[GameLauncher] - Dialogue Fail: {(gameData.dialogues?.fail != null ? "✅" : "❌")}");
        Debug.Log($"[GameLauncher] - Phase actuelle: {phase}");
        
        // Marquer qu'on utilise les données API (pour que GameManager le sache)
        PlayerPrefs.SetString("UseApiData", "true");
        PlayerPrefs.Save();
        
        switch (phase)
        {
            case "Before":
                if (gameData.dialogues?.intro != null && gameData.dialogues.intro.lines != null && gameData.dialogues.intro.lines.Length > 0)
                {
                    Debug.Log($"[GameLauncher] 🎬 Lancement du dialogue INTRO ({gameData.dialogues.intro.lines.Length} lignes)");
                    // TODO: Configurer SubtitleManager avec les données de dialogue
                    // Pour l'instant, on passe directement au jeu
                    PlayerPrefs.SetString("GamePhase", "Shooting");
                    GoToGameScene();
                }
                else
                {
                    Debug.Log("[GameLauncher] ⏭️ Pas de dialogue INTRO - Passage direct au jeu");
                    PlayerPrefs.SetString("GamePhase", "Shooting");
                    GoToGameScene();
                }
                break;
                
            case "Shooting":
                Debug.Log("[GameLauncher] 🎮 Lancement du jeu");
                StartGameBasedOnType();
                break;
                
            case "After":
                Debug.Log("[GameLauncher] 🎬 Phase AFTER");
                StartAfterDialogue();
                break;
        }
        
        yield break;
    }
    
    private void StartBeforeDialogue(string beforeUrl)
    {
        if (string.IsNullOrEmpty(beforeUrl))
        {
            PlayerPrefs.SetString("GamePhase", "Shooting");
            GoToGameScene();
            return;
        }
        
        // Configurer SubtitleManager avec le dialogue BEFORE
        ConfigureSubtitleManager(beforeUrl, () => {
            PlayerPrefs.SetString("GamePhase", "Shooting");
            GoToGameScene();
        });
    }

    private void GoToGameScene()
    {
        // Anti double-clic / anti course : ne lancer la transition qu'une seule fois
        if (_goToGameSceneInProgress)
        {
            Debug.LogWarning("[GameLauncher] ⚠️ GoToGameScene déjà en cours, appel ignoré");
            return;
        }
        _goToGameSceneInProgress = true;

        string levelType = PlayerPrefs.GetString("CurrentLevelType", "shooting");
        
        if (levelType.ToLowerInvariant() == "calculator")
        {
            SceneTransitionManager.LoadSceneWithTransition("calculator");
            StartFallbackTransition("calculator");
        }
        else if (levelType.ToLowerInvariant() == "trous")
        {
            SceneTransitionManager.LoadSceneWithTransition("trous");
            StartFallbackTransition("trous");
        }
        else
        {
            SceneTransitionManager.LoadSceneWithTransition("shooting");
            StartFallbackTransition("shooting");
        }
    }

    private bool _goToGameSceneInProgress = false;
    private Coroutine _fallbackTransitionCoroutine = null;

    private void StartFallbackTransition(string sceneName)
    {
        if (_fallbackTransitionCoroutine != null)
        {
            StopCoroutine(_fallbackTransitionCoroutine);
            _fallbackTransitionCoroutine = null;
        }
        _fallbackTransitionCoroutine = StartCoroutine(FallbackTransition(sceneName));
    }

    private IEnumerator FallbackTransition(string sceneName)
    {
        // Sur mobile, réduire le délai d'attente car les transitions peuvent être plus lentes
        #if UNITY_WEBGL && !UNITY_EDITOR
        float waitTime = 3f; // 3 secondes sur WebGL/mobile
        #else
        float waitTime = 2f; // 2 secondes sur desktop
        #endif
        
        yield return new WaitForSeconds(waitTime);
        
        string currentScene = SceneManager.GetActiveScene().name;

        // Si une transition est encore en cours, ne pas forcer un LoadScene direct (ça crée une course)
        if (SceneTransitionManager.IsTransitionInProgress)
        {
            Debug.LogWarning($"[GameLauncher] ⏳ Transition toujours en cours vers '{sceneName}', fallback annulé");
            yield break;
        }
        
        if (currentScene == sceneName)
        {
            yield break;
        }
        
        Debug.LogWarning($"[GameLauncher] ⚠️ Transition échouée (actuelle: {currentScene}, cible: {sceneName}), fallback vers chargement direct");
        
        // Vérifier que la scène existe avant de la charger
        bool sceneExists = false;
        for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++)
        {
            string scenePath = UnityEngine.SceneManagement.SceneUtility.GetScenePathByBuildIndex(i);
            string sceneNameInBuild = System.IO.Path.GetFileNameWithoutExtension(scenePath);
            if (sceneNameInBuild == sceneName)
            {
                sceneExists = true;
                break;
            }
        }
        
        if (sceneExists)
        {
            SceneManager.LoadScene(sceneName);
        }
        else
        {
            Debug.LogError($"[GameLauncher] ❌ La scène '{sceneName}' n'existe pas dans les Build Settings !");
        }
    }
    
    private void StartGameBasedOnType()
    {
        string levelType = PlayerPrefs.GetString("CurrentLevelType", "shooting");
        string configUrl = PlayerPrefs.GetString("GameConfigUrl");
        
        // Vérifier si on a des données API disponibles
        bool hasApiData = GameDataManager.Instance != null && GameDataManager.Instance.HasData;
        
        Debug.Log($"[GameLauncher] StartGameBasedOnType - Type: {levelType}, HasApiData: {hasApiData}");
        
        // Si on est dans la scène "Player", charger d'abord la bonne scène de jeu
        string currentScene = SceneManager.GetActiveScene().name;
        if (currentScene == "Player")
        {
            GoToGameScene();
            return;
        }
        
        if (levelType.ToLowerInvariant() == "trous")
        {
            // IMPORTANT : Vérifier qu'il n'y a pas de GameManager ou CalculatorGameManager qui s'active par erreur
            GameManager gm = FindFirstObjectByType<GameManager>();
            CalculatorGameManager cm = FindFirstObjectByType<CalculatorGameManager>();
            if (gm != null)
            {
                Debug.LogError($"❌ ERREUR : GameManager trouvé dans la scène 'trous' ! Il ne devrait pas être là.");
                Debug.LogError($"❌ Le GameManager '{gm.gameObject.name}' va créer des bandeaux et interférer avec TrousGameManager");
            }
            if (cm != null)
            {
                Debug.LogError($"❌ ERREUR : CalculatorGameManager trouvé dans la scène 'trous' ! Il ne devrait pas être là.");
            }
            
            // Chercher le TrousGameManager dans la scène
            TrousGameManager tm = FindFirstObjectByType<TrousGameManager>();
            if (tm != null)
            {
                // Si on a des données API, les utiliser
                if (hasApiData)
                {
                    Debug.Log("[GameLauncher] ✅ Utilisation des données API pour TrousGameManager");
                    tm.LoadGameFromApiData(GameDataManager.Instance.CurrentGameData);
                }
                else
                {
                    tm.LoadGameFromURL(configUrl);
                }
            }
            else
            {
                Debug.LogError($"❌ TrousGameManager introuvable dans la scène '{SceneManager.GetActiveScene().name}'");
                Debug.LogError("⚠️ La scène 'trous' est vide !");
                Debug.LogError("👉 Générer la scène avec : Tools → Trous Scene → Generate Scene");
                Debug.LogError("👉 Puis sauvegarder la scène avec Ctrl+S");
                
                // NE PAS utiliser GameManager comme fallback pour "trous" - c'est une erreur
                Debug.LogError("❌ Pas de fallback vers GameManager pour le type 'trous'");
            }
        }
        else if (levelType.ToLowerInvariant() == "shooting")
        {
            GameManager gm = FindFirstObjectByType<GameManager>();
            if (gm != null)
            {
                // Appliquer la config dialogue globale depuis LevelManager
                DialogueConfig globalConfig = LevelManager.Instance?.GetDialogueConfig();
                if (globalConfig != null)
                {
                    gm.SetGlobalDialogueDefaults("", "", globalConfig);
                }
                
                // Si on a des données API, les utiliser
                if (hasApiData)
                {
                    Debug.Log("[GameLauncher] ✅ Utilisation des données API pour GameManager (shooting)");
                    gm.LoadGameFromApiData(GameDataManager.Instance.CurrentGameData);
                }
                else
                {
                    gm.LoadGameFromURL(configUrl);
                }
            }
            else
            {
                Debug.LogError("[GameLauncher] GameManager introuvable dans la scène shooting");
            }
        }
        else if (levelType.ToLowerInvariant() == "calculator")
        {
            CalculatorGameManager cm = FindFirstObjectByType<CalculatorGameManager>();
            if (cm != null)
            {
                // Si on a des données API, les utiliser
                if (hasApiData)
                {
                    Debug.Log("[GameLauncher] ✅ Utilisation des données API pour CalculatorGameManager");
                    cm.LoadGameFromApiData(GameDataManager.Instance.CurrentGameData);
                }
                else
                {
                    cm.LoadGameFromURL(configUrl);
                }
            }
            else
            {
                Debug.LogError("[GameLauncher] CalculatorGameManager introuvable dans la scène calculator");
                
                // Essayer de trouver un GameManager normal comme fallback
                GameManager gm = FindFirstObjectByType<GameManager>();
                if (gm != null)
                {
                    Debug.LogWarning("[GameLauncher] Utilisation du GameManager normal comme fallback");
                    if (hasApiData)
                    {
                        gm.LoadGameFromApiData(GameDataManager.Instance.CurrentGameData);
                    }
                    else
                    {
                        gm.LoadGameFromURL(configUrl);
                    }
                }
            }
        }
        else
        {
            Debug.LogError($"[GameLauncher] Type de jeu inconnu: '{levelType}'");
        }
    }
    
    private void StartAfterDialogue()
    {
        // Vérifier si on utilise le nouveau système (dialogues groupés) ou l'ancien
        string dialogueSystemType = PlayerPrefs.GetString("DialogueSystemType", "");
        string lastGameResult = PlayerPrefs.GetString("LastGameResult", "fail"); // "success" ou "fail"
        
        if (dialogueSystemType == "grouped")
        {
            // NOUVEAU SYSTÈME : Utiliser les dialogues groupés stockés dans PlayerPrefs
            string dialogueJson = lastGameResult == "success" 
                ? PlayerPrefs.GetString("DialogueSuccessJson", "") 
                : PlayerPrefs.GetString("DialogueFailJson", "");
            
            if (!string.IsNullOrEmpty(dialogueJson))
            {
                try
                {
                    // Parser le JSON stocké
                    var wrapper = JsonUtility.FromJson<DialogueWrapper>(dialogueJson);
                    if (wrapper != null && wrapper.dialogue != null)
                    {
                        ConfigureSubtitleManagerWithContent(wrapper.dialogue, () => {
                            ReturnToOriginScene();
                        });
                        return;
                    }
                }
                catch (Exception e)
                {
                    Debug.LogError($"[GameLauncher] Erreur parsing dialogue groupé: {e.Message}");
                }
            }
            else
            {
                Debug.LogWarning($"[GameLauncher] Dialogue groupé ({lastGameResult}) non trouvé dans PlayerPrefs");
            }
        }
        
        // ANCIEN SYSTÈME : Utiliser NextDialogueUrl
        string afterUrl = PlayerPrefs.GetString("NextDialogueUrl");
        
        if (!string.IsNullOrEmpty(afterUrl))
        {
            ConfigureSubtitleManager(afterUrl, () => {
                ReturnToOriginScene();
            });
        }
        else
        {
            ReturnToOriginScene();
        }
    }
    
    // Classe wrapper pour parser le JSON de dialogue stocké
    [Serializable]
    private class DialogueWrapper
    {
        public DialogueContent dialogue;
    }
    
    private void ReturnToOriginScene()
    {
        // Récupérer la scène d'origine (Menu ou Map)
        string returnToScene = PlayerPrefs.GetString("ReturnToScene", "menu");
        
        // Si on retourne à la Map, utiliser le LevelManager pour gérer le système de steps
        if (returnToScene.ToLower() == "map")
        {
            LevelManager levelManager = FindFirstObjectByType<LevelManager>();
            if (levelManager != null)
            {
                levelManager.ReturnToMap();
            }
            else
            {
                // Fallback : charger directement la scène Map
                SceneManager.LoadScene("Map");
            }
        }
        else
        {
            // Retour au menu ou autre scène
            SceneManager.LoadScene(returnToScene);
        }
    }
    
    private IEnumerator LoadGroupedDialogues(string dialoguesFileName, string phase)
    {
        // Construire l'URL complète
        string dialoguesUrl = GeneralConfigManager.Instance.GetDialogueUrl(dialoguesFileName);
        
        using (UnityWebRequest www = UnityWebRequest.Get(dialoguesUrl))
        {
            yield return www.SendWebRequest();
            
            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"[GameLauncher] Erreur chargement dialogues groupés: {www.error}");
                // Fallback : continuer sans dialogues
                PlayerPrefs.SetString("DialogueBeforeUrl", "");
                PlayerPrefs.SetString("DialogueSuccessUrl", "");
                PlayerPrefs.SetString("DialogueFailUrl", "");
                
                if (phase == "Shooting")
                {
                    StartGameBasedOnType();
                }
                yield break;
            }
            
            try
            {
                // Parser le fichier de dialogues groupés
                DialoguesData dialoguesData = JsonUtility.FromJson<DialoguesData>(www.downloadHandler.text);
                
                // Stocker les dialogues en JSON dans PlayerPrefs pour utilisation ultérieure
                if (dialoguesData.dialogues.intro != null)
                {
                    string introJson = JsonUtility.ToJson(new { dialogue = dialoguesData.dialogues.intro });
                    PlayerPrefs.SetString("DialogueIntroJson", introJson);
                }
                
                if (dialoguesData.dialogues.success != null)
                {
                    string successJson = JsonUtility.ToJson(new { dialogue = dialoguesData.dialogues.success });
                    PlayerPrefs.SetString("DialogueSuccessJson", successJson);
                }
                
                if (dialoguesData.dialogues.fail != null)
                {
                    string failJson = JsonUtility.ToJson(new { dialogue = dialoguesData.dialogues.fail });
                    PlayerPrefs.SetString("DialogueFailJson", failJson);
                }
                
                // Marquer qu'on utilise le nouveau système
                PlayerPrefs.SetString("DialogueSystemType", "grouped");
                
                // Exécuter la phase appropriée
                switch (phase)
                {
                    case "Before":
                        StartBeforeDialogueFromJson(dialoguesData.dialogues.intro);
                        break;
                    case "Shooting":
                    case "Game": // Alias pour rétrocompatibilité
                        StartGameBasedOnType();
                        break;
                    case "After":
                        StartAfterDialogue();
                        break;
                }
            }
            catch (Exception e)
            {
                Debug.LogError($"[GameLauncher] Erreur parsing dialogues groupés: {e.Message}");
            }
        }
    }
    
    private void StartBeforeDialogueFromJson(DialogueContent dialogueContent)
    {
        if (dialogueContent == null || dialogueContent.lines == null || dialogueContent.lines.Count == 0)
        {
            PlayerPrefs.SetString("GamePhase", "Shooting");
            GoToGameScene();
            return;
        }
        
        // Configurer SubtitleManager avec le dialogue
        ConfigureSubtitleManagerWithContent(dialogueContent, () => {
            PlayerPrefs.SetString("GamePhase", "Shooting");
            GoToGameScene();
        });
    }
    
    private void ConfigureSubtitleManagerWithContent(DialogueContent dialogueContent, System.Action onComplete)
    {
        SubtitleManager subtitleManager = FindFirstObjectByType<SubtitleManager>();
        if (subtitleManager != null)
        {
            subtitleManager.OnDialogueComplete = onComplete;
            
            // Appliquer la config de dialogue globale si disponible
            if (LevelManager.Instance != null)
            {
                DialogueConfig globalConfig = LevelManager.Instance.GetDialogueConfig();
                if (globalConfig != null)
                {
                    subtitleManager.ApplyDialogueConfig(globalConfig);
                }
            }
            
            // TODO: Adapter SubtitleManager pour accepter DialogueContent directement
            // Pour l'instant, on continue d'utiliser LoadDialogueFromUrl avec le JSON stocké
            string dialogueJson = PlayerPrefs.GetString("DialogueIntroJson");
            if (!string.IsNullOrEmpty(dialogueJson))
            {
                subtitleManager.LoadDialogueFromJson(dialogueJson);
            }
        }
        else
        {
            Debug.LogError("[GameLauncher] SubtitleManager introuvable dans la scène Player");
            onComplete?.Invoke();
        }
    }
    
    private void ConfigureSubtitleManager(string dialogueUrl, System.Action onComplete)
    {
        SubtitleManager subtitleManager = FindFirstObjectByType<SubtitleManager>();
        if (subtitleManager != null)
        {
            subtitleManager.OnDialogueComplete = onComplete;
            
            // Appliquer la config de dialogue globale si disponible
            if (LevelManager.Instance != null)
            {
                DialogueConfig globalConfig = LevelManager.Instance.GetDialogueConfig();
                if (globalConfig != null)
                {
                    subtitleManager.ApplyDialogueConfig(globalConfig);
                }
            }
            
            subtitleManager.LoadDialogueFromUrl(dialogueUrl);
        }
        else
        {
            Debug.LogError("[GameLauncher] SubtitleManager introuvable dans la scène Player");
            onComplete?.Invoke();
        }
    }
}