#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
La Convertoche - Visualiseur de conversion d'unités métriques
Reproduit le tableau de conversion de l'école primaire dans le terminal.
"""

import argparse
import os
import random
import sys

__version__ = "1.0.0"
from decimal import Decimal, InvalidOperation
from typing import Optional, Tuple

# Force UTF-8 pour Windows
if sys.platform == "win32":
    sys.stdout.reconfigure(encoding="utf-8")
    os.system("")  # Active les séquences ANSI sur Windows

from rich.console import Console
from rich.panel import Panel
from rich.prompt import Prompt
from rich.table import Table
from rich.text import Text

# ============================================================================
# CONFIGURATION DES UNITÉS
# ============================================================================

UNIT_FAMILIES = {
    "longueur": {
        "units": ["km", "hm", "dam", "m", "dm", "cm", "mm"],
        "base": "m",
        "color": "blue",
        "title": "Longueurs",
        "imperial": {
            "inch": 39.3701,
            "feet": 3.28084,
        },
    },
    "poids": {
        "units": ["kg", "hg", "dag", "g", "dg", "cg", "mg"],
        "base": "g",
        "color": "green",
        "title": "Poids / Masses",
        "imperial": {
            "lbs": 0.00220462,
            "oz": 0.035274,
        },
    },
    "capacite": {
        "units": ["kL", "hL", "daL", "L", "dL", "cL", "mL"],
        "base": "L",
        "color": "yellow",
        "title": "Capacités / Volumes",
        "imperial": {
            "gallon (US)": 0.264172,
            "quart (US)": 1.05669,
        },
    },
}

# Console Rich globale avec couleurs forcées
console = Console(force_terminal=True, color_system="auto")


# ============================================================================
# FORMATAGE DES NOMBRES
# ============================================================================


def format_number_fr(value: float | Decimal, decimals: int = 4, use_thousands_sep: bool = True) -> str:
    """
    Formate un nombre avec la notation française (virgule, espace pour milliers).

    Args:
        value: La valeur à formater
        decimals: Nombre de décimales max
        use_thousands_sep: Si True, ajoute des espaces comme séparateur de milliers

    Returns:
        Le nombre formaté avec virgule et séparateur de milliers
    """
    # Convertit en float si Decimal
    num = float(value)

    # Formate avec le bon nombre de décimales significatives
    if num == int(num):
        formatted = str(int(num))
    else:
        # Supprime les zéros inutiles
        formatted = f"{num:.{decimals}g}"

    # Sépare partie entière et décimale
    if "." in formatted:
        integer_part, decimal_part = formatted.split(".")
    else:
        integer_part = formatted
        decimal_part = ""

    # Ajoute le séparateur de milliers (espace) à la partie entière
    if use_thousands_sep and len(integer_part) > 3:
        # Gère le signe négatif
        is_negative = integer_part.startswith("-")
        if is_negative:
            integer_part = integer_part[1:]

        # Ajoute les espaces tous les 3 chiffres depuis la droite
        parts = []
        while integer_part:
            parts.append(integer_part[-3:])
            integer_part = integer_part[:-3]
        integer_part = " ".join(reversed(parts))

        if is_negative:
            integer_part = "-" + integer_part

    # Reconstruit avec la virgule française
    if decimal_part:
        return f"{integer_part},{decimal_part}"
    return integer_part


# ============================================================================
# LOGIQUE DE PARSING
# ============================================================================


def parse_value(value_str: str, allow_negative: bool = False) -> Decimal:
    """
    Parse une valeur numérique en acceptant . et , comme séparateur décimal.

    Args:
        value_str: La chaîne représentant le nombre
        allow_negative: Si False, rejette les valeurs négatives

    Returns:
        La valeur en Decimal

    Raises:
        ValueError: Si la valeur n'est pas un nombre valide ou est négative
    """
    # Normalise les virgules en points
    normalized = value_str.strip().replace(",", ".")

    try:
        value = Decimal(normalized)
    except InvalidOperation:
        raise ValueError(f"'{value_str}' n'est pas un nombre valide")

    # Vérifie si la valeur est négative
    if not allow_negative and value < 0:
        raise ValueError("Les valeurs négatives ne sont pas acceptées pour les unités physiques")

    return value


def find_unit_family(unit: str) -> Optional[Tuple[str, dict]]:
    """
    Trouve la famille d'unités correspondant à une unité donnée.

    Args:
        unit: L'unité à rechercher (sensible à la casse pour L)

    Returns:
        Tuple (nom_famille, config_famille) ou None si non trouvée
    """
    unit_lower = unit.lower()

    for family_name, family_config in UNIT_FAMILIES.items():
        units_lower = [u.lower() for u in family_config["units"]]
        if unit_lower in units_lower:
            return family_name, family_config

    return None


def get_unit_index(unit: str, family_config: dict) -> int:
    """
    Retourne l'index de l'unité dans sa famille.

    Args:
        unit: L'unité à chercher
        family_config: La configuration de la famille

    Returns:
        L'index de l'unité (0 = kilo, 6 = milli)
    """
    unit_lower = unit.lower()
    units_lower = [u.lower() for u in family_config["units"]]
    return units_lower.index(unit_lower)


def normalize_unit(unit: str, family_config: dict) -> str:
    """
    Normalise l'unité pour l'affichage (respecte la casse originale).

    Args:
        unit: L'unité entrée par l'utilisateur
        family_config: La configuration de la famille

    Returns:
        L'unité avec la casse correcte
    """
    unit_lower = unit.lower()
    for canonical_unit in family_config["units"]:
        if canonical_unit.lower() == unit_lower:
            return canonical_unit
    return unit


# ============================================================================
# LOGIQUE DE CONVERSION ET TABLEAU
# ============================================================================


def convert_to_base(value: Decimal, unit: str, family_config: dict) -> Decimal:
    """
    Convertit une valeur vers l'unité de base de sa famille.

    Args:
        value: La valeur à convertir
        unit: L'unité source
        family_config: La configuration de la famille

    Returns:
        La valeur en unité de base
    """
    unit_index = get_unit_index(unit, family_config)
    base_index = get_unit_index(family_config["base"], family_config)

    # Chaque rang = facteur 10
    power = base_index - unit_index
    return value * (Decimal(10) ** power)


def build_digit_placement(value: Decimal, unit: str, family_config: dict) -> Tuple[list, bool, bool]:
    """
    Construit le placement des chiffres dans le tableau de conversion.

    L'algorithme place le chiffre des unités (juste avant la virgule)
    dans la colonne de l'unité source.

    Args:
        value: La valeur à placer
        unit: L'unité source
        family_config: La configuration de la famille

    Returns:
        Tuple contenant:
        - Liste de 7 éléments (un par colonne) avec les chiffres à afficher
        - Bool indiquant un débordement à gauche (partie entière trop grande)
        - Bool indiquant un débordement à droite (partie décimale tronquée)
    """
    unit_index = get_unit_index(unit, family_config)

    # Sépare partie entière et décimale
    str_value = str(value)
    if "." in str_value:
        integer_part, decimal_part = str_value.split(".")
    else:
        integer_part = str_value
        decimal_part = ""

    # Initialise le tableau avec des espaces vides
    placement = [""] * 7
    overflow_left = False
    overflow_right = False

    # Vérifie le débordement à gauche (partie entière)
    if len(integer_part) > unit_index + 1:
        overflow_left = True

    # Vérifie le débordement à droite (partie décimale)
    max_decimals = 6 - unit_index  # Colonnes disponibles après l'unité
    if len(decimal_part) > max_decimals:
        overflow_right = True

    # Place les chiffres de la partie entière (de droite à gauche depuis l'unité)
    for i, digit in enumerate(reversed(integer_part)):
        col_index = unit_index - i
        if 0 <= col_index < 7:
            placement[col_index] = digit

    # Place les chiffres de la partie décimale (de gauche à droite après l'unité)
    for i, digit in enumerate(decimal_part):
        col_index = unit_index + 1 + i
        if 0 <= col_index < 7:
            placement[col_index] = digit

    return placement, overflow_left, overflow_right


def find_decimal_position(unit_index: int, value: Decimal) -> int:
    """
    Trouve la position de la virgule dans le tableau.

    Args:
        unit_index: L'index de l'unité source
        value: La valeur originale

    Returns:
        L'index de la colonne après laquelle placer la virgule (-1 si pas de décimale)
    """
    if value == value.to_integral_value():
        return -1  # Pas de partie décimale
    return unit_index


# ============================================================================
# AFFICHAGE RICH
# ============================================================================


def get_responsive_column_width() -> int:
    """
    Calcule la largeur optimale des colonnes en fonction du terminal.

    Returns:
        La largeur minimale de chaque colonne (entre 3 et 6)
    """
    terminal_width = console.width or 80
    # 7 colonnes + bordures (~14 chars) + padding (7*2=14 chars)
    available_width = terminal_width - 28
    col_width = max(3, min(6, available_width // 7))
    return col_width


def create_conversion_table(value: Decimal, unit: str, family_name: str, family_config: dict) -> Tuple[Table, bool, bool]:
    """
    Crée le tableau de conversion Rich.

    Args:
        value: La valeur à afficher
        unit: L'unité source
        family_name: Le nom de la famille
        family_config: La configuration de la famille

    Returns:
        Tuple contenant:
        - Le tableau Rich configuré
        - Bool indiquant un débordement à gauche
        - Bool indiquant un débordement à droite
    """
    color = family_config["color"]
    units = family_config["units"]
    col_width = get_responsive_column_width()

    # Crée le tableau
    table = Table(
        title=f"[bold {color}]{family_config['title']}[/]",
        show_header=True,
        header_style=f"bold {color}",
        border_style=color,
        padding=(0, 1),
        expand=False,
    )

    # Ajoute les colonnes (une par unité)
    unit_index = get_unit_index(unit, family_config)
    for i, u in enumerate(units):
        style = f"bold {color} reverse" if i == unit_index else color
        table.add_column(u, justify="center", style=style, min_width=col_width)

    # Construit le placement des chiffres
    placement, overflow_left, overflow_right = build_digit_placement(value, unit, family_config)
    decimal_pos = find_decimal_position(unit_index, value)

    # Formate les cellules avec la virgule
    cells = []
    for i, digit in enumerate(placement):
        cell_content = digit if digit else " "
        # Ajoute la virgule après le chiffre si nécessaire
        if i == decimal_pos and decimal_pos < 6:
            cell_content = cell_content + ","
        cells.append(cell_content)

    table.add_row(*cells)

    return table, overflow_left, overflow_right


def create_conversions_panel(value: Decimal, unit: str, family_config: dict) -> Panel:
    """
    Crée le panneau des conversions rapides.

    Args:
        value: La valeur originale
        unit: L'unité source
        family_config: La configuration de la famille

    Returns:
        Le panneau Rich avec les conversions
    """
    color = family_config["color"]
    base_unit = family_config["base"]

    # Conversion vers l'unité de base
    base_value = convert_to_base(value, unit, family_config)

    # Construit le texte des conversions
    lines = []

    # Valeur en unité de base (métrique)
    base_formatted = format_number_fr(base_value, 6)
    lines.append(f"[bold]Valeur en {base_unit}:[/] {base_formatted} {base_unit}")

    # Conversions impériales
    lines.append("")
    lines.append("[bold]Conversions impériales:[/]")
    for imperial_unit, factor in family_config["imperial"].items():
        imperial_value = float(base_value) * factor
        imperial_formatted = format_number_fr(imperial_value, 4)
        lines.append(f"  {imperial_formatted} {imperial_unit}")

    content = "\n".join(lines)

    return Panel(
        content,
        title=f"[bold {color}]Conversions rapides[/]",
        border_style=color,
        padding=(1, 2),
    )


def convert_between_units(value: Decimal, source_unit: str, target_unit: str, family_config: dict) -> Decimal:
    """
    Convertit une valeur d'une unité à une autre dans la même famille.

    Args:
        value: La valeur à convertir
        source_unit: L'unité source
        target_unit: L'unité cible
        family_config: La configuration de la famille

    Returns:
        La valeur convertie
    """
    source_index = get_unit_index(source_unit, family_config)
    target_index = get_unit_index(target_unit, family_config)

    # Chaque rang = facteur 10
    power = target_index - source_index
    return value * (Decimal(10) ** power)


def display_target_conversion(value: Decimal, source_unit: str, target_unit: str, family_config: dict) -> None:
    """Affiche la conversion vers l'unité cible."""
    converted = convert_between_units(value, source_unit, target_unit, family_config)
    normalized_target = normalize_unit(target_unit, family_config)
    converted_formatted = format_number_fr(converted, 10)

    color = family_config["color"]
    console.print(Panel(
        f"[bold]{converted_formatted}[/] {normalized_target}",
        title=f"[bold {color}]Conversion vers {normalized_target}[/]",
        border_style=color,
        padding=(0, 2),
    ))
    console.print()


