"""Game-Engine: Auto-Progress, Kämpfe, Loot, Quests, Shop."""

import random
import time
from character import Character, Item, RACES, CLASSES
from llm import NameCache

class Monster:
    def __init__(self, name: str, level: int, hp: int, attack: int, defense: int, xp: int, gold: int):
        self.name = name
        self.level = level
        self.hp = hp
        self.attack = attack
        self.defense = defense
        self.xp = xp
        self.gold = gold
    
    def is_alive(self):
        return self.hp > 0

class GameEngine:
    def __init__(self, character: Character):
        self.character = character
        self.cache = NameCache()
        self.cache.refill_async()
        self.current_location = self.cache.get_location()
        self.current_quest = self.cache.get_quest(character.level)
        self.quest_progress = 0
        self.quest_target = random.randint(3, 8)
        self.log = []
        self.max_log = 15
    
    def _add_log(self, msg: str):
        self.log.insert(0, msg)
        if len(self.log) > self.max_log:
            self.log = self.log[:self.max_log]
    
    def _spawn_monster(self) -> Monster:
        name = self.cache.get_monster(self.character.level, self.current_location)
        level = max(1, self.character.level + random.randint(-1, 1))
        hp = 10 + level * 5 + random.randint(0, 10)
        attack = level * 2 + random.randint(0, 3)
        defense = level + random.randint(0, 2)
        xp = 5 + level * 3 + random.randint(0, 5)
        gold = 1 + level + random.randint(0, 3)
        return Monster(name, level, hp, attack, defense, xp, gold)
    
    def _generate_loot(self, monster: Monster) -> Item:
        item_types = ["weapon", "armor", "helmet", "boots", "accessory", "junk"]
        item_type = random.choices(item_types, weights=[15, 15, 10, 10, 8, 42])[0]
        
        # Rarity based on luck and level
        roll = random.randint(1, 100) + self.character.lck
        if roll > 95:
            rarity = "legendär"
        elif roll > 80:
            rarity = "episch"
        elif roll > 60:
            rarity = "selten"
        else:
            rarity = "gewöhnlich"
        
        name = self.cache.get_item(item_type, self.character.level, rarity)
        
        rarity_mult = {"gewöhnlich": 1, "selten": 1.5, "episch": 2.5, "legendär": 4}
        mult = rarity_mult.get(rarity, 1)
        
        base_power = self.character.level + random.randint(0, 3)
        power = max(1, int(base_power * mult))
        value = max(1, int((monster.gold + 2) * mult * random.uniform(0.8, 1.2)))
        
        return Item(name, item_type, power, value, rarity)
    
    def _combat(self, monster: Monster) -> dict:
        """Führt einen automatischen Kampf durch. Gibt Ergebnis-Dict zurück."""
        rounds = 0
        while monster.is_alive() and self.character.is_alive():
            rounds += 1
            # Character attacks
            char_dmg = max(1, self.character.attack - monster.defense + random.randint(-2, 2))
            char_dmg = min(char_dmg, monster.hp)
            monster.hp -= char_dmg
            
            if not monster.is_alive():
                break
            
            # Monster attacks
            mon_dmg = max(1, monster.attack - self.character.defense + random.randint(-2, 2))
            actual = self.character.take_damage(mon_dmg)
            
            if not self.character.is_alive():
                return {"result": "death", "rounds": rounds, "monster": monster.name}
        
        return {"result": "victory", "rounds": rounds, "monster": monster.name}
    
    def _complete_quest(self):
        self.character.quests_done += 1
        quest_gold = 5 + self.character.level * 3 + random.randint(0, 10)
        quest_xp = 10 + self.character.level * 5 + random.randint(0, 10)
        self.character.gold += quest_gold
        leveled = self.character.gain_xp(quest_xp)
        self._add_log(f"[bold green]✅ Quest abgeschlossen: {self.current_quest} (+{quest_gold} Gold, +{quest_xp} XP)[/]")
        if leveled:
            self._add_log(f"[bold yellow]⬆️ Stufe {self.character.level} erreicht![/]")
            self.character.heal()
        # New quest
        self.current_quest = self.cache.get_quest(self.character.level)
        self.quest_progress = 0
        self.quest_target = random.randint(3, 8)
        self._add_log(f"[cyan]📜 Neue Quest: {self.current_quest} ({self.quest_target} Gegner)[/]")
    
    def step(self) -> dict:
        """Ein Schritt des Auto-Progress. Gibt Event-Info zurück."""
        self.character.steps += 1
        events = []
        
        # Random: sometimes travel
        if random.randint(1, 50) == 1:
            self.current_location = self.cache.get_location()
            events.append(("travel", f"[blue]🌍 Du reist nach: {self.current_location}[/]"))
            self._add_log(events[-1][1])
        
        # Spawn monster
        monster = self._spawn_monster()
        events.append(("encounter", f"[red]⚔️ {monster.name} (Stufe {monster.level}) erscheint![/]"))
        self._add_log(events[-1][1])
        
        # Fight
        result = self._combat(monster)
        
        if result["result"] == "victory":
            self.character.kills += 1
            events.append(("victory", f"[green]⚔️ Besiegst {monster.name} ({result['rounds']} Runden)[/]"))
            self._add_log(events[-1][1])
            
            # XP + Gold
            self.character.gold += monster.gold
            leveled = self.character.gain_xp(monster.xp)
            events.append(("loot_xp", f"[dim]+{monster.xp} XP, +{monster.gold} Gold[/]"))
            self._add_log(events[-1][1])
            
            if leveled:
                self._add_log(f"[bold yellow]⬆️ Stufe {self.character.level} erreicht![/]")
                self.character.heal()
                events.append(("levelup", f"[bold yellow]⬆️ STUFE {self.character.level}![/]"))
            
            # Loot drop
            if random.randint(1, 100) <= 70:  # 70% drop chance
                item = self._generate_loot(monster)
                self._add_log(f"[magenta]📦 Loot: {item}[/]")
                events.append(("loot", f"[magenta]📦 {item}[/]", item))
                self._auto_equip(item)
            else:
                # Always some gold
                extra_gold = random.randint(1, 3)
                self.character.gold += extra_gold
            
            # Quest progress
            self.quest_progress += 1
            if self.quest_progress >= self.quest_target:
                self._complete_quest()
                events.append(("quest_done", f"[green]✅ Quest erfüllt![/]"))
        
        elif result["result"] == "death":
            self.character.deaths += 1
            events.append(("death", f"[bold red]💀 Von {monster.name} besiegt! Respawn...[/]"))
            self._add_log(events[-1][1])
            # Respawn: lose 10% gold, heal
            lost_gold = max(1, self.character.gold // 10)
            self.character.gold -= lost_gold
            self.character.heal()
            self._add_log(f"[red]Verlierst {lost_gold} Gold beim Sterben.[/]")
        
        return {"events": events}
    
    def _auto_equip(self, item: Item):
        """Prüft ob Item besser ist und rüstet es automatisch aus."""
        slot = None
        if item.item_type in ("weapon", "armor", "helmet", "boots", "accessory"):
            slot = item.item_type
        
        if slot:
            current = self.character.equipped[slot]
            if current is None or item.power > current.power:
                if current:
                    self.character.inventory.append(current)
                self.character.equipped[slot] = item
                self._add_log(f"[cyan]🎽 Ausgerüstet: {item}[/]")
            else:
                self.character.inventory.append(item)
        else:
            self.character.inventory.append(item)
        
        # Auto-sell junk to keep inventory clean
        if item.item_type == "junk":
            self.character.gold += item.value
            if item in self.character.inventory:
                self.character.inventory.remove(item)
            self._add_log(f"[dim]💰 Verkauft: {item.name} (+{item.value} Gold)[/]")
    
    def _sell_junk(self):
        """Verkauft alle Schrott-Items."""
        sold = 0
        total_gold = 0
        for item in self.character.inventory[:]:
            if item.item_type == "junk":
                self.character.inventory.remove(item)
                self.character.gold += item.value
                total_gold += item.value
                sold += 1
        if sold > 0:
            self._add_log(f"[dim]💰 {sold} Schrott verkauft (+{total_gold} Gold)[/]")
    
    def get_state(self) -> dict:
        return {
            "character": self.character.to_dict(),
            "current_location": self.current_location,
            "current_quest": self.current_quest,
            "quest_progress": self.quest_progress,
            "quest_target": self.quest_target,
            "log": self.log,
        }
    
    def save(self, path: str):
        import json
        with open(path, "w") as f:
            json.dump(self.get_state(), f, ensure_ascii=False, indent=2)
    
    @classmethod
    def load(cls, path: str) -> "GameEngine":
        import json
        with open(path) as f:
            d = json.load(f)
        char = Character.from_dict(d["character"])
        engine = cls(char)
        engine.current_location = d.get("current_location", engine.current_location)
        engine.current_quest = d.get("current_quest", engine.current_quest)
        engine.quest_progress = d.get("quest_progress", 0)
        engine.quest_target = d.get("quest_target", 5)
        engine.log = d.get("log", [])
        return engine