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

/// <summary>
/// Configuration complète du jeu de tir QCM 2D avec support du pistolet, contraintes, messages de feedback et UI
/// Structure mise à jour pour supporter la séparation des questions
/// </summary>

// NOUVELLES CLASSES POUR LA STRUCTURE JSON SÉPARÉE
[System.Serializable]
public class GameConfigWrapper
{
    public GameConfigData gameConfig;
}

[System.Serializable]
public class QuestionsWrapper
{
    public SuccessConfig successConfig;
    public Question[] questions;
}

// Classes pour parser la réponse de l'API (format snake_case)
[System.Serializable]
public class APIQuestionsResponse
{
    public string status;
    public string message;
    public APIQuestionData[] data;
}

[System.Serializable]
public class APIQuestionData
{
    public int id;
    public string question;
    public APIAnswerData[] answers;
    public string explanation;
}

[System.Serializable]
public class APIAnswerData
{
    public int id;            // ID de l'option de réponse pour l'API answers
    public string text;
    public bool is_correct;  // snake_case depuis l'API
    public string zoneId;
}

// Classes pour parser la réponse API des questions trous
[System.Serializable]
public class APITrousQuestionsResponse
{
    public string status;
    public string message;
    public APITrousQuestionData[] data;
}

[System.Serializable]
public class APITrousQuestionData
{
    public int id;
    public string text;
    public APITrousHoleData[] holes;
    public string explanation;
}

[System.Serializable]
public class APITrousHoleData
{
    public int id;
    public string keyword;
    public int correctAnswer;              // ID de la bonne réponse
    public APIHoleOptionData[] options;    // Options avec IDs {id, content}
}

[System.Serializable]
public class SuccessConfig
{
    public int minCorrectAnswers = 1;
    public int minCorrectPercentage = 50;
    public bool usePercentage = false;
    public string description = "Configuration de réussite par défaut";
}

// CLASSE PRINCIPALE MISE À JOUR
[System.Serializable]
public class GameConfig
{
    public GameConfigData gameConfig;
}

[System.Serializable]
public class GameConfigData
{
    [Header("URLs")]
    public string questionsUrl; // Nouveau champ pour l'URL des questions

    [Header("Configuration de base")]
    public Resolution resolution;
    public Background background;
    public GameAssets assets;
    public Sounds sounds;

    [Header("Configuration du jeu")]
    public GunConfig gunConfig;
    public CrosshairConfig crosshairConfig;
    public FeedbackMessagesConfig feedbackMessages = new FeedbackMessagesConfig();
    public UIConfig uiConfig = new UIConfig();

    [Header("Zones cibles")]
    public List<TargetZoneData> targetZones; // Legacy - pour rétrocompatibilité
    public ZoneTemplates zoneTemplates;      // Nouveau système flexible

    [Header("Compatibilité")]
    public Vector2 gunSize = new Vector2(120f, 80f); // Garde pour compatibilité
}

[System.Serializable]
public class Resolution
{
    public int width;
    public int height;
}

[System.Serializable]
public class Background
{
    public string videoUrl;
    public string imageUrl;
    public string type = "video"; // "video" ou "image"
}

[System.Serializable]
public class GameAssets
{
    public string impact;
    public string ledOff;
    public string ledGreen;
    public string ledRed;
    public string crosshair;
    public string gun;
    public string projectile;
    public ImpactEffect impactEffect; // Nouveau système

}

[System.Serializable]
public class Sounds
{
    public string impact;
    public string success;
    public string fail;
    public string shoot;
}

[System.Serializable]
public class GunConfig
{
    public Vector2 offsetFromCursor = new Vector2(-50f, -30f);
    public float size = 100f;
    public Vector2 gunSize = new Vector2(120f, 80f);
    public bool flipHorizontally = false;
    public bool enableRotation = false;
    public float rotationOffset = 0f;
    public bool alwaysVisible = true;
    public float fadeSpeed = 5f;
    public bool hideDuringFeedback = true;

    public GunBoundaryConfig boundary = new GunBoundaryConfig();
}

[System.Serializable]
public class UIBandsConfig
{
    [Header("Bandes d'interface")]
    public bool showBands = true;
    public float bandHeight = 100f;
    public string bandColor = "#64477f";
    public float bandAlpha = 1f;
    public int sortingOrder = 5;
}

[System.Serializable]
public class QuestionDisplayConfig
{
    [Header("Configuration de l'affichage des questions")]
    public float fontSize = 36f;
    public string fontColor = "#FFFFFF";
    public bool fontBold = true;
    public TextAlignmentOptions alignment = TextAlignmentOptions.Center;
    public float marginTop = 20f;
    public float marginLeft = 300f;
    public float marginRight = 50f;
    public int sortingOrder = 12;