def display_overflow_warning(overflow_left: bool, overflow_right: bool) -> None:
    """Affiche un avertissement si la valeur déborde du tableau."""
    if not overflow_left and not overflow_right:
        return

    messages = []
    if overflow_left:
        messages.append("La partie entière dépasse le tableau (chiffres tronqués à gauche)")
    if overflow_right:
        messages.append("La partie décimale dépasse le tableau (chiffres tronqués à droite)")

    console.print(Panel(
        "\n".join(f"[bold yellow]⚠[/] {msg}" for msg in messages),
        title="[bold yellow]Attention[/]",
        border_style="yellow",
        padding=(0, 2),
    ))
    console.print()


def display_result(value: Decimal, unit: str, target_unit: Optional[str] = None, copy_result: bool = False) -> None:
    """
    Affiche le résultat complet (tableau + conversions).

    Args:
        value: La valeur à convertir
        unit: L'unité source
        target_unit: L'unité cible optionnelle pour conversion directe
        copy_result: Si True, copie le résultat dans le presse-papier
    """
    # Trouve la famille
    result = find_unit_family(unit)
    if result is None:
        display_error(f"Unité '{unit}' non reconnue. Utilisez --list pour voir les unités disponibles.")
        return

    family_name, family_config = result
    normalized_unit = normalize_unit(unit, family_config)

    # Vérifie l'unité cible si spécifiée
    if target_unit:
        target_result = find_unit_family(target_unit)
        if target_result is None:
            display_error(f"Unité cible '{target_unit}' non reconnue.")
            return
        target_family_name, _ = target_result
        if target_family_name != family_name:
            display_error(f"Impossible de convertir entre familles différentes ({family_config['title']} → {target_result[1]['title']})")
            return

    # Stocke le résultat pour copie
    set_last_result(value, unit, target_unit, family_config)

    console.print()

    # Affiche l'entrée formatée
    value_formatted = format_number_fr(value, 10)
    console.print(
        Panel(
            f"[bold]{value_formatted}[/] {normalized_unit}",
            title="[bold]Valeur entrée[/]",
            border_style="white",
            padding=(0, 2),
        )
    )

    console.print()

    # Affiche le tableau de conversion
    table, overflow_left, overflow_right = create_conversion_table(value, unit, family_name, family_config)
    console.print(table)

    console.print()

    # Affiche l'avertissement de débordement si nécessaire
    display_overflow_warning(overflow_left, overflow_right)

    # Affiche la conversion vers l'unité cible si spécifiée
    if target_unit:
        display_target_conversion(value, unit, target_unit, family_config)

    # Affiche les conversions rapides
    panel = create_conversions_panel(value, unit, family_config)
    console.print(panel)

    # Copie dans le presse-papier si demandé
    if copy_result and last_result:
        if copy_to_clipboard(last_result):
            console.print()
            console.print(f"[green]✓ Copié dans le presse-papier : {last_result}[/]")


