#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Convertisseur QCM HTML vers LaTeX pour auto-multiple-choice
Gère les extraits de code Python avec minted
"""

import re
import os
from bs4 import BeautifulSoup
from pathlib import Path
import html

class QCMConverter:
    def __init__(self, output_dir="codes", debug=False, layout_threshold=50, force_layout=None, use_multicol=False, multicol_columns=2, use_csv=False, element_group="general"):
        self.output_dir = Path(output_dir)
        self.output_dir.mkdir(exist_ok=True)
        self.code_counter = 0
        self.debug = debug
        self.layout_threshold = layout_threshold
        self.force_layout = force_layout  # 'horizontal', 'vertical', ou None
        self.use_multicol = use_multicol
        self.multicol_columns = multicol_columns
        self.use_csv = use_csv
        self.element_group = element_group
        
    def escape_latex_chars(self, text):
        """Échappe les caractères spéciaux LaTeX"""
        # Ordre important : & avant les autres car on utilise \& 
        replacements = [
            ('\\', '\\textbackslash{}'),  # \ doit être en premier
            ('&', '\\&'),
            ('%', '\\%'),
            ('$', '\\$'),
            ('#', '\\#'),
            ('^', '\\textasciicircum{}'),
            ('_', '\\_'),
            ('{', '\\{'),
            ('}', '\\}'),
            ('~', '\\textasciitilde{}'),
        ]
        
        for char, replacement in replacements:
            text = text.replace(char, replacement)
        
        return text
    
    def clean_html_tags(self, text):
        """Supprime les balises HTML et décode les entités"""
        # Supprimer les balises HTML
        text = re.sub(r'<[^>]+>', '', text)
        # Décoder les entités HTML
        text = html.unescape(text)
        # Nettoyer les espaces multiples et les sauts de ligne
        text = re.sub(r'\s+', ' ', text).strip()
        # Échapper les caractères spéciaux LaTeX
        text = self.escape_latex_chars(text)
        return text
    
    def format_code_with_line_breaks(self, code, max_line_length=60):
        """Formate le code en ajoutant des sauts de ligne si les lignes sont trop longues"""
        lines = code.split('\n')
        formatted_lines = []
        
        for line in lines:
            # Si la ligne est plus courte que la limite, la garder telle quelle
            if len(line) <= max_line_length:
                formatted_lines.append(line)
            else:
                # Essayer de couper intelligemment
                current_line = line
                while len(current_line) > max_line_length:
                    # Points de coupure préférés en Python
                    break_points = [', ', ' = ', ' + ', ' - ', ' * ', ' / ', ' and ', ' or ', ' if ', ' for ', ' in ']
                    
                    best_break = -1
                    for bp in break_points:
                        # Chercher le dernier point de coupure avant la limite
                        pos = current_line[:max_line_length].rfind(bp)
                        if pos > best_break and pos > max_line_length // 2:  # Au moins à mi-chemin
                            best_break = pos + len(bp)
                    
                    if best_break > 0:
                        # Couper au meilleur point trouvé
                        formatted_lines.append(current_line[:best_break].rstrip())
                        current_line = '    ' + current_line[best_break:].lstrip()  # Indenter la suite
                    else:
                        # Pas de bon point de coupure, couper brutalement
                        formatted_lines.append(current_line[:max_line_length])
                        current_line = '    ' + current_line[max_line_length:]  # Indenter la suite
                
                # Ajouter le reste de la ligne
                if current_line.strip():
                    formatted_lines.append(current_line)
        
        return '\n'.join(formatted_lines)
    
    def extract_code_from_pre(self, pre_element):
        """Extrait le code Python d'un élément <pre><code>"""
        code_element = pre_element.find('code')
        if not code_element:
            return ""
        
        # Extraire le texte en préservant la structure
        code_lines = []
        for line in code_element.get_text().split('\n'):
            # Supprimer les espaces en début de ligne de façon cohérente
            line = line.rstrip()
            code_lines.append(line)
        
        # Supprimer les lignes vides au début et à la fin
        while code_lines and not code_lines[0].strip():
            code_lines.pop(0)
        while code_lines and not code_lines[-1].strip():
            code_lines.pop()
        
        raw_code = '\n'.join(code_lines)
        
        # Formater le code avec des sauts de ligne
        formatted_code = self.format_code_with_line_breaks(raw_code)
        
        return formatted_code
    
    def save_code_to_file(self, code, filename):
        """Sauvegarde le code Python dans un fichier"""
        filepath = self.output_dir / filename
        with open(filepath, 'w', encoding='utf-8') as f:
            f.write(code)
        return filepath
    
    def process_code_blocks(self, element):
        """Traite les blocs de code et retourne le texte avec les références minted"""
        result_parts = []
        
        for child in element.children:
            if child.name == 'pre':
                # C'est un bloc de code
                code = self.extract_code_from_pre(child)
                if code.strip():
                    self.code_counter += 1
                    filename = f"code_{self.code_counter:03d}.py"
                    self.save_code_to_file(code, filename)
                    result_parts.append(f"\\inputminted[xleftmargin=20pt]{{python}}{{{self.output_dir}/{filename}}}")
            elif child.name:
                # Autre balise HTML
                result_parts.append(self.clean_html_tags(str(child)))
            else:
                # Texte simple
                result_parts.append(str(child).strip())
        
        return '\n\n'.join(part for part in result_parts if part.strip())
    
    def extract_inline_code(self, text):
        """Extrait et formate le code Python inline"""
        # D'abord échapper les caractères LaTeX normaux
        text = self.escape_latex_chars(text)
        
        # Ensuite traiter le code inline (après échappement pour éviter les conflits)
        # Recherche de code Python simple (variables, méthodes, etc.)
        patterns = [
            # Méthodes avec parenthèses
            (r'([a-zA-Z_][a-zA-Z0-9_]*\.[a-zA-Z_][a-zA-Z0-9_]*\([^)]*\))', r'\\texttt{\1}'),
            # Indexation avec crochets
            (r'([a-zA-Z_][a-zA-Z0-9_]*\[[^\]]+\])', r'\\texttt{\1}'),
            # Listes littérales
            (r'(\[[^\]]*\])', r'\\texttt{\1}'),
        ]
        
        for pattern, replacement in patterns:
            text = re.sub(pattern, replacement, text)
        
        return text
    
    def parse_question(self, question_html):
        """Parse une question HTML et retourne les données structurées"""
        soup = BeautifulSoup(question_html, 'html.parser')
        
        # Extraire le numéro de question
        question_match = re.search(r'Q(\d+)', question_html)
        if not question_match:
            return None
        
        question_num = question_match.group(1)
        
        # Vérifier s'il y a plusieurs questions dans ce HTML
        all_question_matches = list(re.finditer(r'Q(\d+)\s*-', question_html))
        if len(all_question_matches) > 1:
            # Il y a plusieurs questions, extraire seulement la première
            first_q_start = all_question_matches[0].start()
            second_q_start = all_question_matches[1].start()
            
            # Chercher le début du tag <p> qui contient la première question
            p_start = question_html.rfind('<p>', 0, first_q_start + 50)
            if p_start != -1:
                first_q_start = p_start
            
            question_html = question_html[first_q_start:second_q_start]
            soup = BeautifulSoup(question_html, 'html.parser')
            
            if self.debug:
                print(f"DEBUG Q{question_num} - Question tronquée (multiple détectée) de {first_q_start} à {second_q_start}")
                print(f"DEBUG Q{question_num} - HTML tronqué: {question_html[:150]}...")
        
        # Séparer le HTML en section question et section réponses
        responses_section_start = question_html.find("Réponses :")
        if responses_section_start != -1:
            question_html_part = question_html[:responses_section_start]
            responses_html_part = question_html[responses_section_start:]
        else:
            question_html_part = question_html
            responses_html_part = ""
        
        # Parser la section question de manière séquentielle
        question_soup = BeautifulSoup(question_html_part, 'html.parser')
        question_parts = []
        
        # Si le HTML est mal formé (pas de <p> d'ouverture), le réparer
        if not question_html_part.strip().startswith('<'):
            question_html_part = '<p>' + question_html_part
            question_soup = BeautifulSoup(question_html_part, 'html.parser')
        
        # Traiter séquentiellement tous les éléments de la question
        for element in question_soup.find_all(['p', 'pre']):
            if element.name == 'p':
                text = element.get_text().strip()
                if f'Q{question_num}' in text:
                    # Texte principal de la question (sans le numéro)
                    # Trouver la position de Q{num} et prendre le texte après
                    q_pos = text.find(f'Q{question_num}')
                    if q_pos != -1:
                        clean_text = text[q_pos + len(f'Q{question_num}'):].strip(' -').strip()
                        clean_text = self.clean_html_tags(clean_text)
                        if clean_text:
                            question_parts.append(clean_text)
                elif text and text != "Réponses :" and not re.match(r'^Q\d+\s*-', text):
                    # Texte additionnel de la question (éviter les questions parasites)
                    clean_text = self.clean_html_tags(text)
                    if clean_text:
                        question_parts.append(clean_text)
            elif element.name == 'pre':
                # Bloc de code dans la question
                code = self.extract_code_from_pre(element)
                if code.strip():
                    self.code_counter += 1
                    filename = f"q{question_num}_{self.code_counter}.py"
                    self.save_code_to_file(code, filename)
                    question_parts.append(f"\\inputminted[xleftmargin=20pt]{{python}}{{{self.output_dir}/{filename}}}")
        
        # Parser les réponses de manière plus intelligente
        responses = []
        if responses_html_part:
            responses_soup = BeautifulSoup(responses_html_part, 'html.parser')
            
            # Analyser séquentiellement tous les éléments après "Réponses :"
            response_elements = responses_soup.find_all(['p', 'pre'])
            current_response = None
            
            for element in response_elements:
                if element.name == 'p':
                    text = element.get_text().strip()
                    
                    # Vérifier si c'est le début d'une nouvelle question (Q[0-9]+)
                    if re.match(r'^Q\d+\s*-', text):
                        if self.debug:
                            print(f"DEBUG Q{question_num} - Nouvelle question détectée dans les réponses: {text[:50]}")
                        break  # Arrêter le parsing des réponses
                    
                    if self.debug:
                        print(f"DEBUG Q{question_num} - Element P: {repr(text[:100])}")
                    
                    # Vérifier si c'est une nouvelle réponse (A-, B-, C-, D-)
                    response_match = re.match(r'^(>|&gt;)?([A-D])-\s*(.*)', text)
                    if response_match:
                        # Sauvegarder la réponse précédente si elle existe
                        if current_response is not None:
                            responses.append(current_response)
                        
                        # Commencer une nouvelle réponse
                        prefix = response_match.group(1) or ""
                        letter = response_match.group(2)
                        response_text = response_match.group(3).strip()
                        
                        # Nettoyer le texte
                        if response_text:
                            response_text = self.clean_html_tags(response_text)
                        
                        # Vérifier si c'est la bonne réponse
                        is_correct = element.find('span', class_='ok') is not None
                        
                        current_response = {
                            'letter': letter,
                            'text': response_text,
                            'correct': is_correct
                        }
                        
                        if self.debug:
                            print(f"DEBUG Q{question_num} - Nouvelle réponse {letter}: '{response_text}' (correct: {is_correct})")
                    
                    elif text == "Réponses :" or not text.strip():
                        # Ignorer les titres et paragraphes vides
                        continue
                    else:
                        # Texte additionnel pour la réponse actuelle
                        if current_response is not None and text:
                            additional_text = self.clean_html_tags(text)
                            if current_response['text']:
                                current_response['text'] += " " + additional_text
                            else:
                                current_response['text'] = additional_text
                
                elif element.name == 'pre':
                    # Bloc de code pour la réponse actuelle
                    if current_response is not None:
                        code = self.extract_code_from_pre(element)
                        if code.strip():
                            self.code_counter += 1
                            filename = f"r{question_num}_{current_response['letter'].lower()}.py"
                            self.save_code_to_file(code, filename)
                            code_block = f"\\inputminted[xleftmargin=20pt]{{python}}{{{self.output_dir}/{filename}}}"
                            
                            if current_response['text']:
                                current_response['text'] += "\n\n" + code_block
                            else:
                                current_response['text'] = code_block
                            
                            if self.debug:
                                print(f"DEBUG Q{question_num} - Code ajouté à réponse {current_response['letter']}")
            
            # Ajouter la dernière réponse
            if current_response is not None:
                responses.append(current_response)
            
            # Vérification de sécurité : chercher des bonnes réponses manquées
            if not any(resp['correct'] for resp in responses):
                # Chercher dans le HTML brut des patterns de bonne réponse
                if '<span class="ok">' in responses_html_part:
                    # Chercher quel élément contient le span.ok
                    ok_elements = responses_soup.find_all('span', class_='ok')
                    for ok_element in ok_elements:
                        parent_text = ok_element.parent.get_text() if ok_element.parent else ""
                        
                        # Déterminer quelle lettre correspond
                        for letter in ['A', 'B', 'C', 'D']:
                            if f'{letter}-' in parent_text or f'>{letter}-' in parent_text or f'&gt;{letter}-' in parent_text:
                                # Marquer cette réponse comme correcte
                                for resp in responses:
                                    if resp['letter'] == letter:
                                        resp['correct'] = True
                                        if self.debug:
                                            print(f"DEBUG Q{question_num} - Correction: Réponse {letter} marquée comme correcte")
                                        break
                                break
            
            # Convertir en format final (sans la lettre)
            final_responses = []
            for resp in responses:
                final_responses.append({
                    'text': resp['text'],
                    'correct': resp['correct']
                })
            responses = final_responses
        
        # S'assurer qu'on a exactement 4 réponses
        while len(responses) < 4:
            responses.append({
                'text': '',
                'correct': False
            })
        
        # Limiter à 4 réponses maximum
        responses = responses[:4]
        
        if self.debug:
            print(f"DEBUG Q{question_num} - HTML partie question: {question_html_part[:200]}...")
            print(f"DEBUG Q{question_num} - HTML partie réponses: {responses_html_part[:200]}...")
            print(f"DEBUG Q{question_num} - Question finale: {len(question_parts)} parties")
            print(f"DEBUG Q{question_num} - Parties de question: {[part[:50] + '...' if len(part) > 50 else part for part in question_parts]}")
            print(f"DEBUG Q{question_num} - Réponses finales: {len(responses)} réponses")
            for i, resp in enumerate(responses):
                correct_marker = "✓" if resp['correct'] else "✗"
                text_preview = resp['text'][:80] + ('...' if len(resp['text']) > 80 else '')
                print(f"DEBUG Q{question_num} - Réponse {['A','B','C','D'][i]}: {correct_marker} {text_preview}")
        
        return {
            'number': question_num,
            'text': '\n\n'.join(question_parts),
            'responses': responses
        }
    
    def get_latex_header(self):
        """Retourne l'en-tête LaTeX complet pour AMC"""
        return """\\documentclass[12pt,a4paper]{article}

\\usepackage{csvsimple}%

\\usepackage[francais,bloc]{automultiplechoice}

\\usepackage{minted}
%\\usepackage{ulem}
\\usepackage{multicol}
\\let\\multicolmulticols\\multicols
\\let\\endmulticolmulticols\\endmulticols

\\RenewDocumentEnvironment{multicols}{mO{}}
 {%
  \\ifnum#1=1
    #2%
  \\else % More than 1 column
    \\multicolmulticols{#1}[#2]
  \\fi
 }
 {%
  \\ifnum#1=1
  \\else % More than 1 column
    \\endmulticolmulticols
  \\fi
 }


\\usepackage{xcolor}
\\definecolor{LightGray}{gray}{0.9}

% Définition des commandes AMC pour éviter les erreurs
\\def\\nom{NOM}
\\def\\prenom{PRENOM}
\\def\\id{NUMERO}

\\newcommand{\\sujet}{
\\exemplaire{1}{%

%%% debut de l'en-tête des copies :  
\\begin{center}
\\noindent{}\\fbox{\\vspace*{3mm}
         \\Large\\bf\\nom{}~\\prenom{}\\normalsize{}% 
          \\vspace*{3mm}
      }
\\end{center}

\\noindent{\\bf QCM  \\hfill TEST}

\\vspace*{.5cm}
\\begin{minipage}{.4\\linewidth}
  \\centering\\large\\bf Test\\\\ Examen du 01/01/2008
\\end{minipage}

\\begin{center}\\em
Durée : 10 minutes.

  Aucun document n'est autorisé.
  L'usage de la calculatrice est interdit.

  Les questions faisant apparaître le symbole \\multiSymbole{} peuvent
  présenter zéro, une ou plusieurs bonnes réponses. Les autres ont
  une unique bonne réponse.

  Des points négatifs pourront être affectés à de \\emph{très
    mauvaises} réponses.
\\end{center}
\\vspace{1ex}
%%% fin de l'en-tête

\\restituegroupe{""" + self.element_group + """}
 

\\AMCassociation{\\id}

%\\AMCaddpagesto{3}
	  }
}

%%%%§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§

\\begin{document}
%%%Options
\\AMCrandomseed{1237893}

\\def\\AMCformQuestion#1{{\\sc Question #1 :}}

\\setdefaultgroupmode{withoutreplacement}
%%% Fin Options

%%% groupes

% Questions générées automatiquement"""

    def get_latex_footer(self):
        """Retourne le pied de page LaTeX pour AMC"""
        if self.use_csv:
            return f"""

\\csvreader[head to column names]{{liste.csv}}{{}}{{\\sujet}}

\\end{{document}}"""
        else:
            return f"""

\\sujet

\\end{{document}}"""

    def analyze_code_complexity(self, question_text, responses):
        """Analyse la complexité du code dans la question et les réponses"""
        # Compter les blocs de code dans la question
        question_code_blocks = question_text.count('\\inputminted')
        
        # Détecter les codes longs dans la question (plus de 2 blocs = complexe)
        has_long_question_code = question_code_blocks > 2
        
        # Analyser les réponses
        response_code_blocks = sum(1 for resp in responses if '\\inputminted' in resp['text'])
        has_code_in_responses = response_code_blocks > 0
        
        return {
            'question_code_blocks': question_code_blocks,
            'response_code_blocks': response_code_blocks,
            'has_long_question_code': has_long_question_code,
            'has_code_in_responses': has_code_in_responses
        }

    def should_use_horizontal_layout(self, question_text, responses):
        """Détermine si on doit utiliser un layout horizontal ou vertical"""
        # Si un layout est forcé, l'utiliser
        if self.force_layout == 'horizontal':
            return True
        elif self.force_layout == 'vertical':
            return False
        
        # Analyser la complexité du code
        code_analysis = self.analyze_code_complexity(question_text, responses)
        
        # Si la question a beaucoup de code, forcer vertical pour les réponses
        if code_analysis['has_long_question_code']:
            return False
            
        # Si les réponses contiennent du code, forcer vertical
        if code_analysis['has_code_in_responses']:
            return False
        
        # Vérifier si toutes les réponses sont courtes
        all_short = all(len(resp['text']) <= self.layout_threshold for resp in responses)
        
        # Vérifier si aucune réponse ne contient de code multilignes
        no_multiline_code = all('\\inputminted' not in resp['text'] and '\n' not in resp['text'] 
                               for resp in responses)
        
        return all_short and no_multiline_code

    def should_use_multicol(self, question_text, responses):
        """Détermine si on doit utiliser multicol pour cette question"""
        if not self.use_multicol:
            return False
        
        # Analyser la complexité du code
        code_analysis = self.analyze_code_complexity(question_text, responses)
        
        # Ne pas utiliser multicol si la question a beaucoup de code
        if code_analysis['has_long_question_code']:
            return False
            
        # Ne jamais utiliser multicol s'il y a du code dans les réponses
        if code_analysis['has_code_in_responses']:
            return False
        
        # Calculer la longueur moyenne des réponses
        valid_responses = [resp for resp in responses if resp['text'].strip()]
        if not valid_responses:
            return False
            
        avg_length = sum(len(resp['text']) for resp in valid_responses) / len(valid_responses)
        max_length = max(len(resp['text']) for resp in valid_responses)
        
        # Utiliser multicol seulement pour les réponses très courtes
        return avg_length <= 25 and max_length <= 35

    def determine_multicol_columns(self, responses):
        """Détermine le nombre optimal de colonnes pour multicol"""
        valid_responses = [resp for resp in responses if resp['text'].strip()]
        if not valid_responses:
            return 2
            
        avg_length = sum(len(resp['text']) for resp in valid_responses) / len(valid_responses)
        max_length = max(len(resp['text']) for resp in valid_responses)
        
        # Réponses très courtes -> 4 colonnes
        if avg_length <= 15 and max_length <= 20 and len(valid_responses) == 4:
            return 4
        # Réponses courtes -> 2 colonnes  
        elif avg_length <= 25 and max_length <= 35:
            return 2
        else:
            return 2  # fallback

    def generate_latex(self, question_data):
        """Génère le code LaTeX pour une question"""
        latex_parts = []
        
        # Encapsuler chaque question dans son propre element (même groupe pour toutes)
        latex_parts.append(f"\\element{{{self.element_group}}}{{")
        latex_parts.append(f"\\begin{{question}}{{q{question_data['number']}}}")
        latex_parts.append("")
        latex_parts.append(question_data['text'])
        latex_parts.append("")
        
        # Choisir le layout selon la longueur des réponses et la complexité du code
        use_horizontal = self.should_use_horizontal_layout(question_data['text'], question_data['responses'])
        use_multicol = self.should_use_multicol(question_data['text'], question_data['responses'])
        
        # Filtrer les réponses vides
        valid_responses = [resp for resp in question_data['responses'] if resp['text'].strip()]
        
        if use_multicol and len(valid_responses) > 0:
            # Déterminer le nombre optimal de colonnes
            optimal_columns = self.determine_multicol_columns(valid_responses)
            layout_env = "reponses"
            latex_parts.append(f"  \\begin{{multicols}}{{{optimal_columns}}}")
            latex_parts.append(f"  \\begin{{{layout_env}}}")
        else:
            layout_env = "reponseshoriz" if use_horizontal else "reponses"
            latex_parts.append(f"  \\begin{{{layout_env}}}")
        
        if self.debug:
            code_analysis = self.analyze_code_complexity(question_data['text'], question_data['responses'])
            total_length = sum(len(resp['text']) for resp in valid_responses)
            avg_length = total_length / len(valid_responses) if valid_responses else 0
            
            layout_info = f"{layout_env}"
            if use_multicol:
                optimal_columns = self.determine_multicol_columns(valid_responses)
                layout_info += f" + multicol({optimal_columns})"
            if self.force_layout:
                layout_info += f" (forcé: {self.force_layout})"
            if code_analysis['has_long_question_code']:
                layout_info += " (vertical: code long dans question)"
            elif code_analysis['has_code_in_responses']:
                layout_info += " (vertical: code dans réponses)"
                
            print(f"DEBUG Q{question_data['number']} - Layout: {layout_info}")
            print(f"DEBUG Q{question_data['number']} - Code: {code_analysis['question_code_blocks']} blocs question, {code_analysis['response_code_blocks']} blocs réponses")
            print(f"DEBUG Q{question_data['number']} - Réponses: {len(valid_responses)} valides, longueur moy: {avg_length:.1f}")
        
        for resp in valid_responses:
            command = "\\bonne" if resp['correct'] else "\\mauvaise"
            latex_parts.append(f"    {command}{{{resp['text']}}}")
        
        if use_multicol and len(valid_responses) > 0:
            latex_parts.append(f"  \\end{{{layout_env}}}")
            latex_parts.append(f"  \\end{{multicols}}")
        else:
            latex_parts.append(f"  \\end{{{layout_env}}}")
        
        latex_parts.append("\\end{question}")
        latex_parts.append("}")  # Fermer l'element
        latex_parts.append("")
        
        return '\n'.join(latex_parts)
    
    def parse_html_file(self, html_content):
        """Parse un fichier HTML complet et extrait toutes les questions"""
        # D'abord essayer de séparer par <hr>
        if '<hr>' in html_content:
            questions_html = html_content.split('<hr>')
        else:
            # Pas de <hr>, chercher les questions par pattern Q[0-9]+
            questions_html = []
            
            # Chercher tous les patterns Q[numéro] dans le texte
            question_pattern = r'<p>\s*Q(\d+)\s*-'
            matches = list(re.finditer(question_pattern, html_content))
            
            if matches:
                for i, match in enumerate(matches):
                    start = match.start()
                    # Fin = début de la question suivante ou fin du document
                    end = matches[i + 1].start() if i + 1 < len(matches) else len(html_content)
                    
                    question_html = html_content[start:end]
                    questions_html.append(question_html)
                    
                    if self.debug:
                        question_num = match.group(1)
                        print(f"DEBUG - Question Q{question_num} trouvée de {start} à {end}")
            else:
                # Fallback : traiter tout comme une seule question
                questions_html = [html_content]
        
        questions_data = []
        for q_html in questions_html:
            if 'Q' in q_html and '- ' in q_html:  # Vérifier qu'il y a bien une question
                question_data = self.parse_question(q_html)
                if question_data:
                    questions_data.append(question_data)
        
        return questions_data
    
    def convert_file(self, input_file, output_file, full_document=False):
        """Convertit un fichier HTML en LaTeX"""
        with open(input_file, 'r', encoding='utf-8') as f:
            html_content = f.read()
        
        questions = self.parse_html_file(html_content)
        
        latex_content = []
        
        if full_document:
            latex_content.append(self.get_latex_header())
        else:
            latex_content.append("% Questions générées automatiquement")
        
        latex_content.append("")
        
        for question in questions:
            latex_content.append(self.generate_latex(question))
        
        if full_document:
            latex_content.append(self.get_latex_footer())
        
        with open(output_file, 'w', encoding='utf-8') as f:
            f.write('\n'.join(latex_content))
        
        print(f"Conversion terminée !")
        print(f"- {len(questions)} questions converties")
        print(f"- {self.code_counter} fichiers de code créés dans {self.output_dir}/")
        print(f"- Fichier LaTeX généré : {output_file}")
        if full_document:
            print(f"- Document LaTeX complet généré (prêt à compiler)")
            if self.use_csv:
                print(f"- Mode CSV activé (nécessite liste.csv)")
            else:
                print(f"- Mode simple activé (\\sujet)")
            print(f"- Groupe d'éléments : {self.element_group}")
        if self.force_layout:
            print(f"- Layout forcé : {self.force_layout}")
        if self.use_multicol:
            print(f"- Multicol activé : {self.multicol_columns} colonnes pour réponses courtes")
        if self.debug:
            print(f"- Mode debug était activé")

