import random
import os
import sys

# --- GESTION DES TOUCHES (Inchangée) ---
try:
    import msvcrt
    def get_key():
        key = msvcrt.getch()
        if key == b'\xe0':
            key = msvcrt.getch()
            return {b'H': 'up', b'P': 'down'}.get(key, None)
        return 'enter' if key == b'\r' else None
except ImportError:
    import tty, termios
    def get_key():
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(3)
            if ch == '\x1b[A': return 'up'
            elif ch == '\x1b[B': return 'down'
            elif ch == '\r': return 'enter'
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return None

class Style:
    ROUGE, VERT, BLEU, JAUNE, CYAN, VIOLET, GRIS = '\033[91m', '\033[92m', '\033[94m', '\033[93m', '\033[96m', '\033[95m', '\033[90m'
    FIN, GRAS, REVERSE = '\033[0m', '\033[1m', '\033[7m'

# --- VISUELS ASCII ---
VISUELS = {
    "Chevalier": [
        "      _      ",
        "     [ ]     ",
        "    _|_|_    ",
        "   |  |  |   ",
        "   |--|--|   ",
        "   |__|__|   ",
        "   /_| |_\\   "
    ],
    "Magicien": [
        "      ^      ",
        "     / \\     ",
        "    /___\\    ",
        "    (o o)    ",
        "    _\\_/_    ",
        "   /  |  \\   ",
        "  /   |   \\  "
    ],
    "Ogre": [
        "    _____    ",
        "   /     \\   ",
        "  | (O)(O) | ",
        "  |   __   | ",
        "  |  |__|  | ",
        " /|        |\\",
        "/ |________|\\"
    ],
    "Pretre": [
        "     _|_     ",
        "    (   )    ",
        "    /   \\    ",
        "   /_____\\   ",
        "   |  |  |   ",
        "   |  |  |   ",
        "   |__|__|   "
    ],
    "Necromancien": [
        "    .---.    ",
        "   / / \\ \\   ",
        "   | \\_/ |   ",
        "   /(---)\\   ",
        "  / )   ( \\  ",
        " / /     \\ \\ ",
        "(_/       \\_)"
    ]
}

class Personnage:
    def __init__(self, nom, hp, mp, force, magie, lore):
        self.nom = nom
        self.hp_max, self.hp = hp, hp
        self.mp_max, self.mp = mp, mp // 2
        self.force, self.magie = force, magie
        self.lore = lore
        self.defense_active = False
        self.boost_dmg = 1.0
        self.armure = 1.0
        self.etats = {"Assommé": 0, "Paralysé": 0, "Peur": 0, "Immunité": 0}
        self.visuel = VISUELS.get(self.__class__.__name__, ["?"])

    def barre(self, actuel, max_val, coul, taille=15):
        blocs = int((max(0, actuel) / max_val) * taille)
        return f"[{coul}{'█'*blocs}{Style.GRIS}{'█'*(taille-blocs)}{Style.FIN}] {actuel}/{max_val}"

# --- CLASSES ET LORE (Inchangées) ---

class Chevalier(Personnage):
    def __init__(self, nom):
        super().__init__(nom, 150, 40, 1.4, 0.6, "Un noble guerrier en armure étincelante.")
    def get_actions(self, cible):
        return [
            {"nom": "Tranchage", "cout": 0, "type": "phys", "dmg": "14-20", "desc": "Coup d'épée lourd.", "verbe": "fend l'air avec sa lame et touche"},
            {"nom": "Lancer de Javelot", "cout": 15, "type": "mag", "dmg": "22-28", "desc": "Attaque à distance.", "verbe": "projette un javelot d'acier sur"},
            {"nom": "Bandage", "cout": 10, "type": "soin", "val": 25, "desc": "Soins de fortune.", "verbe": "serre ses blessures avec des linges sales"},
            {"nom": "Posture de Fer", "cout": 5, "type": "def", "desc": "Réduction de 70%.", "verbe": "se verrouille derrière son bouclier"},
            {"nom": "Repos", "cout": 0, "type": "mana", "desc": "+25 MP.", "verbe": "reprend son souffle un instant"},
            {"nom": "Cri de Guerre", "cout": 15, "type": "spec", "desc": "Peur + Fragilité.", "verbe": "pousse un hurlement qui glace le sang de"},
            {"nom": "Discipline", "cout": 0, "type": "purif", "desc": "Soigne malus.", "verbe": "fait appel à sa volonté pour briser ses chaînes"}
        ]