def display_units_list() -> None:
    """Affiche la liste de toutes les unités supportées."""
    console.print()
    console.print("[bold]La Convertoche[/] - Unités supportées", style="bold underline")
    console.print()

    for family_name, family_config in UNIT_FAMILIES.items():
        color = family_config["color"]
        units = family_config["units"]

        console.print(f"[bold {color}]{family_config['title']}[/]")
        console.print(f"  Unités : {' | '.join(units)}")
        console.print(f"  Base : {family_config['base']}")
        console.print()


def display_error(message: str) -> None:
    """Affiche un message d'erreur formaté."""
    console.print()
    console.print(Panel(
        f"[bold red]{message}[/]",
        title="[bold red]Erreur[/]",
        border_style="red",
        padding=(0, 2),
    ))


def display_welcome() -> None:
    """Affiche le message de bienvenue."""
    welcome_text = Text()
    welcome_text.append("La Convertoche", style="bold magenta")
    welcome_text.append("\n")
    welcome_text.append("Le tableau de conversion de l'école... dans ton terminal !", style="italic")

    console.print()
    console.print(Panel(
        welcome_text,
        border_style="magenta",
        padding=(1, 2),
    ))


# ============================================================================
# PRESSE-PAPIER
# ============================================================================

# Variable globale pour stocker le dernier résultat (pour --copy)
last_result: Optional[str] = None