def main():
    """Fonction principale"""
    import argparse
    
    parser = argparse.ArgumentParser(description='Convertit un QCM HTML vers LaTeX AMC')
    parser.add_argument('input_file', help='Fichier HTML d\'entrée')
    parser.add_argument('-o', '--output', default='qcm.tex', help='Fichier LaTeX de sortie')
    parser.add_argument('-c', '--codes-dir', default='codes', help='Répertoire pour les fichiers de code')
    parser.add_argument('-d', '--debug', action='store_true', help='Active le mode debug avec informations détaillées')
    parser.add_argument('-f', '--full-document', action='store_true', help='Génère un document LaTeX complet (avec documentclass, packages et structure AMC)')
    parser.add_argument('--csv', action='store_true', help='Utilise \\csvreader au lieu de \\sujet (nécessite liste.csv)')
    parser.add_argument('-g', '--element-group', default='general', help='Nom du groupe d\'éléments pour AMC (défaut: general)')
    
    # Options de layout
    layout_group = parser.add_argument_group('Options de mise en page')
    layout_group.add_argument('--layout-threshold', type=int, default=50, help='Seuil de longueur pour choisir le layout horizontal (défaut: 50)')
    layout_group.add_argument('--force-horizontal', action='store_true', help='Force le layout horizontal pour toutes les réponses')
    layout_group.add_argument('--force-vertical', action='store_true', help='Force le layout vertical pour toutes les réponses')
    layout_group.add_argument('--multicol', action='store_true', help='Active l\'utilisation de multicol pour les réponses très courtes')
    layout_group.add_argument('--multicol-columns', type=int, default=2, help='Nombre de colonnes pour multicol (défaut: 2)')
    
    args = parser.parse_args()
    
    # Vérifier les conflits d'options
    if args.force_horizontal and args.force_vertical:
        parser.error("--force-horizontal et --force-vertical ne peuvent pas être utilisés ensemble")
    
    # Déterminer le layout forcé
    force_layout = None
    if args.force_horizontal:
        force_layout = 'horizontal'
    elif args.force_vertical:
        force_layout = 'vertical'
    
    converter = QCMConverter(
        output_dir=args.codes_dir, 
        debug=args.debug,
        layout_threshold=args.layout_threshold,
        force_layout=force_layout,
        use_multicol=args.multicol,
        multicol_columns=args.multicol_columns,
        use_csv=args.csv,
        element_group=args.element_group
    )
    converter.convert_file(args.input_file, args.output, full_document=args.full_document)

if __name__ == '__main__':
    main()