    [Header("Position personnalisée")]
    public bool useCustomPosition = false;
    public Vector2 customPosition = new Vector2(0f, -50f);

    [Header("Responsive")]
    public bool adaptToScreenSize = true;
    public float minFontSize = 24f;
    public float maxFontSize = 48f;
    
    [Header("Animation")]
    public WordAnimationConfig wordAnimation;
}

[System.Serializable]
public class WordAnimationConfig
{
    public bool enabled = false;
    public float delayBetweenWords = 0.1f;
}

[System.Serializable]
public class LEDConfig
{
    [Header("Taille et espacement des LEDs")]
    public float ledSize = 40f;
    public float ledSpacing = 50f;

    [Header("Position dans le bandeau")]
    public float marginLeft = 30f;
    public float verticalOffset = 0f;

    [Header("Style des LEDs")]
    public bool useCustomSprites = true;
    public Color defaultOffColor = new Color(0.5f, 0.5f, 0.5f, 1f);
    public Color defaultGreenColor = Color.green;
    public Color defaultRedColor = Color.red;

    [Header("Animation (optionnel)")]
    public bool enableLEDAnimation = false;
    public float animationSpeed = 1f;
    public AnimationType animationType = AnimationType.None;
}

[System.Serializable]
public enum AnimationType
{
    None,
    Fade,
    Scale,
    Pulse
}

[System.Serializable]
public class GunBoundaryConfig
{
    public bool enableBoundaryConstraints = true;
    public bool useAutomaticMargins = true;
    public float minX = 100f;
    public float maxX = 1820f;
    public float minY = 100f;
    public float maxY = 980f;
    public float marginLeft = 0f;
    public float marginRight = 0f;
    public float marginTop = 0f;
    public float marginBottom = 0f;

    public Rect GetConstrainedRect(Vector2 gunSize, Vector2 screenSize)
    {
        if (!enableBoundaryConstraints)
        {
            return new Rect(0, 0, screenSize.x, screenSize.y);
        }

        if (useAutomaticMargins)
        {
            float halfWidth = gunSize.x * 0.5f;
            float halfHeight = gunSize.y * 0.5f;

            float finalMinX = halfWidth + marginLeft;
            float finalMinY = halfHeight + marginBottom;
            float finalMaxX = screenSize.x - halfWidth - marginRight;
            float finalMaxY = screenSize.y - halfHeight - marginTop;

            return new Rect(
                finalMinX,
                finalMinY,
                finalMaxX - finalMinX,
                finalMaxY - finalMinY
            );
        }
        else
        {
            float finalMinX = minX + marginLeft;
            float finalMinY = minY + marginBottom;
            float finalMaxX = maxX - marginRight;
            float finalMaxY = maxY - marginTop;

            if (finalMaxX <= finalMinX) finalMaxX = finalMinX + 100f;
            if (finalMaxY <= finalMinY) finalMaxY = finalMinY + 100f;

            return new Rect(
                finalMinX,
                finalMinY,
                finalMaxX - finalMinX,
                finalMaxY - finalMinY
            );
        }
    }
}

[System.Serializable]
public class FeedbackMessagesConfig
{
    public float feedbackDisplayDelay = 0f; // Délai en secondes avant d'afficher le feedback (0 = utiliser default)
    public string correctAnswerMessage = "BONNE RÉPONSE";
    public string incorrectAnswerMessage = "MAUVAISE RÉPONSE";

    public bool showResultMessage = true;
    public bool resultMessageInBold = true;
    public string resultMessageColor = "#00FF00";
    public string incorrectMessageColor = "#FF0000";
    public float resultMessageSize = 32f;
    public string resultMessageFont = ""; // Police pour les messages (ex: "Anton SDF")
    public float resultMessagePositionY = 0f; // Position verticale du titre (depuis le haut du panel, en pixels)

    public string separator = "\n\n";
    public bool showSeparatorLine = false;

    public bool changeBackgroundColor = false;
    public string correctBackgroundColor = "#E8F5E8";
    public string incorrectBackgroundColor = "#F5E8E8";

    [Header("Images de fond du feedback")]
    public bool useBackgroundImage = false;
    public string successBackgroundImageUrl = "";
    public string failureBackgroundImageUrl = "";
    public float backgroundImageAlpha = 1.0f;
    public bool stretchToFitPanel = true;

    [Header("Centrage du texte")]
    public bool centerTextInPanel = true;

