package com.example.boidelov3;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

import com.example.boidelov3.data.PlayerStats;
import com.example.boidelov3.data.QuestionCategory;
import com.example.boidelov3.utils.SoundManager;
import com.example.boidelov3.utils.ErrorHandler;
import com.google.android.material.button.MaterialButton;
import com.google.gson.Gson;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;

/**
 * Activité principale du jeu Boidelo
 * Affiche les questions et gère les interactions de jeu
 */
public class Jeux extends AppCompatActivity {
    // Vues
    private TextView questionTextView;
    private TextView progressTextView;
    private TextView mancheCounterTextView;
    private TextView mancheQuestionText;
    private ProgressBar progressBar;
    private MaterialButton suivantButton;
    private MaterialButton skipButton;
    private LinearLayout questionIndicator;
    private ImageView indicatorIcon;
    private TextView indicatorText;
    private View rootLayout; // Layout racine pour la couleur de fond

    // Données
    private Questions questions;
    private List<String> toutlesjoueurs;
    private List<Question> questionsAvecManches = new ArrayList<>();
    private Map<String, PlayerStats> playerStatsMap; // Statistiques des joueurs
    private SoundManager soundManager; // Gestionnaire de sons
    private OpenAIService openAIService; // Service OpenAI
    private OpenAIService.AIProvider aiProvider = OpenAIService.AIProvider.OPENAI; // Provider IA
    private List<Question> generatedAIQuestions; // Questions générées par l'IA

    // Générateur aléatoire unique pour toute l'activité
    private final Random random = new Random();

    // Paramètres de partie
    private int nombreQuestions;
    private int ajoutGorgees;
    private boolean openAI;
    private int ratiOpenai;
    private String keyOpenai;
    private int durationDefis; // Offset pour la durée des défis

    // État du jeu
    private int currentQuestionIndex = 0;
    private int totalQuestionsAsked = 0;
    private String currentQuestionText = "";
    private boolean isMancheActive = false;
    private boolean isFinishingGame = false; // Flag pour empêcher les appels multiples pendant la fin du jeu
    private int questionsSinceLastAI = 0; // Compteur pour le ratio IA

    // Constantes pour les nombres magiques
    private static final int MIN_DEFI_ROUNDS = 4;  // Minimum 4 manches pour les défis
    private static final int MAX_DEFI_ROUNDS_RANDOM = 6;  // Max 6 tours aléatoires (4-10 tours au total)
    private static final int MIN_MANCHES_COUNT = 4;
    private static final int PREGENERATED_AI_QUESTIONS = 2;
    private static final int MIN_AI_QUESTION_STOCK = 2;
    private static final int MIN_AI_GORGEE = 1;  // Minimum 1 gorgée
    private static final int MAX_AI_GORGEE_ADDITIONAL = 3;
    private static final int ANIMATION_DURATION_SHORT_MS = 300;
    private static final int BACKGROUND_COLOR_DELAY_MS = 1000;
    private static final int END_GAME_DELAY_MS = 3000;
    private static final int RANDOM_PLAYER_SELECTION_COUNT = 3;
    private static final int TWO_PLAYERS = 2;
    private static final int ONE_PLAYER = 1;