class Magicien(Personnage):
    def __init__(self, nom):
        super().__init__(nom, 85, 130, 0.5, 2.0, "Un vieil érudit manipulant les énergies du cosmos.")
    def get_actions(self, cible):
        return [
            {"nom": "Frappe de Bâton", "cout": 0, "type": "phys", "dmg": "5-10", "desc": "Faible coup.", "verbe": "donne un coup de bois sec à"},
            {"nom": "Boule de Feu", "cout": 15, "type": "mag", "dmg": "28-38", "desc": "Dégâts magiques.", "verbe": "incante une sphère ardente qui explose sur"},
            {"nom": "Soin Arcanique", "cout": 15, "type": "soin", "val": 30, "desc": "Soin magique.", "verbe": "tisse une aura bleutée qui referme ses plaies"},
            {"nom": "Barrière", "cout": 8, "type": "def", "desc": "Bouclier d'éther.", "verbe": "érige un mur de lumière crépitante"},
            {"nom": "Canalisation", "cout": 0, "type": "mana", "desc": "+25 MP.", "verbe": "absorbe les particules magiques du lieu"},
            {"nom": "Éclair", "cout": 25, "type": "spec", "desc": "Dégâts + Paralysie.", "verbe": "abat la foudre du ciel directement sur"},
            {"nom": "Dissipation", "cout": 0, "type": "purif", "desc": "Retire malus.", "verbe": "prononce un mot de pouvoir annulant les sorts"}
        ]

class Ogre(Personnage):
    def __init__(self, nom):
        super().__init__(nom, 220, 30, 1.9, 0.3, "Une créature massive qui ne comprend que la force.")
    def get_actions(self, cible):
        return [
            {"nom": "Grosse Claque", "cout": 0, "type": "phys", "dmg": "15-25", "desc": "Brutalité pure.", "verbe": "abat sa main énorme sur le visage de"},
            {"nom": "Jet de Rocher", "cout": 10, "type": "mag", "dmg": "20-30", "desc": "Lancer lourd.", "verbe": "déterre un rocher et le fracasse sur"},
            {"nom": "Manger un Os", "cout": 5, "type": "soin", "val": 20, "desc": "Grignotage.", "verbe": "croque bruyamment dans un fémur"},
            {"nom": "Peau Épaisse", "cout": 0, "type": "def", "desc": "Encaisser.", "verbe": "gonfle ses muscles pour ne rien sentir"},
            {"nom": "Grosse Sieste", "cout": 0, "type": "mana", "desc": "+25 MP.", "verbe": "s'assoit et ferme les yeux en bavant"},
            {"nom": "Fracas", "cout": 15, "type": "spec", "desc": "Assomme.", "verbe": "frappe le sol si fort qu'il fait tomber"},
            {"nom": "Secouer tête", "cout": 0, "type": "purif", "desc": "Reset.", "verbe": "secoue la tête pour oublier la douleur"}
        ]

class Pretre(Personnage):
    def __init__(self, nom):
        super().__init__(nom, 110, 110, 0.6, 1.3, "Serviteur de la Lumière, il soigne et châtie.")
    def get_actions(self, cible):
        return [
            {"nom": "Sceptre", "cout": 0, "type": "phys", "dmg": "8-12", "desc": "Coup béni.", "verbe": "frappe avec son bâton sacré"},
            {"nom": "Colère Divine", "cout": 18, "type": "mag", "dmg": "20-30", "desc": "Châtiment.", "verbe": "invoque un rayon céleste pour brûler"},
            {"nom": "Grande Guérison", "cout": 12, "type": "soin", "val": 55, "desc": "Gros soin.", "verbe": "chante un hymne sacré qui restaure sa vie"},
            {"nom": "Halo", "cout": 10, "type": "def", "desc": "Protection.", "verbe": "s'enveloppe dans une bulle de sainteté"},
            {"nom": "Prière", "cout": 0, "type": "mana", "desc": "+25 MP.", "verbe": "se recueille et reçoit la grâce"},
            {"nom": "Bénédiction", "cout": 20, "type": "spec", "desc": "Immunité + Force.", "verbe": "reçoit la bénédiction suprême"},
            {"nom": "Exorcisme", "cout": 0, "type": "purif", "desc": "Purifie.", "verbe": "chasse les démons qui le tourmentent"}
        ]