    [Header("Configuration du panneau")]
    public Vector2 panelSize = new Vector2(800f, 400f);
    public bool useCustomPanelSize = false;
    public string panelStyle = ""; // Style de panel depuis panelStyles (ex: "feedbackPanel")

    [Header("Style du texte d'explication")]
    public string explanationTextColor = "#FFFFFF";
    public float explanationTextSize = 24f;
    public bool explanationTextBold = false;
    public float explanationTextPaddingLeft = 20f;
    public float explanationTextPaddingRight = 20f;
    public float explanationTextPositionY = 0f; // Position verticale du texte d'explication (offset depuis le titre, en pixels)
    
    [Header("Texte d'instructions")]
    public string feedbackInstructionsText = "Cliquez pour continuer";
    public float feedbackInstructionsTextSize = 18;
    public string feedbackInstructionsTextColor = "#808080";

    [Header("Boutons de feedback (shooting)")]
    public string feedbackNextButtonText = "Question suivante";
    public string feedbackLastButtonText = "Fermer";
    public string feedbackButtonBackgroundColor = "#268CE6"; // bleu par défaut
    public string feedbackButtonStyle; // Nom du style de bouton à utiliser (ex: "validationPurple")
}

[System.Serializable]
public class UIConfig
{
    [Header("Configuration du texte de survol")]
    public float hoverTextSize = 24f;
    public string hoverTextColor = "#FFFFFF";
    public bool hoverTextBold = false;

    [Header("Configuration du panneau de survol")]
    public HoverPanelSize hoverPanelSize = new HoverPanelSize();
    public string hoverBackgroundColor = "#000000";
    public float hoverBackgroundAlpha = 0.9f;

    [Header("Position du panneau")]
    public bool useCustomPosition = false;
    public Vector2 customPosition = new Vector2(0f, 15f);
    public bool useCenteredHoverPanel = false;

    [Header("Panneau centré (hover shooting)")]
    public float centeredHoverPaddingX = 40f;
    public float centeredHoverPaddingY = 20f;
    public float centeredHoverAlpha    = 0.9f;

    [Header("Bandes d'interface")]
    public UIBandsConfig bands = new UIBandsConfig();

    [Header("Configuration des LEDs")]
    public LEDConfig ledConfig = new LEDConfig();

    [Header("Configuration des questions")]
    public QuestionDisplayConfig questionDisplay = new QuestionDisplayConfig();
}

[System.Serializable]
public class HoverPanelSize
{
    public float width = 500f;
    public float height = 50f;

    public Vector2 ToVector2()
    {
        return new Vector2(width, height);
    }
}

[System.Serializable]
public class TargetZoneData
{
    public string id;
    public int x;
    public int y;
    public int width;
    public int height;
}

[System.Serializable]
public class CrosshairConfig
{
    // Propriétés existantes (ne pas modifier)
    public float defaultSize = 50f;
    public float minSize = 20f;
    public float maxSize = 100f;
    public bool allowPlayerResize = false;

    // NOUVELLES PROPRIÉTÉS pour le double état
    public bool alwaysShowCrosshair = true;
    public float onTargetSizeMultiplier = 1.0f;
    public float offTargetSizeMultiplier = 0.5f;
    public float onTargetAlpha = 1.0f;
    public float offTargetAlpha = 0.6f;
    public float sizeTransitionSpeed = 15f;
    public float alphaTransitionSpeed = 10f;
    public bool smoothTransitions = true;
}

// NOUVELLES CLASSES POUR LE SYSTÈME FLEXIBLE
[System.Serializable]
public class ZoneTemplates
{
    public List<TargetZoneData> twoChoices;
    public List<TargetZoneData> threeChoices;
    public List<TargetZoneData> fourChoices;
}

[System.Serializable]
public class Question
{
    public int id;
    public string question;
    public List<Answer> answers;
    public string explanation;
    public int points;
    public int answerCount;   // Nouveau : nombre de réponses
}

[System.Serializable]
public class Answer
{
    public int id;            // ID de l'option de réponse pour l'API answers
    public string text;
    public bool isCorrect;
    public string zoneId;     // Legacy pour rétrocompatibilité
    public int choiceIndex;   // Nouveau : index dans le template
}

[System.Serializable]
public class Zone
{
    public int x;
    public int y;
    public int width;
    public int height;

    public bool ContainsPoint(Vector2 point)
    {
        return point.x >= x &&
               point.x <= x + width &&
               point.y >= y &&
               point.y <= y + height;
    }

    public Vector2 GetCenter()
    {
        return new Vector2(x + width / 2f, y + height / 2f);
    }

    public override string ToString()
    {
        return $"Zone(x:{x}, y:{y}, w:{width}, h:{height})";
    }
}