def copy_to_clipboard(text: str) -> bool:
    """
    Copie le texte dans le presse-papier.

    Args:
        text: Le texte à copier

    Returns:
        True si la copie a réussi, False sinon
    """
    try:
        import pyperclip
        pyperclip.copy(text)
        return True
    except ImportError:
        console.print("[yellow]⚠ pyperclip non installé. Installez avec: pip install la-convertoche[clipboard][/]")
        return False
    except Exception as e:
        console.print(f"[yellow]⚠ Impossible de copier dans le presse-papier: {e}[/]")
        return False


def set_last_result(value: Decimal, unit: str, target_unit: Optional[str], family_config: dict) -> None:
    """Stocke le dernier résultat pour copie ultérieure."""
    global last_result
    normalized_unit = normalize_unit(unit, family_config)

    if target_unit:
        converted = convert_between_units(value, unit, target_unit, family_config)
        normalized_target = normalize_unit(target_unit, family_config)
        last_result = f"{format_number_fr(converted, 10)} {normalized_target}"
    else:
        last_result = f"{format_number_fr(value, 10)} {normalized_unit}"


# ============================================================================
# MODE INTERACTIF ET HISTORIQUE
# ============================================================================

# Historique des conversions de la session
conversion_history: list = []


def add_to_history(value: Decimal, unit: str, target_unit: Optional[str] = None) -> None:
    """Ajoute une conversion à l'historique."""
    entry = {
        "value": value,
        "unit": unit,
        "target_unit": target_unit,
    }
    conversion_history.append(entry)