class Necromancien(Personnage):
    def __init__(self, nom):
        super().__init__(nom, 105, 95, 0.8, 1.5, "Un maître des morts-vivants.")
    def get_actions(self, cible):
        return [
            {"nom": "Griffe d'Ombre", "cout": 0, "type": "phys", "dmg": "12-16", "desc": "Ténèbres.", "verbe": "lacère les chairs de"},
            {"nom": "Peste", "cout": 15, "type": "mag", "dmg": "25-35", "desc": "Poison.", "verbe": "souffle un vent de décomposition sur"},
            {"nom": "Saignée", "cout": 10, "type": "soin", "val": 25, "desc": "Vol de vie.", "verbe": "aspire l'essence vitale pour se soigner"},
            {"nom": "Voile d'Os", "cout": 10, "type": "def", "desc": "Défense.", "verbe": "fait jaillir des squelettes pour le protéger"},
            {"nom": "Récolte", "cout": 0, "type": "mana", "desc": "+25 MP.", "verbe": "dévore une âme errante pour sa mana"},
            {"nom": "Sort de Malheur", "cout": 20, "type": "spec", "desc": "Malus aléatoire.", "verbe": "lance une malédiction impie sur"},
            {"nom": "Rituel", "cout": 0, "type": "purif", "desc": "Purification.", "verbe": "se baigne dans des flammes noires"}
        ]

# --- MOTEUR DE RENDU FACE À FACE ---

def afficher_arene(p1, p2, message=""):
    os.system('cls' if os.name == 'nt' else 'clear')
    print(f"\n{Style.JAUNE}           <<< ARENE DE COMBAT >>>{Style.FIN}\n")
    
    # Dessin des personnages côte à côte
    for i in range(7):
        line1 = p1.visuel[i]
        line2 = p2.visuel[i]
        print(f"   {line1}           {line2}")
    
    # Stats en colonnes
    print(f"\n {Style.GRAS}{p1.nom[:12]:<15}           {p2.nom[:12]:<15}{Style.FIN}")
    print(f" PV: {p1.barre(p1.hp, p1.hp_max, Style.VERT, 12)}      PV: {p2.barre(p2.hp, p2.hp_max, Style.VERT, 12)}")
    print(f" MP: {p1.barre(p1.mp, p1.mp_max, Style.BLEU, 12)}      MP: {p2.barre(p2.mp, p2.mp_max, Style.BLEU, 12)}")
    
    # États
    actifs1 = [e[0] for e, t in p1.etats.items() if t > 0]
    actifs2 = [e[0] for e, t in p2.etats.items() if t > 0]
    print(f" Stat: {','.join(actifs1):<12}           Stat: {','.join(actifs2):<12}")
    
    if message:
        print(f"\n{Style.REVERSE} INFO : {message} {Style.FIN}")

# --- SYSTÈME DE SÉLECTION (Avec Visuel) ---

def selectionner_classe(num_joueur):
    classes = [Chevalier, Magicien, Ogre, Pretre, Necromancien]
    idx = 0
    while True:
        os.system('cls' if os.name == 'nt' else 'clear')
        print(f"{Style.JAUNE}--- SÉLECTION DU JOUEUR {num_joueur} ---{Style.FIN}\n")
        
        # Affichage du visuel de la classe actuelle
        temp = classes[idx]("Temp")
        for line in temp.visuel:
            print(f"          {Style.CYAN}{line}{Style.FIN}")
            
        print(f"\n          << {Style.GRAS}{classes[idx].__name__}{Style.FIN} >>\n")
        
        for i, cl in enumerate(classes):
            sel = f"{Style.JAUNE} > " if i == idx else "   "
            txt = Style.REVERSE if i == idx else ""
            print(f"{sel}{txt}{cl.__name__:<15}{Style.FIN}")
        
        print("\n" + "—"*40)
        print(f"{Style.CYAN}HISTOIRE :{Style.FIN} {temp.lore}")
        print("—"*40)
        print("(↑↓ : Choisir, Entrée : Valider)")

        k = get_key()
        if k == 'up': idx = (idx - 1) % len(classes)
        elif k == 'down': idx = (idx + 1) % len(classes)
        elif k == 'enter': 
            nom = input(f"\nNom du {classes[idx].__name__} : ") or f"Héros {num_joueur}"
            return classes[idx](nom)

# --- NARRATION ---