[System.Serializable]
public class LevelInfo
{
    public string id;
    public string name;
    public string description;
    public int difficulty;
    public string category;
    public string jsonUrl;
    public string thumbnail;
}

[System.Serializable]
public class LevelData
{
    // Champ principal pour JsonUtility (correspond au JSON)
    public string id;

    // Alias pour compatibilité (pointe vers id)
    public string levelId { get { return id; } set { id = value; } }

    public string levelName;
    public string title;
    public string type;     // "shooting" / "calculator"
    public string questId;  // "quete01", etc.
    public bool isEnabled = true;

    // URLs de configuration
    public string configUrl;
    public string dialogueBeforeUrl;
    public string dialogueSuccessUrl;
    public string dialogueFailUrl;
    public string thumbnailUrl;

    // Champs hérités (compatibilité)
    public string sceneName;
    public string description;
    public int difficultyLevel;

    // Exigences de déverrouillage
    public UnlockRequirements unlockRequirements;

    public string returnToMapId = GeneralConfigManager.Instance != null ? 
        GeneralConfigManager.Instance.GetDefaultMapId() : "map_Q0J1"; // NOUVEAU
}

[System.Serializable]
public class UnlockRequirements
{
    public List<string> requiredLevels;
    public int minimumScore;
    public bool requireAllPreviousLevels;
}

[System.Serializable]
public class LevelsIndex
{
    public List<LevelInfo> levels;
}


[System.Serializable]
public class ImpactEffect
{
    public string type = "static"; // "static" ou "animated"
    public List<string> frames;
    public float frameRate = 12f;
    public float duration = 0.5f;

    // NOUVELLES PROPRIÉTÉS À AJOUTER :
    public float scale = 1f;        // Multiplicateur de taille
    public float width = 0f;        // Taille fixe en pixels (optionnel)
    public float height = 0f;       // Taille fixe en pixels (optionnel)
}



[System.Serializable]
public class AnswerWithZone : Answer
{
    public Zone zone;

    public static AnswerWithZone CreateFrom(Answer answer, TargetZoneData zoneData)
    {
        return new AnswerWithZone
        {
            id = answer.id,  // ID de l'option pour l'API answers
            text = answer.text,
            isCorrect = answer.isCorrect,
            zoneId = answer.zoneId,
            choiceIndex = answer.choiceIndex,
            zone = new Zone
            {
                x = zoneData.x,
                y = zoneData.y,
                width = zoneData.width,
                height = zoneData.height
            }
        };
    }

    public bool IsPointInZone(Vector2 screenPoint)
    {
        if (zone == null) return false;
        return zone.ContainsPoint(screenPoint);
    }

    public string GetDebugInfo()
    {
        string correctness = isCorrect ? "✅ CORRECTE" : "❌ INCORRECTE";
        string zoneInfo = zone != null ? zone.ToString() : "Zone NULL";
        return $"'{text}' [{correctness}] - {zoneInfo} - ID:{zoneId}";
    }
}

// CLASSE UTILITAIRES MISE À JOUR
public static class GameConfigUtils
{
    // NOUVELLES MÉTHODES POUR LA VALIDATION AVEC QUESTIONS SÉPARÉES
    public static bool ValidateGameConfig(GameConfigData configData)
    {
        if (configData == null) return false;
        if (string.IsNullOrEmpty(configData.questionsUrl)) return false;

        // Vérifier qu'on a soit targetZones (legacy) soit zoneTemplates (nouveau)
        bool hasLegacyZones = configData.targetZones != null && configData.targetZones.Count > 0;
        bool hasZoneTemplates = configData.zoneTemplates != null;

        return hasLegacyZones || hasZoneTemplates;
    }

    public static bool ValidateQuestions(List<Question> questions)
    {
        if (questions == null || questions.Count == 0) return false;

        foreach (var question in questions)
        {
            if (question.answers == null || question.answers.Count == 0) return false;

            bool hasCorrectAnswer = false;
            foreach (var answer in question.answers)
            {
                if (answer.isCorrect) hasCorrectAnswer = true;

                // Vérifier qu'on a soit zoneId (legacy) soit choiceIndex (nouveau)
                bool hasZoneId = !string.IsNullOrEmpty(answer.zoneId);
                bool hasChoiceIndex = answer.choiceIndex >= 0;

                if (!hasZoneId && !hasChoiceIndex) return false;
            }

            if (!hasCorrectAnswer) return false;
        }

        return true;
    }

    // MÉTHODES MISES À JOUR POUR LA NOUVELLE STRUCTURE
    public static bool ValidateCompleteGameData(GameConfigData configData, List<Question> questions)
    {
        return ValidateGameConfig(configData) && ValidateQuestions(questions);
    }