def display_history() -> None:
    """Affiche l'historique des conversions."""
    if not conversion_history:
        console.print("[dim]Aucune conversion dans l'historique.[/]")
        return

    console.print()
    console.print("[bold magenta]📜 Historique des conversions[/]")
    console.print()

    for i, entry in enumerate(conversion_history, 1):
        value_formatted = format_number_fr(entry["value"], 10)
        unit = entry["unit"]
        target = entry["target_unit"]

        if target:
            # Calcule la conversion
            result = find_unit_family(unit)
            if result:
                _, family_config = result
                converted = convert_between_units(entry["value"], unit, target, family_config)
                converted_formatted = format_number_fr(converted, 10)
                console.print(f"  {i}. {value_formatted} {unit} → {converted_formatted} {target}")
        else:
            console.print(f"  {i}. {value_formatted} {unit}")

    console.print()


def interactive_mode() -> None:
    """Lance le mode interactif en boucle avec prompts Rich."""
    display_welcome()
    console.print()
    console.print("[dim]Tapez 'quit' ou 'q' pour quitter, 'history' ou 'h' pour l'historique[/]")

    while True:
        console.print()

        # Demande la valeur
        value_str = Prompt.ask("[bold cyan]Valeur (ou commande)[/]")

        # Commandes spéciales
        if value_str.lower() in ("quit", "q", "exit"):
            console.print("[bold magenta]À bientôt ![/]")
            break

        if value_str.lower() in ("history", "h", "historique"):
            display_history()
            continue

        if value_str.lower() in ("list", "l"):
            display_units_list()
            continue

        if value_str.lower() in ("help", "?"):
            console.print()
            console.print("[bold]Commandes disponibles :[/]")
            console.print("  [cyan]quit[/], [cyan]q[/]     - Quitter")
            console.print("  [cyan]history[/], [cyan]h[/] - Afficher l'historique")
            console.print("  [cyan]list[/], [cyan]l[/]    - Lister les unités")
            console.print("  [cyan]help[/], [cyan]?[/]    - Cette aide")
            continue

        try:
            value = parse_value(value_str)
        except ValueError as e:
            display_error(str(e))
            continue

        # Demande l'unité
        console.print("[dim]Exemples: m, km, g, kg, L, mL...[/]")
        unit = Prompt.ask("[bold cyan]Unité[/]")

        if unit.lower() in ("quit", "q", "exit"):
            console.print("[bold magenta]À bientôt ![/]")
            break

        # Demande optionnellement l'unité cible
        target_input = Prompt.ask("[bold cyan]Unité cible (optionnel, Entrée pour passer)[/]", default="")
        target_unit = target_input.strip() if target_input.strip() else None

        # Ajoute à l'historique et affiche le résultat
        add_to_history(value, unit, target_unit)
        display_result(value, unit, target_unit)


