package com.example.boidelov3.data;

import com.example.boidelov3.Question;

import org.junit.Test;
import static org.junit.Assert.*;

import java.util.Arrays;

/**
 * Tests unitaires pour la classe QuestionCategory.
 * Couvre la détection automatique de catégorie et les énumérations.
 */
public class QuestionCategoryTest {

    /**
     * Crée une question avec le texte spécifié
     */
    private Question createQuestion(String text) {
        Question q = new Question();
        q.setQuestion(text);
        return q;
    }

    @Test
    public void testDetectCategory_withNull_returnsClassique() {
        QuestionCategory.Category category = QuestionCategory.detectCategory(null);
        assertEquals("Null question should return CLASSIQUE", QuestionCategory.Category.CLASSIQUE, category);
    }

    @Test
    public void testDetectCategory_calienteFlag_returnsCaliente() {
        Question q = createQuestion("Question simple");
        q.setCaliente(true);

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Caliente flag should return CALIENTE", QuestionCategory.Category.CALIENTE, category);
    }

    @Test
    public void testDetectCategory_manches_returnsDefiManches() {
        Question q = createQuestion("Défi à manches <manches>");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Question with <manches> should return DEFI_MANCHES", QuestionCategory.Category.DEFI_MANCHES, category);
    }

    @Test
    public void testDetectCategory_manchesFlag_returnsDefiManches() {
        Question q = createQuestion("Défi sans tag");
        q.setManches(true);

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Manches flag should return DEFI_MANCHES", QuestionCategory.Category.DEFI_MANCHES, category);
    }

    @Test
    public void testDetectCategory_ciblage_ceuxQui() {
        Question q = createQuestion("Ceux qui portent du rouge boivent 2 gorgées");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect CIBLAGE pattern", QuestionCategory.Category.CIBLAGE, category);
    }

    @Test
    public void testDetectCategory_ciblage_lesJoueursQui() {
        Question q = createQuestion("Les joueurs qui ont des lunettes distribuent 3 gorgées");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect CIBLAGE pattern", QuestionCategory.Category.CIBLAGE, category);
    }

    @Test
    public void testDetectCategory_ciblage_toutesCelles() {
        Question q = createQuestion("Toutes celles qui ont les cheveux longs boivent");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect CIBLAGE pattern", QuestionCategory.Category.CIBLAGE, category);
    }

    @Test
    public void testDetectCategory_ciblage_tousCeux() {
        Question q = createQuestion("Tous ceux qui sont nés en hiver");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect CIBLAGE pattern", QuestionCategory.Category.CIBLAGE, category);
    }

    @Test
    public void testDetectCategory_classement_lePlus() {
        Question q = createQuestion("Le plus ivre boit 3 gorgées");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect CLASSEMENT pattern", QuestionCategory.Category.CLASSEMENT, category);
    }

    @Test
    public void testDetectCategory_classement_laPlus() {
        Question q = createQuestion("La plus drôle distribue");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect CLASSEMENT pattern", QuestionCategory.Category.CLASSEMENT, category);
    }

    @Test
    public void testDetectCategory_classement_elisez() {
        Question q = createQuestion("Élisez le meilleur joueur");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect CLASSEMENT pattern", QuestionCategory.Category.CLASSEMENT, category);
    }

    @Test
    public void testDetectCategory_classement_quiALePlus() {
        Question q = createQuestion("Qui a le plus bu distribue 5 gorgées");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect CLASSEMENT pattern", QuestionCategory.Category.CLASSEMENT, category);
    }

    @Test
    public void testDetectCategory_vote_votezTous() {
        Question q = createQuestion("Votez tous en même temps pour le perdant");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect VOTE pattern", QuestionCategory.Category.VOTE, category);
    }

    @Test
    public void testDetectCategory_vote_mainLevee() {
        Question q = createQuestion("Vote à main levée");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect VOTE pattern", QuestionCategory.Category.VOTE, category);
    }

    @Test
    public void testDetectCategory_jugement_juge() {
        Question q = createQuestion("<J1> à toi de juger qui distribue");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect JUGEMENT pattern", QuestionCategory.Category.JUGEMENT, category);
    }

    @Test
    public void testDetectCategory_jugement_selonToi() {
        Question q = createQuestion("<J1>, selon toi qui mérite de boire ?");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect JUGEMENT pattern", QuestionCategory.Category.JUGEMENT, category);
    }

    @Test
    public void testDetectCategory_duel_j1EtJ2() {
        Question q = createQuestion("<J1> et <J2> se regardent dans les yeux");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect DUEL pattern", QuestionCategory.Category.DUEL, category);
    }