    public static TargetZoneData FindZoneById(GameConfigData configData, string zoneId)
    {
        if (configData?.targetZones == null) return null;

        foreach (var zone in configData.targetZones)
        {
            if (zone.id == zoneId) return zone;
        }

        return null;
    }

    public static int GetTotalQuestions(List<Question> questions)
    {
        return questions?.Count ?? 0;
    }

    public static int GetMaxPossibleScore(List<Question> questions)
    {
        if (questions == null) return 0;

        int maxScore = 0;
        foreach (var question in questions)
        {
            maxScore += question.points;
        }

        return maxScore;
    }

    public static float GetResponsiveFontSize(QuestionDisplayConfig config)
    {
        if (config == null || !config.adaptToScreenSize)
        {
            return config?.fontSize ?? 36f;
        }

        float screenRatio = Screen.width / 1920f;
        float calculatedSize = config.fontSize * screenRatio;

        return Mathf.Clamp(calculatedSize, config.minFontSize, config.maxFontSize);
    }

    public static float GetResponsiveLEDSize(LEDConfig config)
    {
        if (config == null) return 40f;

        float screenRatio = Mathf.Min(Screen.width / 1920f, Screen.height / 1080f);
        return config.ledSize * screenRatio;
    }

    // MÉTHODES DE DEBUG MISES À JOUR
    public static void DebugGameConfigData(GameConfigData configData)
    {
        if (configData == null)
        {
            Debug.LogError("GameConfigData est null !");
            return;
        }

        Debug.Log("=== DEBUG GAMECONFIG DATA ===");
        Debug.Log($"URL des questions: {configData.questionsUrl}");
        Debug.Log($"Résolution: {configData.resolution.width}x{configData.resolution.height}");
        Debug.Log($"Zones legacy définies: {configData.targetZones?.Count ?? 0}");
        Debug.Log($"Zone templates définies: {configData.zoneTemplates != null}");
        Debug.Log($"Config valide: {ValidateGameConfig(configData)}");

        if (configData.gunConfig != null)
        {
            var gun = configData.gunConfig;
            Debug.Log($"Config pistolet: Offset={gun.offsetFromCursor}, Size={gun.size}");
            Debug.Log($"Contraintes: Activées={gun.boundary.enableBoundaryConstraints}");
        }

        if (configData.targetZones != null)
        {
            foreach (var zone in configData.targetZones)
            {
                Debug.Log($"Zone {zone.id}: ({zone.x},{zone.y},{zone.width},{zone.height})");
            }
        }

        Debug.Log("=== FIN DEBUG GAMECONFIG DATA ===");
    }

    public static void DebugQuestions(List<Question> questions)
    {
        if (questions == null)
        {
            Debug.LogError("Questions list est null !");
            return;
        }

        Debug.Log("=== DEBUG QUESTIONS ===");
        Debug.Log($"Questions totales: {GetTotalQuestions(questions)}");
        Debug.Log($"Score maximum: {GetMaxPossibleScore(questions)}");
        Debug.Log($"Questions valides: {ValidateQuestions(questions)}");

        for (int i = 0; i < questions.Count; i++)
        {
            var q = questions[i];
            Debug.Log($"Q{i + 1}: '{q.question}' - {q.points} pts - {q.answers?.Count ?? 0} réponses - answerCount: {q.answerCount}");
        }

        Debug.Log("=== FIN DEBUG QUESTIONS ===");
    }

    // NOUVELLE MÉTHODE POUR DEBUG COMPLET
    public static void DebugCompleteGameData(GameConfigData configData, List<Question> questions)
    {
        DebugGameConfigData(configData);
        DebugQuestions(questions);

        Debug.Log("=== VALIDATION COMPLÈTE ===");
        Debug.Log($"Système complet valide: {ValidateCompleteGameData(configData, questions)}");
        Debug.Log("=== FIN VALIDATION COMPLÈTE ===");
    }