# ============================================================================
# MODE QUIZ
# ============================================================================


def generate_quiz_question() -> Tuple[Decimal, str, str, Decimal]:
    """
    Génère une question de quiz aléatoire.

    Returns:
        Tuple (valeur, unité_source, unité_cible, réponse_correcte)
    """
    # Choisit une famille aléatoire
    family_name = random.choice(list(UNIT_FAMILIES.keys()))
    family_config = UNIT_FAMILIES[family_name]
    units = family_config["units"]

    # Choisit deux unités différentes
    source_unit = random.choice(units)
    target_unit = random.choice([u for u in units if u != source_unit])

    # Génère une valeur aléatoire (entier ou décimal simple)
    if random.random() < 0.5:
        # Entier entre 1 et 100
        value = Decimal(str(random.randint(1, 100)))
    else:
        # Décimal simple (1 décimale)
        value = Decimal(str(random.randint(1, 999))) / Decimal("10")

    # Calcule la réponse
    answer = convert_between_units(value, source_unit, target_unit, family_config)

    return value, source_unit, target_unit, answer


def quiz_mode(num_questions: int = 5) -> None:
    """
    Lance le mode quiz interactif.

    Args:
        num_questions: Nombre de questions à poser
    """
    console.print()
    console.print(Panel(
        "[bold magenta]🎓 Mode Quiz - Conversion d'unités[/]\n\n"
        f"Répondez à {num_questions} questions de conversion.\n"
        "Utilisez la virgule (,) ou le point (.) pour les décimales.\n"
        "Tapez 'q' pour quitter.",
        border_style="magenta",
        padding=(1, 2),
    ))

    score = 0
    questions_asked = 0

    for i in range(num_questions):
        value, source_unit, target_unit, correct_answer = generate_quiz_question()
        value_formatted = format_number_fr(value, 10)

        console.print()
        console.print(f"[bold cyan]Question {i + 1}/{num_questions}[/]")
        console.print(f"  Convertir [bold]{value_formatted} {source_unit}[/] en [bold]{target_unit}[/]")
        console.print()

        user_input = Prompt.ask("[bold yellow]Votre réponse[/]")

        if user_input.lower() in ("q", "quit", "exit"):
            console.print("[dim]Quiz interrompu.[/]")
            break

        questions_asked += 1

        try:
            user_answer = parse_value(user_input)

            # Normalise pour comparaison (arrondi à 6 décimales)
            user_normalized = round(float(user_answer), 6)
            correct_normalized = round(float(correct_answer), 6)

            if user_normalized == correct_normalized:
                score += 1
                console.print("[bold green]✓ Correct ![/]")
            else:
                correct_formatted = format_number_fr(correct_answer, 10)
                console.print(f"[bold red]✗ Incorrect.[/] La réponse était [bold]{correct_formatted} {target_unit}[/]")

        except ValueError:
            correct_formatted = format_number_fr(correct_answer, 10)
            console.print(f"[bold red]✗ Réponse invalide.[/] La réponse était [bold]{correct_formatted} {target_unit}[/]")

    # Affiche le score final
    if questions_asked > 0:
        percentage = (score / questions_asked) * 100
        console.print()

        if percentage >= 80:
            emoji = "🏆"
            style = "bold green"
            message = "Excellent !"
        elif percentage >= 60:
            emoji = "👍"
            style = "bold yellow"
            message = "Bien joué !"
        elif percentage >= 40:
            emoji = "📚"
            style = "bold orange3"
            message = "Continuez à pratiquer !"
        else:
            emoji = "💪"
            style = "bold red"
            message = "Révise ton tableau !"

        console.print(Panel(
            f"[{style}]{emoji} Score final : {score}/{questions_asked} ({percentage:.0f}%)[/]\n\n{message}",
            title="[bold magenta]Résultat[/]",
            border_style="magenta",
            padding=(1, 2),
        ))