def tour_narratif(attaquant, cible, p1, p2):
    if attaquant.etats["Assommé"] > 0:
        afficher_arene(p1, p2, f"{attaquant.nom} est au sol et passe son tour !")
        attaquant.etats["Assommé"] = 0
        input("\n..."); return

    actions = attaquant.get_actions(cible)
    idx = 0
    while True:
        msg = f"C'est au tour de {attaquant.nom} !"
        afficher_arene(p1, p2, msg)
        
        print("\n" + "—"*45)
        for i, a in enumerate(actions):
            sel = f"{Style.JAUNE} > " if i == idx else "   "
            txt = Style.REVERSE if i == idx else ""
            print(f"{sel}{txt}{a['nom']:<20}{Style.FIN} {Style.BLEU}{a['cout']} MP{Style.FIN}")
        print("—"*45)
        print(f"{Style.CYAN}EFFET :{Style.FIN} {actions[idx]['desc']}")
        
        k = get_key()
        if k == 'up': idx = (idx - 1) % len(actions)
        elif k == 'down': idx = (idx + 1) % len(actions)
        elif k == 'enter': break

    act = actions[idx]
    recit = ""

    if attaquant.mp < act['cout']:
        recit = f"Mana insuffisante pour {act['nom']} !"
    elif attaquant.etats["Peur"] > 0 and random.random() < 0.5:
        recit = f"{attaquant.nom} est pétrifié de peur !"
    elif act['type'] == "phys" and attaquant.etats["Paralysé"] > 0:
        recit = f"{attaquant.nom} est paralysé !"
    else:
        attaquant.mp -= act['cout']
        v = act.get('verbe', "agit")
        
        if act['type'] == "phys":
            r = act['dmg'].split('-')
            d = int(random.randint(int(r[0]), int(r[1])) * attaquant.force * attaquant.boost_dmg * cible.armure)
            if cible.defense_active: d //= 3
            cible.hp -= d
            recit = f"{attaquant.nom} {v} {cible.nom} (-{d} PV)."
            attaquant.boost_dmg = 1.0
        elif act['type'] == "mag":
            r = act['dmg'].split('-')
            d = int(random.randint(int(r[0]), int(r[1])) * cible.armure)
            cible.hp -= d
            recit = f"{attaquant.nom} {v} {cible.nom} ! (-{d} PV)."
        elif act['type'] == "soin":
            val = act['val']
            attaquant.hp = min(attaquant.hp_max, attaquant.hp + val)
            recit = f"{attaquant.nom} {v} (+{val} PV)."
        elif act['type'] == "def":
            attaquant.defense_active = True
            recit = f"{attaquant.nom} {v}."
        elif act['type'] == "mana":
            attaquant.mp = min(attaquant.mp_max, attaquant.mp + 25)
            recit = f"{attaquant.nom} {v} (+25 Mana)."
        elif act['type'] == "purif":
            for e in attaquant.etats: attaquant.etats[e] = 0
            attaquant.armure = 1.0
            recit = f"{attaquant.nom} {v} (Purifié)."
        elif act['type'] == "spec":
            recit = f"{attaquant.nom} {v} {cible.nom} !"
            if isinstance(attaquant, Chevalier):
                cible.armure = 1.5; cible.etats["Peur"] = 2
            elif isinstance(attaquant, Magicien):
                d = int(45 * attaquant.magie); cible.hp -= d; cible.etats["Paralysé"] = 2
            elif isinstance(attaquant, Ogre):
                d = int(35 * attaquant.force); cible.hp -= d; cible.etats["Assommé"] = 1
            elif isinstance(attaquant, Pretre):
                attaquant.etats["Immunité"] = 3; attaquant.boost_dmg = 1.6
            elif isinstance(attaquant, Necromancien):
                e = random.choice(["Assommé", "Paralysé", "Peur"]); cible.etats[e] = 2

    # Animation du message final
    afficher_arene(p1, p2, recit)
    input("\nAppuyez sur Entrée...")

def main():
    p1 = selectionner_classe(1)
    p2 = selectionner_classe(2)
    t = 0
    while p1.hp > 0 and p2.hp > 0:
        # On remet la défense à zéro au début de chaque tour
        if t % 2 == 0: p1.defense_active = False
        else: p2.defense_active = False
        
        tour_narratif(p1 if t%2==0 else p2, p2 if t%2==0 else p1, p1, p2)
        t += 1
    
    gagnant = p1 if p1.hp > 0 else p2
    os.system('cls' if os.name == 'nt' else 'clear')
    print(f"\n\n{Style.JAUNE}*** VICTOIRE DE {gagnant.nom.upper()} ! ***{Style.FIN}")
    for line in gagnant.visuel: print(f"          {line}")
    print("\nLe combat prend fin...")

if __name__ == "__main__":
    main()