    // MÉTHODES EXISTANTES MAINTENUES POUR COMPATIBILITÉ
    public static string BuildFeedbackMessage(GameConfigData configData, bool wasCorrect, string explanation)
    {
        var feedbackConfig = configData.feedbackMessages;

        if (feedbackConfig == null || !feedbackConfig.showResultMessage)
        {
            return explanation;
        }

        string resultMessage = wasCorrect
            ? feedbackConfig.correctAnswerMessage
            : feedbackConfig.incorrectAnswerMessage;

        if (feedbackConfig.resultMessageInBold)
        {
            resultMessage = $"<b>{resultMessage}</b>";
        }

        string messageColor = wasCorrect
            ? feedbackConfig.resultMessageColor
            : feedbackConfig.incorrectMessageColor;

        if (!string.IsNullOrEmpty(messageColor))
        {
            resultMessage = $"<color={messageColor}>{resultMessage}</color>";
        }

        if (feedbackConfig.resultMessageSize > 0)
        {
            resultMessage = $"<size={feedbackConfig.resultMessageSize}>{resultMessage}</size>";
        }

        // Appliquer la police personnalisée si configurée
        if (!string.IsNullOrEmpty(feedbackConfig.resultMessageFont))
        {
            resultMessage = $"<font=\"{feedbackConfig.resultMessageFont}\">{resultMessage}</font>";
        }

        string separator = feedbackConfig.separator;

        if (feedbackConfig.showSeparatorLine)
        {
            separator += "────────────────\n";
        }

        // Appliquer le style à l'explication depuis defaultFeedbackMessages
        string explanationStyled = explanation;
        var defaultFeedback = GeneralConfigManager.Instance?.GetDefaultFeedbackMessages();
        
        if (defaultFeedback != null && !string.IsNullOrEmpty(explanation))
        {
            float explanationSize = defaultFeedback.explanationTextSize;
            string explanationColor = defaultFeedback.explanationTextColor;
            string explanationFont = defaultFeedback.explanationTextFont;
            bool explanationBold = defaultFeedback.explanationTextBold;
            
            // Construire le style de l'explication (sans balise font)
            // TextMeshPro applique la police par défaut, on ne peut pas changer la police via rich text
            if (explanationBold)
            {
                explanationStyled = $"<b>{explanation}</b>";
            }
            
            if (!string.IsNullOrEmpty(explanationColor))
            {
                explanationStyled = $"<color={explanationColor}>{explanationStyled}</color>";
            }
            
            if (explanationSize > 0)
            {
                explanationStyled = $"<size={explanationSize}>{explanationStyled}</size>";
            }
        }

        return resultMessage + separator + explanationStyled;
    }

    public static Color GetFeedbackBackgroundColor(GameConfigData configData, bool wasCorrect)
    {
        var feedbackConfig = configData.feedbackMessages;

        if (feedbackConfig == null || !feedbackConfig.changeBackgroundColor)
        {
            return Color.white;
        }

        string colorHex = wasCorrect
            ? feedbackConfig.correctBackgroundColor
            : feedbackConfig.incorrectBackgroundColor;

        if (ColorUtility.TryParseHtmlString(colorHex, out Color color))
        {
            return color;
        }

        return wasCorrect ? new Color(0.9f, 1f, 0.9f, 1f) : new Color(1f, 0.9f, 0.9f, 1f);
    }

    public static void ApplyUIConfigToHover(GameConfigData configData, TMPro.TextMeshProUGUI hoverText, RectTransform hoverPanel, UnityEngine.UI.Image hoverBackground)
    {
        if (configData?.uiConfig == null) return;

        var uiConfig = configData.uiConfig;

        if (hoverText != null)
        {
            hoverText.fontSize = uiConfig.hoverTextSize;

            if (ColorUtility.TryParseHtmlString(uiConfig.hoverTextColor, out Color textColor))
            {
                hoverText.color = textColor;
            }

            hoverText.fontStyle = uiConfig.hoverTextBold ? TMPro.FontStyles.Bold : TMPro.FontStyles.Normal;
        }

        if (hoverPanel != null)
        {
            hoverPanel.sizeDelta = uiConfig.hoverPanelSize.ToVector2();
        }

        if (hoverBackground != null)
        {
            if (ColorUtility.TryParseHtmlString(uiConfig.hoverBackgroundColor, out Color backgroundColor))
            {
                backgroundColor.a = uiConfig.hoverBackgroundAlpha;
                hoverBackground.color = backgroundColor;
            }
        }
    }
}

// ========================================
// NOUVELLES STRUCTURES POUR L'API GAMES
// Endpoint: /api/ujsa/games/{gameId}?difficulty={difficulty}
// ========================================

/// <summary>
/// Réponse de l'API pour récupérer la configuration complète d'un jeu
/// </summary>
[System.Serializable]
public class APIGameResponse
{
    public string status;
    public string message;
    public APIGameData data;
}

/// <summary>
/// Données complètes d'un jeu depuis l'API
/// Contient : backdrop, background, config jeu, dialogues, questions/réponses
/// </summary>
[System.Serializable]
public class APIGameData
{
    // Backdrop (image d'habillage à l'extérieur de la zone de jeu)
    public APIGameBackground backdrop;
    