# ============================================================================
# POINT D'ENTRÉE
# ============================================================================


def main() -> None:
    """Point d'entrée principal du programme."""
    parser = argparse.ArgumentParser(
        prog="convertoche",
        description="La Convertoche - Visualiseur de conversion d'unités métriques",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Exemples:
  python main.py 12.5 m           Affiche 12,5 mètres dans le tableau
  python main.py 1,5 kg           Affiche 1,5 kilogrammes (virgule acceptée)
  python main.py 2.5 km --to m    Convertit 2,5 km en mètres
  python main.py --list           Affiche toutes les unités supportées
  python main.py --version        Affiche la version
  python main.py                  Lance le mode interactif
        """,
    )

    parser.add_argument(
        "value",
        nargs="?",
        help="La valeur numérique à convertir (accepte . et ,)",
    )

    parser.add_argument(
        "unit",
        nargs="?",
        help="L'unité de la valeur (ex: m, km, g, L)",
    )

    parser.add_argument(
        "--to", "-t",
        dest="target_unit",
        help="Unité cible pour la conversion (ex: --to km)",
    )

    parser.add_argument(
        "--list", "-l",
        action="store_true",
        dest="list_units",
        help="Affiche la liste des unités supportées",
    )

    parser.add_argument(
        "--read", "-r",
        dest="read_unit",
        metavar="UNITÉ",
        help="Lecture directe : lit une valeur depuis stdin et la convertit (ex: echo 12.5 | convertoche --read m)",
    )

    parser.add_argument(
        "--copy", "-c",
        action="store_true",
        dest="copy_result",
        help="Copie le résultat dans le presse-papier (nécessite pyperclip)",
    )

    parser.add_argument(
        "--quiz", "-q",
        nargs="?",
        const=5,
        type=int,
        dest="quiz_questions",
        metavar="N",
        help="Lance le mode quiz avec N questions (défaut: 5)",
    )

    parser.add_argument(
        "--version", "-v",
        action="version",
        version=f"%(prog)s {__version__}",
    )

    args = parser.parse_args()

    # Mode liste des unités
    if args.list_units:
        display_units_list()
        return

    # Mode quiz
    if args.quiz_questions is not None:
        quiz_mode(args.quiz_questions)
        return

    # Mode lecture depuis stdin
    if args.read_unit:
        try:
            value_str = sys.stdin.read().strip()
            if not value_str:
                display_error("Aucune valeur lue depuis stdin. Usage: echo 12.5 | convertoche --read m")
                sys.exit(1)
            value = parse_value(value_str)
            display_result(value, args.read_unit, args.target_unit, args.copy_result)
        except ValueError as e:
            display_error(str(e))
            sys.exit(1)
        return

    # Mode interactif si pas d'arguments
    if args.value is None:
        interactive_mode()
        return

    # Mode ligne de commande
    if args.unit is None:
        display_error("Vous devez spécifier une unité. Ex: python main.py 12.5 m")
        return

    try:
        value = parse_value(args.value)
    except ValueError as e:
        display_error(str(e))
        sys.exit(1)

    display_result(value, args.unit, args.target_unit, args.copy_result)


if __name__ == "__main__":
    main()