    @Test
    public void testDetectCategory_interactif_quiz() {
        Question q = createQuestion("Quiz : quel est le plus grand fleuve du monde ?");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect INTERACTIF pattern", QuestionCategory.Category.INTERACTIF, category);
    }

    @Test
    public void testDetectCategory_interactif_deviner() {
        Question q = createQuestion("<J1> doit deviner la chanson");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect INTERACTIF pattern", QuestionCategory.Category.INTERACTIF, category);
    }

    @Test
    public void testDetectCategory_interactif_mime() {
        Question q = createQuestion("<J1> doit mimer un animal");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect INTERACTIF pattern", QuestionCategory.Category.INTERACTIF, category);
    }

    @Test
    public void testDetectCategory_variante_withVariante() {
        Question q = createQuestion("Choisissez une option <variante>");
        q.setVariante(Arrays.asList("Option A", "Option B"));

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Should detect VARIANTE pattern", QuestionCategory.Category.VARIANTE, category);
    }

    @Test
    public void testDetectCategory_variante_emptyList() {
        Question q = createQuestion("Test question");
        q.setVariante(Arrays.asList());

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Empty variante should return CLASSIQUE", QuestionCategory.Category.CLASSIQUE, category);
    }

    @Test
    public void testDetectCategory_default_returnsClassique() {
        Question q = createQuestion("Question simple sans pattern particulier");

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("Default should return CLASSIQUE", QuestionCategory.Category.CLASSIQUE, category);
    }

    @Test
    public void testGetColorForCategory_returnsValidColor() {
        for (QuestionCategory.Category category : QuestionCategory.Category.values()) {
            int color = QuestionCategory.getColorForCategory(category);
            // Colors include alpha channel (0xFF prefix), so they might be negative in signed int
            // Just check that the color is not black/transparent (0x0)
            assertTrue("Color should be valid (not 0) for " + category, color != 0);
        }
    }

    @Test
    public void testGetNameForCategory_returnsNonEmpty() {
        for (QuestionCategory.Category category : QuestionCategory.Category.values()) {
            String name = QuestionCategory.getNameForCategory(category);
            assertNotNull("Name should not be null for " + category, name);
            assertFalse("Name should not be empty for " + category, name.isEmpty());
        }
    }

    @Test
    public void testCategoryEnum_allCategoriesHaveUniqueNames() {
        java.util.Set<String> names = new java.util.HashSet<>();
        for (QuestionCategory.Category category : QuestionCategory.Category.values()) {
            assertTrue("Duplicate name found: " + category.getName(),
                    names.add(category.getName()));
        }
    }

    @Test
    public void testCategoryEnum_allCategoriesHaveUniqueColors() {
        java.util.Set<Integer> colors = new java.util.HashSet<>();
        for (QuestionCategory.Category category : QuestionCategory.Category.values()) {
            assertTrue("Duplicate color found for " + category.getName(),
                    colors.add(category.getColor()));
        }
    }

    @Test
    public void testDetectCategory_caseInsensitive() {
        Question q1 = createQuestion("CEUX QUI ont un chapeau boivent");
        Question q2 = createQuestion("ceux qui ont un chapeau boivent");

        QuestionCategory.Category cat1 = QuestionCategory.detectCategory(q1);
        QuestionCategory.Category cat2 = QuestionCategory.detectCategory(q2);

        assertEquals("Detection should be case-insensitive", cat1, cat2);
        assertEquals("Should detect CIBLAGE", QuestionCategory.Category.CIBLAGE, cat1);
    }

    @Test
    public void testDetectCategory_priority_calienteOverOthers() {
        Question q = createQuestion("<J1> et <J2> se font un bras de fer");
        q.setCaliente(true);

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("CALIENTE should have priority", QuestionCategory.Category.CALIENTE, category);
    }

    @Test
    public void testDetectCategory_priority_manchesOverVariante() {
        Question q = createQuestion("Défi <manches> avec choix <variante>");
        q.setVariante(Arrays.asList("A", "B"));

        QuestionCategory.Category category = QuestionCategory.detectCategory(q);
        assertEquals("DEFI_MANCHES should have priority over VARIANTE",
                QuestionCategory.Category.DEFI_MANCHES, category);
    }

    @Test
    public void testCategoryEnum_allFieldsAccessible() {
        QuestionCategory.Category ciblage = QuestionCategory.Category.CIBLAGE;
        assertEquals("Ciblage", ciblage.getName());
        assertEquals("Questions qui ciblent un groupe spécifique", ciblage.getDescription());
        assertTrue("Color should be valid (not 0)", ciblage.getColor() != 0);
    }
}