    // Background (vidéo/image dans la zone de jeu)
    public APIGameBackground background;
    
    // Configuration du crosshair
    public APICrosshairConfig crosshairConfig;
    
    // Assets (gun, crosshair, impact)
    public APIGameAssets assets;
    
    // Sons
    public APIGameSounds sounds;
    
    // Configuration du pistolet
    public APIGunConfig gunConfig;
    
    // Configuration de la calculatrice (pour calculator)
    public APICalculatorConfig calculatorConfig;
    
    // Boutons de la calculatrice
    public APICalculatorButton[] calculatorButtons;
    
    // Zones de tir
    public APIGameZone[] zones;
    
    // Questions/Réponses
    public APIGameQuestionData[] questions;
    
    // Dialogues (intro, success, fail)
    public APIGameDialogues dialogues;
    
    // Configuration de la zone de texte (pour text_hole)
    public APITextAreaConfig textArea;
    public APITextAreaConfig textConfig; // Alias
}

/// <summary>
/// Configuration de la calculatrice depuis l'API
/// </summary>
[System.Serializable]
public class APICalculatorConfig
{
    public APIPosition imagePosition;
    public APISize imageSize;
    public float imageScale = 1f;
    public APIPosition position;
    public APISize size;
    public APIPosition displayPosition;
    public APISize displaySize;
    public string displayBackgroundColor;
    public string displayTextColor;
    public float displayTextSize;
}

/// <summary>
/// Bouton de calculatrice depuis l'API
/// </summary>
[System.Serializable]
public class APICalculatorButton
{
    public string buttonId;
    public string buttonType;
    public string value;
    // Format imbriqué
    public APIPosition position;
    public APISize size;
    // Format plat (alternative)
    public float x;
    public float y;
    public float width;
    public float height;
}

/// <summary>
/// Position x,y depuis l'API
/// </summary>
[System.Serializable]
public class APIPosition
{
    public float x;
    public float y;
}

/// <summary>
/// Taille x,y depuis l'API
/// </summary>
[System.Serializable]
public class APISize
{
    public float x;
    public float y;
}

/// <summary>
/// Configuration de la zone de texte (pour jeux text_hole)
/// Supporte à la fois l'ancienne structure (x, y, width, height) 
/// et la nouvelle structure imbriquée (position, size, padding)
/// </summary>
[System.Serializable]
public class APITextAreaConfig
{
    // Ancienne structure (compatibilité)
    public float x;           // Position X du coin haut-gauche
    public float y;           // Position Y du coin haut-gauche
    public float width;       // Largeur de la zone
    public float height;      // Hauteur de la zone
    
    // Nouvelle structure imbriquée (depuis l'API)
    public APITextAreaPosition position;
    public APITextAreaSize size;
    public APITextAreaPadding padding;
    
    public float fontSize;    // Taille de la police
    public string fontColor;  // Couleur du texte
    public bool fontBold;     // Police en gras
    public string alignment;  // Alignement du texte
    public float lineSpacing; // Espacement des lignes
    public string backgroundColor; // Couleur de fond
    public float backgroundAlpha;  // Transparence du fond
    
    // Ancienne structure padding (compatibilité)
    public float paddingTop;
    public float paddingBottom;
    public float paddingLeft;
    public float paddingRight;
    
    // Méthodes d'accès qui gèrent les deux structures
    public float GetX() => position != null ? position.x : x;
    public float GetY() => position != null ? position.y : y;
    public float GetWidth() => size != null ? size.width : width;
    public float GetHeight() => size != null ? size.height : height;
    public float GetPaddingTop() => padding != null ? padding.top : paddingTop;
    public float GetPaddingBottom() => padding != null ? padding.bottom : paddingBottom;
    public float GetPaddingLeft() => padding != null ? padding.left : paddingLeft;
    public float GetPaddingRight() => padding != null ? padding.right : paddingRight;
}

[System.Serializable]
public class APITextAreaPosition
{
    public float x;
    public float y;
}

[System.Serializable]
public class APITextAreaSize
{
    public float width;
    public float height;
}

[System.Serializable]
public class APITextAreaPadding
{
    public float top;
    public float bottom;
    public float left;
    public float right;
}

/// <summary>
/// Background du jeu (video ou image)
/// </summary>
[System.Serializable]
public class APIGameBackground
{
    public string type; // "video" ou "image"
    public string url;
}

