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;
}

[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;
}

[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;
}

[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 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 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;

    [Header("Style du texte d'explication")]
    public string explanationTextColor = "#FFFFFF";
    public float explanationTextSize = 24f;
    public bool explanationTextBold = false;
}

[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);

    [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 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
        {
            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>";
        }

        string separator = feedbackConfig.separator;

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

        return resultMessage + separator + explanation;
    }

    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;
            }
        }
    }
}