    // Clés pour sauvegarde d'état
    private static final String KEY_TOTAL_QUESTIONS = "total_questions_asked";
    private static final String KEY_CURRENT_QUESTION_TEXT = "current_question_text";
    private static final String KEY_IS_MANCHE_ACTIVE = "is_manche_active";
    private static final String KEY_MANCHES_COUNT = "manches_count";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_jeux);

        // Initialiser les vues
        initViews();

        // Récupération des données passées par l'activité précédente
        toutlesjoueurs = getIntent().getStringArrayListExtra("EXTRA_LIST_JOUEUR");

        // Initialiser les statistiques des joueurs
        initializePlayerStats();

        // Initialiser le gestionnaire de sons
        soundManager = SoundManager.getInstance(this);

        // Initialiser les services IA si activés
        generatedAIQuestions = new ArrayList<>();

        nombreQuestions = getIntent().getIntExtra("EXTRA_NOMBRE_QUESTIONS", 50);
        ajoutGorgees = getIntent().getIntExtra("EXTRA_AJOUT_GORGEE", 0);
        ratiOpenai = getIntent().getIntExtra("EXTRA_RATIO_OPENAI", 0);
        durationDefis = getIntent().getIntExtra("EXTRA_DURATION_DEFIS", 0);
        openAI = getIntent().getBooleanExtra("EXTRA_OPENAI", false);
        keyOpenai = getIntent().getStringExtra("EXTRA_KEY_OPENAI");

        // Récupérer le provider IA
        String providerName = getIntent().getStringExtra("EXTRA_AI_PROVIDER");
        if (providerName != null) {
            try {
                aiProvider = OpenAIService.AIProvider.valueOf(providerName);
            } catch (IllegalArgumentException e) {
                aiProvider = OpenAIService.AIProvider.OPENAI;
            }
        }

        if (openAI && keyOpenai != null && !keyOpenai.isEmpty()) {
            // Valider la clé API avant de créer le service
            if (OpenAIService.validateApiKey(keyOpenai, aiProvider)) {
                openAIService = new OpenAIService(keyOpenai, aiProvider);
                // Prégénérer quelques questions IA pour avoir un stock au démarrage
                for (int i = 0; i < PREGENERATED_AI_QUESTIONS; i++) {
                    generateAIQuestion();
                }
            } else {
                // Clé API invalide : désactiver l'IA et afficher un message
                Log.w("Jeux", "Clé API invalide, désactivation de la génération IA");
                openAI = false;
                Toast.makeText(this, "Clé API invalide. Vérifiez votre configuration.", Toast.LENGTH_LONG).show();
            }
        }

        // Charger les questions depuis le JSON
        loadQuestions();

        // Configurer la barre de progression
        setupProgressBar();

        // Restaurer l'état si disponible (rotation)
        if (savedInstanceState != null) {
            restoreGameState(savedInstanceState);
        } else {
            // Réinitialiser le flag de fin de jeu
            isFinishingGame = false;
            // Afficher la première question
            updateQuestion();
        }

        // Configuration des listeners de boutons
        setupButtonListeners();
    }

    /**
     * Initialise toutes les vues de l'activité
     */
    private void initViews() {
        questionTextView = findViewById(R.id.textView1);
        progressTextView = findViewById(R.id.progressText);
        mancheCounterTextView = findViewById(R.id.mancheCounter);
        mancheQuestionText = findViewById(R.id.mancheQuestionText);
        progressBar = findViewById(R.id.progressBar);
        suivantButton = findViewById(R.id.button);
        skipButton = findViewById(R.id.skipButton);
        questionIndicator = findViewById(R.id.questionIndicator);
        indicatorIcon = findViewById(R.id.indicatorIcon);
        indicatorText = findViewById(R.id.indicatorText);
        rootLayout = findViewById(R.id.rootLayout);

        // Appliquer les animations aux boutons
        BoideloAnimationUtils.applyButtonPressAnimation(suivantButton);
        BoideloAnimationUtils.applyButtonPressAnimation(skipButton);

        // Cacher le bouton Passé au début (uniquement visible pendant les défis)
        skipButton.setVisibility(View.GONE);
    }

    /**
     * Charge les questions depuis le fichier JSON
     */
    private void loadQuestions() {
        try {
            try (InputStream is = getAssets().open("question.json")) {
                int size = is.available();
                byte[] buffer = new byte[size];
                is.read(buffer);
                String json = new String(buffer, "UTF-8");

                Gson gson = new Gson();
                questions = gson.fromJson(json, Questions.class);
            }
        } catch (IOException ex) {
            String operation = "Chargement du fichier question.json depuis les assets";
            String details = "Impossible de lire ou de parser le fichier de questions";
            ErrorHandler.showError(this, "Jeux", operation, details + ": " + ex.getMessage(), ex);
        }
    }

    /**
     * Initialise les statistiques des joueurs
     */
    private void initializePlayerStats() {
        playerStatsMap = new HashMap<>();
        if (toutlesjoueurs != null) {
            for (String joueur : toutlesjoueurs) {
                playerStatsMap.put(joueur, new PlayerStats(joueur));
            }
        }
    }

    /**
     * Configure la barre de progression initiale
     */
    private void setupProgressBar() {
        progressBar.setMax(nombreQuestions);
        progressBar.setProgress(0);
        updateProgressText();
    }

    /**
     * Configure les listeners des boutons
     */
    private void setupButtonListeners() {
        suivantButton.setOnClickListener(v -> {
            BoideloAnimationUtils.triggerHapticFeedback(this);
            // Plus de son de clic - juste la vibration haptique
            updateQuestion();
        });

        skipButton.setOnClickListener(v -> {
            BoideloAnimationUtils.triggerHapticFeedback(this);
            skipQuestion();
        });
    }

    /**
     * Met à jour le texte de progression
     */
    private void updateProgressText() {
        progressTextView.setText("Question " + (totalQuestionsAsked + 1) + " / " + nombreQuestions);
    }

    /**
     * Met à jour la barre de progression
     */
    private void updateProgressBar() {
        progressBar.setProgress(totalQuestionsAsked);
        updateProgressText();
    }

    /**
     * Met à jour la question affichée avec toutes les animations
     */
    private void updateQuestion() {
        // Si le jeu est en train de se terminer, ne rien faire
        if (isFinishingGame) {
            return;
        }

        // Vérifier si toutes les questions ont été posées
        if (shouldEndGame()) {
            handleGameEnd();
            return;
        }

        // Gérer les questions avec manches actives
        boolean hasMancheActive = processActiveManches();

        // Afficher une nouvelle question (que ce soit pendant ou hors manche)
        displayNewQuestion(hasMancheActive);
    }

    /**
     * Vérifie si le jeu doit se terminer
     */
    private boolean shouldEndGame() {
        return totalQuestionsAsked >= nombreQuestions;
    }

    /**
     * Gère la fin du jeu
     */
    private void handleGameEnd() {
        // Vérifier s'il y a encore des manches actives
        if (!questionsAvecManches.isEmpty()) {
            // Afficher le message de fin de manche et terminer
            showFinalMancheEndMessage();
        } else {
            endGame();
        }
    }

    /**
     * Traite les manches actives et retourne true si une manche est active
     */
    private boolean processActiveManches() {
        Iterator<Question> iterator = questionsAvecManches.iterator();
        boolean hasMancheActive = false;

        while (iterator.hasNext()) {
            Question mancheQuestion = iterator.next();
            mancheQuestion.setManchesRestantes(mancheQuestion.getManchesRestantes() - 1);

            if (mancheQuestion.getManchesRestantes() <= 0) {
                // Afficher brièvement le message d'arrêt et continuer
                showMancheEndNotification(mancheQuestion.getArretMessageManche());
                iterator.remove();
                // Continuer avec une nouvelle question après la fin de manche
                break;
            } else {
                // Afficher la question de manche en petit et continuer
                hasMancheActive = true;
                displayMancheQuestionSmall(mancheQuestion);
                break; // Un seul défi à manches à la fois
            }
        }

        return hasMancheActive;
    }

    /**
     * Affiche une nouvelle question
     */
    private void displayNewQuestion(boolean hasMancheActive) {
        Question question = getRandomQuestion();
        if (question != null) {
            displayQuestion(question, hasMancheActive);
            totalQuestionsAsked++;
            updateProgressBar();
        } else {
            endGame();
        }
    }

    /**
     * Affiche une notification de fin de manche (sans bloquer le jeu)
     */
    private void showMancheEndNotification(String message) {
        // Afficher un Toast avec le message de fin
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();

        // Vibration de succès
        BoideloAnimationUtils.triggerSuccessHaptic(this);

        // Masquer le compteur de manches, l'indicateur et le bouton Passé
        mancheCounterTextView.setVisibility(View.GONE);
        questionIndicator.setVisibility(View.GONE);
        mancheQuestionText.setVisibility(View.GONE);
        skipButton.setVisibility(View.GONE);

        // Animation de fond jaune temporaire
        int yellowColor = ContextCompat.getColor(this, R.color.game_manche_end);
        BoideloAnimationUtils.animateBackgroundColor(getWindow().getDecorView(), yellowColor);

        // Revenir à la couleur normale après un délai
        mancheCounterTextView.postDelayed(() -> {
            int defaultColor = ContextCompat.getColor(this, R.color.game_normal);
            BoideloAnimationUtils.animateBackgroundColor(getWindow().getDecorView(), defaultColor);
        }, BACKGROUND_COLOR_DELAY_MS);
    }

    /**
     * Affiche le message de fin de manche finale (quand le jeu se termine)
     */
    private void showFinalMancheEndMessage() {
        // Marquer le jeu comme en train de se terminer
        isFinishingGame = true;

        // Récupérer le message de la dernière manche
        if (!questionsAvecManches.isEmpty()) {
            Question lastManche = questionsAvecManches.get(0);
            questionTextView.setText(Html.fromHtml(lastManche.getArretMessageManche(), Html.FROM_HTML_MODE_LEGACY));
        }

        // Animation de fond jaune
        int yellowColor = ContextCompat.getColor(this, R.color.game_manche_end);
        BoideloAnimationUtils.animateBackgroundColor(getWindow().getDecorView(), yellowColor);

        // Vibration de succès
        BoideloAnimationUtils.triggerSuccessHaptic(this);

        // Masquer le compteur, l'indicateur et le bouton Passé
        mancheCounterTextView.setVisibility(View.GONE);
        questionIndicator.setVisibility(View.GONE);
        mancheQuestionText.setVisibility(View.GONE);
        skipButton.setVisibility(View.GONE);
        suivantButton.setEnabled(false); // Désactiver le bouton pendant la fin

        // Terminer après un délai
        mancheCounterTextView.postDelayed(() -> {
            questionsAvecManches.clear();
            endGame();
        }, END_GAME_DELAY_MS);
    }

    /**
     * Affiche une question de manche en petit (sans bloquer le jeu)
     */
    private void displayMancheQuestionSmall(Question question) {
        // Afficher la question de manche en petit avec le nombre de manches restantes
        String mancheQuestion = question.getQuestion() + " <small>(" + question.getManchesRestantes() + " manche(s) restante(s))</small>";
        mancheQuestionText.setText(Html.fromHtml(mancheQuestion, Html.FROM_HTML_MODE_LEGACY));
        mancheQuestionText.setVisibility(View.VISIBLE);

        // Mettre à jour le compteur
        updateMancheCounter(question.getManchesRestantes(), question.getQuestion());
    }

    /**
     * Affiche une question de manche active (ancienne méthode, plus utilisée)
     */
    private void displayMancheQuestion(Question question) {
        questionTextView.setText(Html.fromHtml(question.getQuestion(), Html.FROM_HTML_MODE_LEGACY));

        // Fond bleu pour les manches
        int blueColor = ContextCompat.getColor(this, R.color.game_question_manche);
        BoideloAnimationUtils.animateBackgroundColor(getWindow().getDecorView(), blueColor);

        // Afficher l'indicateur de manche
        showQuestionIndicator(R.drawable.ic_manche, "Manche en cours");

        // Mettre à jour le compteur
        updateMancheCounter(question.getManchesRestantes(), question.getQuestion());
    }

    /**
     * Met à jour le compteur de manches (affiché comme rappel)
     */
    private void updateMancheCounter(int manchesRestantes, String mancheQuestion) {
        mancheCounterTextView.setText("Défi en cours: " + manchesRestantes + " tour(s) restant(s)");
        mancheCounterTextView.setVisibility(View.VISIBLE);

        // Afficher l'indicateur de manche en haut
        showQuestionIndicator(R.drawable.ic_manche, "Manche en cours");

        // Animation du compteur
        BoideloAnimationUtils.pulse(mancheCounterTextView, ANIMATION_DURATION_SHORT_MS);
    }

    /**
     * Affiche une nouvelle question
     */
    private void displayQuestion(Question question, boolean hasMancheActive) {
        // Afficher le texte de la question
        displayQuestionText(question);

        // Masquer ou afficher la question de manche selon l'état
        handleMancheQuestionVisibility(hasMancheActive);

        // Détecter et afficher la catégorie de la question
        QuestionCategory.Category category = QuestionCategory.detectCategory(question);
        applyCategoryStyle(category);

        // Déterminer et afficher l'indicateur de joueurs
        String indicatorText = determinePlayerCountIndicator(question, category);
        showIndicatorText(indicatorText);
    }

    /**
     * Affiche le texte de la question
     */
    private void displayQuestionText(Question question) {
        questionTextView.setText(Html.fromHtml(question.getQuestion(), Html.FROM_HTML_MODE_LEGACY));
    }

    /**
     * Gère la visibilité de la question de manche
     */
    private void handleMancheQuestionVisibility(boolean hasMancheActive) {
        if (!hasMancheActive) {
            mancheQuestionText.setVisibility(View.GONE);
        }
    }

    /**
     * Applique le style de catégorie (couleur de fond, etc.)
     */
    private void applyCategoryStyle(QuestionCategory.Category category) {
        // Réinitialiser les indicateurs
        questionIndicator.setVisibility(View.GONE);
        mancheCounterTextView.setVisibility(View.GONE);

        // Appliquer la couleur de fond
        int categoryColor = QuestionCategory.getColorForCategory(category);
        rootLayout.setBackgroundColor(categoryColor);
    }

    /**
     * Détermine le texte de l'indicateur en fonction du nombre de joueurs et de la catégorie
     */
    private String determinePlayerCountIndicator(Question question, QuestionCategory.Category category) {
        String questionText = question.getQuestion();
        boolean isJoueurs1 = questionText.contains("<J1>");
        boolean isJoueurs2 = questionText.contains("<J2>");
        boolean isJoueurs3 = questionText.contains("<J3>");

        String categoryEmoji = getCategoryEmoji(category);
        String categoryName = QuestionCategory.getNameForCategory(category);

        // Priorité aux indications de nombre de joueurs si applicable
        if (isJoueurs1 && isJoueurs2 && isJoueurs3) {
            return "3 joueurs";
        } else if (isJoueurs1 && isJoueurs2) {
            return "2 joueurs";
        } else if (isJoueurs1) {
            return "1 joueur";
        } else {
            // Juste l'emoji et le nom de la catégorie
            return categoryEmoji + " " + categoryName;
        }
    }

    /**
     * Affiche l'indicateur avec le texte spécifié
     */
    private void showIndicatorText(String textToShow) {
        questionIndicator.setVisibility(View.VISIBLE);
        indicatorIcon.setVisibility(View.GONE);
        indicatorText.setText(textToShow);
    }

    /**
     * Retourne l'emoji associé à une catégorie
     */
    private String getCategoryEmoji(QuestionCategory.Category category) {
        switch (category) {
            case CIBLAGE:
                return "🎯";
            case CLASSEMENT:
                return "👑";
            case JUGEMENT:
                return "⚖️";
            case DUEL:
                return "🤝";
            case INTERACTIF:
                return "🎮";
            case DEFI_MANCHES:
                return "🔥";
            case VARIANTE:
                return "❓";
            case CALIENTE:
                return "😈";
            case VOTE:
                return "🗳️";
            case CLASSIQUE:
            default:
                return "⚪";
        }
    }


    /**
     * Affiche l'indicateur de type de question
     */
    private void showQuestionIndicator(int iconRes, String text) {
        indicatorIcon.setImageResource(iconRes);
        indicatorIcon.setVisibility(View.VISIBLE);
        indicatorText.setText(text);
        questionIndicator.setVisibility(View.VISIBLE);
        BoideloAnimationUtils.fadeIn(questionIndicator, ANIMATION_DURATION_SHORT_MS);
    }

    /**
     * Passe la question actuelle ou ignore le défi en cours
     */
    private void skipQuestion() {
        // Vérifier s'il y a un défi en cours
        if (!questionsAvecManches.isEmpty()) {
            // Ignorer le défi actuel
            Question mancheToRemove = questionsAvecManches.get(0);
            questionsAvecManches.clear();

            // Masquer le compteur, l'indicateur et le bouton Passé
            mancheCounterTextView.setVisibility(View.GONE);
            questionIndicator.setVisibility(View.GONE);
            mancheQuestionText.setVisibility(View.GONE);
            skipButton.setVisibility(View.GONE);

            // Afficher un message de confirmation
            Toast.makeText(this, "Défi ignoré !", Toast.LENGTH_SHORT).show();

            // Vibration de confirmation
            BoideloAnimationUtils.triggerHapticFeedback(this);

            // Animation de fond
            int defaultColor = ContextCompat.getColor(this, R.color.game_normal);
            BoideloAnimationUtils.animateBackgroundColor(getWindow().getDecorView(), defaultColor);
        } else {
            // Sinon, passer simplement la question
            totalQuestionsAsked++;
            updateProgressBar();
        }
        updateQuestion();
    }

    /**
     * Termine la partie et affiche l'écran de fin
     */
    private void endGame() {
        // Jouer le son de fin
        if (soundManager != null) soundManager.playFin();

        // Sauvegarder les statistiques de la partie
        saveGameStats();

        // Lancer l'activité de fin de partie
        Intent intent = new Intent(this, EndGameActivity.class);
        intent.putExtra("EXTRA_QUESTIONS_PLAYED", totalQuestionsAsked);
        intent.putExtra("EXTRA_PLAYERS_COUNT", toutlesjoueurs != null ? toutlesjoueurs.size() : 0);
        intent.putStringArrayListExtra("EXTRA_PLAYERS", (ArrayList<String>) toutlesjoueurs);

        // Passer les statistiques des joueurs
        ArrayList<PlayerStats> playerStatsList = new ArrayList<>(playerStatsMap.values());
        intent.putParcelableArrayListExtra("PLAYER_STATS", playerStatsList);

        startActivity(intent);

        // Animation de transition
        overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);

        // Vibration de fin
        BoideloAnimationUtils.triggerErrorHaptic(this);

        // Réinitialiser les questions posées pour une prochaine partie
        resetAskedQuestions();

        // Terminer l'activité
        finish();
    }

    /**
     * Sauvegarde les statistiques de la partie
     */
    private void saveGameStats() {
        SharedPreferences prefs = getSharedPreferences("game_stats", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = prefs.edit();
        editor.putInt("questions_played", totalQuestionsAsked);
        editor.putInt("players_count", toutlesjoueurs != null ? toutlesjoueurs.size() : 0);
        editor.apply();
    }

    /**
     * Réinitialise la liste des questions posées
     */
    private void resetAskedQuestions() {
        SharedPreferences prefs = getSharedPreferences("app", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = prefs.edit();
        editor.remove("askedQuestions");
        editor.apply();
    }

    /**
     * Sélectionne trois joueurs aléatoires différents
     */
    public List<String> TroisJoueurAleatoire(List<String> toutlesjoueurs) {
        Set<String> setJoueur = new HashSet<>();

        while (setJoueur.size() < RANDOM_PLAYER_SELECTION_COUNT && toutlesjoueurs.size() >= RANDOM_PLAYER_SELECTION_COUNT) {
            setJoueur.add(toutlesjoueurs.get(random.nextInt(toutlesjoueurs.size())));
        }

        // Mélanger la liste pour avoir un ordre aléatoire (pas toujours le même)
        List<String> result = new ArrayList<>(setJoueur);
        Collections.shuffle(result, random);
        return result;
    }

    /**
     * Récupère le message d'arrêt par ID
     */
    private String getArretById(int id) {
        for (Question question : questions.getQuestions()) {
            if (question.getId() == id) {
                return question.getArret();
            }
        }
        return null;
    }

    /**
     * Génère une nouvelle question via l'IA OpenAI
     */
    private void generateAIQuestion() {
        if (openAIService == null) {
            return;
        }

        openAIService.generateQuestion(toutlesjoueurs, ajoutGorgees, new OpenAIService.OpenAICallback() {
            @Override
            public void onSuccess(String questionText) {
                if (questionText != null && !questionText.isEmpty()) {
                    // Créer une nouvelle question à partir du texte généré
                    Question aiQuestion = createAIQuestion(questionText);
                    if (aiQuestion != null) {
                        generatedAIQuestions.add(aiQuestion);
                        // Afficher un petit indicateur que c'est une question IA
                        Toast.makeText(Jeux.this, "✨ Question IA générée !", Toast.LENGTH_SHORT).show();
                    }
                }
            }

            @Override
            public void onError(String errorMessage) {
                // En cas d'erreur, on continue avec les questions JSON
                // Pas de toast pour ne pas interrompre le jeu
                android.util.Log.e("OpenAI", "Erreur génération question: " + errorMessage);
            }
        });
    }

    /**
     * Crée un objet Question à partir du texte généré par l'IA
     */
    private Question createAIQuestion(String questionText) {
        try {
            Question question = new Question();
            question.setId(-1); // ID négatif pour les questions IA
            question.setQuestion(questionText);
            question.setGorger(MIN_AI_GORGEE + random.nextInt(MAX_AI_GORGEE_ADDITIONAL)); // 2-4 gorgées par défaut
            question.setDistribution(random.nextBoolean());
            question.setRecois(!question.isDistribution() || random.nextBoolean());

            // Détecter si c'est une question de vote
            if (questionText.toLowerCase().contains("votez") ||
                questionText.toLowerCase().contains("minorité") ||
                questionText.toLowerCase().contains("majorité")) {
                question.setDistribution(false);
                question.setRecois(true);
            }

            return question;
        } catch (Exception e) {
            android.util.Log.e("OpenAI", "Erreur création question IA: " + e.getMessage());
            return null;
        }
    }

    /**
     * Obtient une question aléatoire qui n'a pas encore été posée
     * Intègre les questions générées par l'IA selon le ratio configuré
     */
    private Question getRandomQuestion() {
        // Incrémenter le compteur de questions depuis la dernière IA
        questionsSinceLastAI++;

        // Vérifier si on doit utiliser une question IA
        Question aiQuestion = tryGetAIQuestion();
        if (aiQuestion != null) {
            return aiQuestion;
        }

        // Générer une question IA en arrière-plan si le stock est bas
        if (shouldGenerateAIInBackground()) {
            generateAIQuestion();
        }

        // Sinon, utiliser une question du JSON
        return getJSONQuestion();
    }

    /**
     * Tente de récupérer une question IA si les conditions sont remplies
     */
    private Question tryGetAIQuestion() {
        if (!shouldUseAIQuestion()) {
            return null;
        }

        if (generatedAIQuestions.isEmpty()) {
            return null;
        }

        Question aiQuestion = generatedAIQuestions.remove(0);
        questionsSinceLastAI = 0; // Réinitialiser le compteur

        // Traiter la question IA
        processQuestion(aiQuestion);

        // Générer en arrière-plan la prochaine question IA pour avoir un stock
        generateAIQuestion();

        return aiQuestion;
    }

    /**
     * Vérifie si on doit utiliser une question IA selon le ratio
     */
    private boolean shouldUseAIQuestion() {
        return ratiOpenai > 0 && openAIService != null && questionsSinceLastAI >= ratiOpenai;
    }

    /**
     * Vérifie si on doit générer une question IA en arrière-plan
     */
    private boolean shouldGenerateAIInBackground() {
        return openAIService != null && generatedAIQuestions.size() < MIN_AI_QUESTION_STOCK;
    }

    /**
     * Récupère une question depuis le fichier JSON
     */
    private Question getJSONQuestion() {
        if (questions == null) {
            return null;
        }

        SharedPreferences prefs = getSharedPreferences("app", Context.MODE_PRIVATE);
        Set<String> askedQuestions = prefs.getStringSet("askedQuestions", new HashSet<>());

        List<Question> unaskedQuestions = getUnaskedQuestions(askedQuestions);

        if (unaskedQuestions.isEmpty()) {
            return null;
        }

        List<Question> availableQuestions = filterAvailableQuestions(unaskedQuestions);

        if (availableQuestions.isEmpty()) {
            return null;
        }

        Question question = selectRandomQuestion(availableQuestions);
        markQuestionAsAsked(question, askedQuestions, prefs);

        // Traiter la question
        processQuestion(question);

        return question;
    }

    /**
     * Récupère la liste des questions non posées
     */
    private List<Question> getUnaskedQuestions(Set<String> askedQuestions) {
        List<Question> unaskedQuestions = new ArrayList<>();
        for (Question question : questions.getQuestions()) {
            if (!askedQuestions.contains(String.valueOf(question.getId()))) {
                unaskedQuestions.add(question);
            }
        }
        return unaskedQuestions;
    }

    /**
     * Filtre les questions disponibles selon qu'un défi est en cours ou non
     */
    private List<Question> filterAvailableQuestions(List<Question> unaskedQuestions) {
        List<Question> availableQuestions = new ArrayList<>();
        boolean mancheActive = !questionsAvecManches.isEmpty();

        for (Question question : unaskedQuestions) {
            if (mancheActive) {
                // Un défi est en cours, exclure les questions avec <manches>
                if (!question.getQuestion().contains("<manches>")) {
                    availableQuestions.add(question);
                }
            } else {
                // Pas de défi en cours, toutes les questions sont disponibles
                availableQuestions.add(question);
            }
        }

        return availableQuestions;
    }

    /**
     * Sélectionne une question aléatoire parmi celles disponibles
     */
    private Question selectRandomQuestion(List<Question> availableQuestions) {
        return availableQuestions.get(random.nextInt(availableQuestions.size()));
    }

    /**
     * Marque une question comme posée et sauvegarde l'état
     */
    private void markQuestionAsAsked(Question question, Set<String> askedQuestions, SharedPreferences prefs) {
        askedQuestions.add(String.valueOf(question.getId()));

        // Sauvegarder les questions posées
        SharedPreferences.Editor editor = prefs.edit();
        editor.putStringSet("askedQuestions", askedQuestions);
        editor.apply();
    }

    /**
     * Traite une question (remplace les variables, etc.)
     */
    private void processQuestion(Question question) {
        String questionText = question.getQuestion();

        // Remplacer les variantes
        questionText = processVariantes(question, questionText);

        // Gérer les manches
        questionText = processManches(question, questionText);

        // Remplacer les joueurs et récupérer le nom du joueur J1 pour les stats
        PlayerSelectionResult playerResult = replacePlayers(questionText);
        questionText = playerResult.questionText;

        // Ajouter les gorgées et tracker les stats (en passant le nombre de joueurs pour l'accord)
        GorgeeResult gorgeeResult = processGorgees(question, questionText, playerResult.playerCount);
        questionText = gorgeeResult.questionText;

        // Mettre à jour les statistiques du joueur J1
        updatePlayerStats(playerResult.j1Name, gorgeeResult);

        question.setQuestion(questionText);
    }

    /**
     * Remplace les variantes dans la question
     */
    private String processVariantes(Question question, String questionText) {
        if (question.getVariante() != null && !question.getVariante().isEmpty()) {
            String chosenVariante = question.getVariante().get(random.nextInt(question.getVariante().size()));
            questionText = questionText.replace("<variante>", chosenVariante);
        }
        return questionText;
    }

    /**
     * Gère les manches pour les défis
     */
    private String processManches(Question question, String questionText) {
        if (questionText.contains("<manches>")) {
            int nbaleatoiremanches = calculateManchesCount();
            questionText = questionText.replace("<manches>", String.valueOf(nbaleatoiremanches));
            question.setManchesRestantes(nbaleatoiremanches);

            String stopid = getArretById(question.getId());
            if (stopid == null) stopid = "Le défi est terminé !";
            question.setArretMessageManche("Fin de défi!\n" + stopid);
            questionsAvecManches.add(question);

            // Jouer le son de manche
            if (soundManager != null) soundManager.playManche();

            // Afficher le bouton Passé pendant les défis
            skipButton.setVisibility(View.VISIBLE);
            BoideloAnimationUtils.fadeIn(skipButton, ANIMATION_DURATION_SHORT_MS);
        }
        return questionText;
    }

    /**
     * Calcule le nombre de manches pour un défi
     */
    private int calculateManchesCount() {
        int nbaleatoiremanches = random.nextInt(MAX_DEFI_ROUNDS_RANDOM) + MIN_DEFI_ROUNDS + durationDefis;
        // S'assurer qu'il y a au moins 1 manche
        return Math.max(nbaleatoiremanches, MIN_MANCHES_COUNT);
    }

    /**
     * Résultat du remplacement des joueurs
     */
    private static class PlayerSelectionResult {
        String questionText;
        String j1Name;
        int playerCount;  // Nombre de joueurs sélectionnés pour l'accord du verbe

        PlayerSelectionResult(String questionText, String j1Name, int playerCount) {
            this.questionText = questionText;
            this.j1Name = j1Name;
            this.playerCount = playerCount;
        }
    }

    /**
     * Remplace les placeholders de joueurs dans la question
     */
    private PlayerSelectionResult replacePlayers(String questionText) {
        boolean isJoueurs1 = questionText.contains("<J1>");
        boolean isJoueurs2 = questionText.contains("<J2>");
        boolean isJoueurs3 = questionText.contains("<J3>");

        String j1Name = null;
        int playerCount = 0;

        if (isJoueurs1 || isJoueurs2 || isJoueurs3) {
            List<String> aleatoirejoueurs = TroisJoueurAleatoire(toutlesjoueurs);

            if (isJoueurs1 && isJoueurs2 && isJoueurs3 && aleatoirejoueurs.size() >= RANDOM_PLAYER_SELECTION_COUNT) {
                playerCount = 3;
                j1Name = aleatoirejoueurs.get(0);
                questionText = questionText.replace("<J1>", ErrorHandler.escapeHtml(j1Name));
                questionText = questionText.replace("<J2>", ErrorHandler.escapeHtml(aleatoirejoueurs.get(1)));
                questionText = questionText.replace("<J3>", ErrorHandler.escapeHtml(aleatoirejoueurs.get(2)));
            } else if (isJoueurs1 && isJoueurs2 && aleatoirejoueurs.size() >= TWO_PLAYERS) {
                playerCount = 2;
                j1Name = aleatoirejoueurs.get(0);
                questionText = questionText.replace("<J1>", ErrorHandler.escapeHtml(j1Name));
                questionText = questionText.replace("<J2>", ErrorHandler.escapeHtml(aleatoirejoueurs.get(1)));
            } else if (isJoueurs1 && aleatoirejoueurs.size() >= ONE_PLAYER) {
                playerCount = 1;
                j1Name = aleatoirejoueurs.get(0);
                questionText = questionText.replace("<J1>", ErrorHandler.escapeHtml(j1Name));
            }
        }

        return new PlayerSelectionResult(questionText, j1Name, playerCount);
    }

    /**
     * Résultat du traitement des gorgées
     */
    private static class GorgeeResult {
        String questionText;
        int totalGorgees;
        boolean isBois;
        boolean isDistribue;

        GorgeeResult(String questionText, int totalGorgees, boolean isBois, boolean isDistribue) {
            this.questionText = questionText;
            this.totalGorgees = totalGorgees;
            this.isBois = isBois;
            this.isDistribue = isDistribue;
        }
    }

    /**
     * Traite les gorgées pour une question
     */
    private GorgeeResult processGorgees(Question question, String questionText, int playerCount) {
        int totalGorgees = 0;
        boolean isBois = false;
        boolean isDistribue = false;

        if (question.isDistribution() || question.isRecois()) {
            totalGorgees = question.getGorger() + ajoutGorgees;

            ActionChoiceResult actionResult = determineActionChoice(question, questionText, playerCount);
            questionText = actionResult.questionText;
            isBois = actionResult.isBois;
            isDistribue = actionResult.isDistribue;

            questionText = appendGorgeeCount(questionText, totalGorgees);
        }

        return new GorgeeResult(questionText, totalGorgees, isBois, isDistribue);
    }

    /**
     * Résultat du choix d'action (bois/distribue)
     */
    private static class ActionChoiceResult {
        String questionText;
        boolean isBois;
        boolean isDistribue;

        ActionChoiceResult(String questionText, boolean isBois, boolean isDistribue) {
            this.questionText = questionText;
            this.isBois = isBois;
            this.isDistribue = isDistribue;
        }
    }

    /**
     * Détermine l'action (boit/boivent ou distribue/distribuent) selon le nombre de joueurs
     */
    private ActionChoiceResult determineActionChoice(Question question, String questionText, int playerCount) {
        boolean isBois = false;
        boolean isDistribue = false;

        // Accord du verbe selon le nombre de joueurs
        String boisVerb = (playerCount > 1) ? "boivent" : "boit";
        String distribueVerb = (playerCount > 1) ? "distribuent" : "distribue";

        if (question.isRecois() && question.isDistribution()) {
            boolean rand = random.nextBoolean();
            if (rand) {
                questionText = questionText.concat(" <b>" + boisVerb + "</b>");
                isBois = true;
            } else {
                questionText = questionText.concat(" <b>" + distribueVerb + "</b>");
                isDistribue = true;
            }
        } else if (question.isRecois()) {
            questionText = questionText.concat(" <b>" + boisVerb + "</b>");
            isBois = true;
        } else if (question.isDistribution()) {
            questionText = questionText.concat(" <b>" + distribueVerb + "</b>");
            isDistribue = true;
        }

        return new ActionChoiceResult(questionText, isBois, isDistribue);
    }

    /**
     * Ajoute le nombre de gorgées au texte de la question
     */
    private String appendGorgeeCount(String questionText, int totalGorgees) {
        String plural = totalGorgees > 1 ? "s" : "";
        return questionText.concat(" " + totalGorgees + " gorgée" + plural + ".");
    }

    /**
     * Met à jour les statistiques du joueur J1
     */
    private void updatePlayerStats(String j1Name, GorgeeResult gorgeeResult) {
        if (j1Name != null && playerStatsMap != null && playerStatsMap.containsKey(j1Name)) {
            PlayerStats stats = playerStatsMap.get(j1Name);
            if (gorgeeResult.isBois) {
                stats.addGorgeesBuves(gorgeeResult.totalGorgees);
            }
            if (gorgeeResult.isDistribue) {
                stats.addGorgeesDistribuees(gorgeeResult.totalGorgees);
            }
        }
    }

    /**
     * Méthode publique pour le bouton suivant (compatibilité avec XML)
     */
    public void OnClickButton1(View view) {
        BoideloAnimationUtils.triggerHapticFeedback(this);
        updateQuestion();
    }

    /**
     * Méthode publique pour le bouton passer
     */
    public void onSkipClick(View view) {
        BoideloAnimationUtils.triggerHapticFeedback(this);
        skipQuestion();
    }

    /**
     * Navigue vers l'activité JeuxParametres en cas d'échec API
     */
    public void navigateToJeuxParametres() {
        Intent intent = new Intent(Jeux.this, JeuxParametres.class);
        Toast.makeText(getApplicationContext(), "Échec de la communication avec l'API !", Toast.LENGTH_SHORT).show();
        startActivity(intent);
        finish();
    }

    /**
     * Sauvegarde l'état du jeu avant la rotation
     */
    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(KEY_TOTAL_QUESTIONS, totalQuestionsAsked);
        outState.putString(KEY_CURRENT_QUESTION_TEXT, questionTextView.getText().toString());
        outState.putBoolean(KEY_IS_MANCHE_ACTIVE, isMancheActive);

        // Sauvegarder l'état des manches actives
        ArrayList<Integer> mancheIds = new ArrayList<>();
        ArrayList<Integer> mancheCounts = new ArrayList<>();
        for (Question q : questionsAvecManches) {
            mancheIds.add(q.getId());
            mancheCounts.add(q.getManchesRestantes());
        }
        outState.putIntegerArrayList("manche_ids", mancheIds);
        outState.putIntegerArrayList("manche_counts", mancheCounts);
    }

    /**
     * Restaure l'état du jeu après rotation
     */
    private void restoreGameState(Bundle savedInstanceState) {
        totalQuestionsAsked = savedInstanceState.getInt(KEY_TOTAL_QUESTIONS, 0);
        currentQuestionText = savedInstanceState.getString(KEY_CURRENT_QUESTION_TEXT, "");
        isMancheActive = savedInstanceState.getBoolean(KEY_IS_MANCHE_ACTIVE, false);
        isFinishingGame = false; // Réinitialiser le flag de fin de jeu

        // Restaurer la progression
        progressBar.setProgress(totalQuestionsAsked);
        updateProgressText();

        // Restaurer le texte de la question
        if (!currentQuestionText.isEmpty()) {
            questionTextView.setText(Html.fromHtml(currentQuestionText, Html.FROM_HTML_MODE_LEGACY));
        }

        // Restaurer les manches actives
        ArrayList<Integer> mancheIds = savedInstanceState.getIntegerArrayList("manche_ids");
        ArrayList<Integer> mancheCounts = savedInstanceState.getIntegerArrayList("manche_counts");
        if (mancheIds != null && mancheCounts != null) {
            questionsAvecManches.clear();
            for (int i = 0; i < mancheIds.size(); i++) {
                Question q = findQuestionById(mancheIds.get(i));
                if (q != null) {
                    q.setManchesRestantes(mancheCounts.get(i));
                    questionsAvecManches.add(q);
                }
            }
        }
    }

    /**
     * Trouve une question par son ID
     */
    private Question findQuestionById(int id) {
        if (questions == null) return null;
        for (Question q : questions.getQuestions()) {
            if (q.getId() == id) {
                // Créer une copie pour éviter de modifier l'original
                Question copy = new Question();
                copy.setId(q.getId());
                copy.setQuestion(q.getQuestion());
                copy.setArret(q.getArret());
                copy.setVariante(q.getVariante());
                copy.setDistribution(q.isDistribution());
                copy.setRecois(q.isRecois());
                copy.setGorger(q.getGorger());
                copy.setManchesRestantes(q.getManchesRestantes());
                return copy;
            }
        }
        return null;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // Libérer les ressources du SoundManager
        if (soundManager != null) {
            soundManager.release();
        }
        // Libérer les ressources du service OpenAI
        if (openAIService != null) {
            openAIService.shutdown();
        }
    }
}