/// <summary>
/// Configuration du crosshair depuis l'API
/// </summary>
[System.Serializable]
public class APICrosshairConfig
{
    public float defaultSize = 50f;
    public float minSize = 10f;
    public float maxSize = 150f;
    public bool allowPlayerResize = true;
    public bool alwaysShowCrosshair = true;
    public float onTargetSizeMultiplier = 1f;
    public float offTargetSizeMultiplier = 0.75f;
    public float onTargetAlpha = 1f;
    public float offTargetAlpha = 0.3f;
    public float sizeTransitionSpeed = 20f;
    public float alphaTransitionSpeed = 15f;
    public bool smoothTransitions = true;
}

/// <summary>
/// Assets du jeu (images)
/// </summary>
[System.Serializable]
public class APIGameAssets
{
    public string gun;
    public string crosshair;
    public string impact;
    public string calculatorImage;  // Image de la calculatrice pour les jeux calculator
    public string ledOff;           // LED éteinte
    public string ledGreen;         // LED verte (réponse correcte)
    public string ledRed;           // LED rouge (réponse incorrecte)
}

/// <summary>
/// Sons du jeu
/// </summary>
[System.Serializable]
public class APIGameSounds
{
    public string shoot;
    public string impact;
    public string success;
    public string fail;
}

/// <summary>
/// Configuration du pistolet
/// </summary>
[System.Serializable]
public class APIGunConfig
{
    public APIVector2 offsetFromCursor;
    public float size = 900f;
    public APIVector2 gunSize;
    public bool flipHorizontally = false;
    public bool enableRotation = false;
    public float rotationOffset = -90f;
    public bool alwaysVisible = true;
    public float fadeSpeed = 8f;
    public bool hideDuringFeedback = true;
    public APIGunBoundary boundary;
}

/// <summary>
/// Vecteur 2D pour l'API
/// </summary>
[System.Serializable]
public class APIVector2
{
    public float x;
    public float y;
    
    public Vector2 ToVector2()
    {
        return new Vector2(x, y);
    }
}

/// <summary>
/// Configuration des limites du pistolet
/// </summary>
[System.Serializable]
public class APIGunBoundary
{
    public bool enableBoundaryConstraints = true;
    public bool useAutomaticMargins = true;
    public float marginLeft = 0f;
    public float marginRight = 0f;
    public float marginTop = 0f;
    public float marginBottom = 0f;
}

/// <summary>
/// Zone de tir
/// </summary>
[System.Serializable]
public class APIGameZone
{
    public int id;
    public string label;
    public bool is_correct;
    public float x;
    public float y;
    public float width;
    public float height;
    public string text;       // Texte de la zone (optionnel)
    public string imageUrl;   // Image de la zone (optionnel)
}

/// <summary>
/// Question d'un jeu depuis l'API
/// </summary>
[System.Serializable]
public class APIGameQuestionData
{
    public int id;
    public string question;
    public string text;           // Texte alternatif pour certains types de jeux
    public APIGameAnswerData[] answers;
    public string explanation;
    public string[] options;      // Options pour les jeux text_hole
    public string correct_answer; // Réponse correcte pour certains jeux
    public APIHoleData[] holes;   // Données des trous pour text_hole
    public APIHoleData[] blanks;  // Alias pour holes (certaines APIs utilisent "blanks")
}

/// <summary>
/// Données d'un trou (pour jeux text_hole)
/// </summary>
[System.Serializable]
public class APIHoleData
{
    public int id;
    public string marker;         // "TROU1", "TROU2", etc.
    public string keyword;        // Alias pour marker
    public APIHoleOptionData[] options; // Options avec IDs {id, content}
    public string correct_answer; // Réponse correcte (format legacy: texte)
    public int correctAnswer;     // ID de la bonne réponse (nouveau format)
    public int correct_index;     // Index de la bonne réponse dans options
}

/// <summary>
/// Option d'un trou avec son ID
/// </summary>
[System.Serializable]
public class APIHoleOptionData
{
    public int id;
    public string content;
}

/// <summary>
/// Réponse à une question depuis l'API
/// </summary>
[System.Serializable]
public class APIGameAnswerData
{
    public int id;            // ID de l'option de réponse pour l'API answers
    public string text;
    public bool is_correct;
    public string zoneId;
}

/// <summary>
/// Conteneur des dialogues
/// </summary>
[System.Serializable]
public class APIGameDialogues
{
    public APIDialogueContent intro;
    public APIDialogueContent success;
    public APIDialogueContent fail;
}

/// <summary>
/// Contenu d'un dialogue (intro, success, fail)
/// </summary>
[System.Serializable]
public class APIDialogueContent
{
    public string title;
    public string video;
    public APIDialogueLine[] lines;
}

/// <summary>
/// Une ligne de dialogue
/// </summary>
[System.Serializable]
public class APIDialogueLine
{
    public string text;
    public string image;
}