"""
NPC definitions for combat encounters - NOW LOADED FROM JSON
Each NPC has stats, loot tables, and combat behavior.
"""

from dataclasses import dataclass
from typing import Dict, List, Optional
import json
from pathlib import Path


@dataclass
class LootItem:
    """Item that can be dropped by NPCs"""
    item_id: str
    quantity_min: int
    quantity_max: int
    drop_chance: float  # 0.0 to 1.0


@dataclass
class CorpseLoot:
    """Item that can be scavenged from a corpse"""
    item_id: str
    quantity_min: int
    quantity_max: int
    required_tool: Optional[str] = None  # item_id of required tool


@dataclass
class StatusEffect:
    """Status effect data"""
    name: str
    duration_turns: int
    damage_per_turn: int = 0  # For bleeding
    stun: bool = False  # Prevents action


@dataclass
class NPCDefinition:
    """Complete NPC definition"""
    npc_id: str
    name: str
    description: str
    emoji: str
    
    # Combat stats
    hp_min: int
    hp_max: int
    damage_min: int
    damage_max: int
    defense: int  # Reduces incoming damage
    
    # Rewards
    xp_reward: int
    loot_table: List[LootItem]
    corpse_loot: List[CorpseLoot]
    
    # Behavior
    flee_chance: float  # NPC's chance to flee if low HP
    status_inflict_chance: float  # Chance to inflict status on player
    
    # Visuals
    image_path: Optional[str] = None
    death_message: str = "The enemy falls defeated."


def load_npcs_from_json():
    """Load NPCs, danger levels, and spawn tables from JSON"""
    json_path = Path(__file__).parent.parent / 'gamedata' / 'npcs.json'
    
    try:
        with open(json_path, 'r') as f:
            data = json.load(f)
        
        # Convert JSON to NPCDefinition objects
        npcs = {}
        for npc_id, npc_data in data['npcs'].items():
            # Convert loot tables
            loot_table = [
                LootItem(**loot) for loot in npc_data.get('loot_table', [])
            ]
            corpse_loot = [
                CorpseLoot(**loot) for loot in npc_data.get('corpse_loot', [])
            ]
            
            # Create NPC definition
            npcs[npc_id] = NPCDefinition(
                npc_id=npc_data['npc_id'],
                name=npc_data['name'],
                description=npc_data['description'],
                emoji=npc_data['emoji'],
                hp_min=npc_data['hp_min'],
                hp_max=npc_data['hp_max'],
                damage_min=npc_data['damage_min'],
                damage_max=npc_data['damage_max'],
                defense=npc_data['defense'],
                xp_reward=npc_data['xp_reward'],
                loot_table=loot_table,
                corpse_loot=corpse_loot,
                flee_chance=npc_data['flee_chance'],
                status_inflict_chance=npc_data['status_inflict_chance'],
                image_path=npc_data.get('image_path'),
                death_message=npc_data.get('death_message', "The enemy falls defeated.")
            )
        
        # Load danger levels - convert to tuple format (danger_level, encounter_rate, wandering_chance)
        danger_levels = {}
        for loc_id, danger_data in data['danger_levels'].items():
            danger_levels[loc_id] = (
                danger_data['danger_level'],
                danger_data['encounter_rate'],
                danger_data['wandering_chance']
            )
        
        # Load spawn tables - convert to list of tuples format
        spawn_tables = {}
        for loc_id, spawns in data['spawn_tables'].items():
            spawn_tables[loc_id] = [
                (spawn['npc_id'], spawn['weight']) for spawn in spawns
            ]
        
        print(f"✅ Loaded {len(npcs)} NPCs, {len(danger_levels)} danger configs, {len(spawn_tables)} spawn tables from JSON")
        return npcs, danger_levels, spawn_tables
        
    except FileNotFoundError:
        print(f"⚠️  Warning: {json_path} not found, using fallback NPCs")
        return _get_fallback_npcs()
    except Exception as e:
        print(f"⚠️  Warning: Error loading NPCs from JSON: {e}")
        import traceback
        traceback.print_exc()
        return _get_fallback_npcs()


def _get_fallback_npcs():
    """Fallback NPCs if JSON loading fails"""
    npcs = {
        "feral_dog": NPCDefinition(
            npc_id="feral_dog",
            name="Feral Dog",
            description="A wild, mangy dog with desperate hunger in its eyes.",
            emoji="🐕",
            hp_min=15,
            hp_max=25,
            damage_min=3,
            damage_max=7,
            defense=0,
            xp_reward=10,
            flee_chance=0.3,
            status_inflict_chance=0.15,
            loot_table=[
                LootItem("raw_meat", 1, 2, 0.6),
                LootItem("bone", 1, 1, 0.4),
                LootItem("animal_hide", 1, 1, 0.3)
            ],
            corpse_loot=[
                CorpseLoot("raw_meat", 1, 2),
                CorpseLoot("bone", 1, 1),
                CorpseLoot("animal_hide", 1, 1, required_tool="knife")
            ],
            image_path=None,
            death_message="The feral dog whimpers and collapses."
        )
    }
    
    danger_levels = {
        "start_point": (0, 0.0, 0.0),
    }
    
    spawn_tables = {
        "start_point": [],
    }
    
    return npcs, danger_levels, spawn_tables


# Load on module import
NPCS, LOCATION_DANGER, LOCATION_SPAWNS = load_npcs_from_json()

# Status effects that can be applied in combat
STATUS_EFFECTS = {
    "bleeding": StatusEffect(
        name="Bleeding",
        duration_turns=3,
        damage_per_turn=2,
        stun=False
    ),
    "stunned": StatusEffect(
        name="Stunned",
        duration_turns=1,
        damage_per_turn=0,
        stun=True
    ),
    "infected": StatusEffect(
        name="Infected",
        duration_turns=5,
        damage_per_turn=1,
        stun=False
    ),
}


# Helper functions
def get_danger_level(location_id: str) -> int:
    """Get danger level for a location (0-4)"""
    return LOCATION_DANGER.get(location_id, (0, 0.0, 0.0))[0]


def get_location_encounter_rate(location_id: str) -> float:
    """Get base encounter rate for a location"""
    return LOCATION_DANGER.get(location_id, (0, 0.0, 0.0))[1]


def get_wandering_enemy_chance(location_id: str) -> float:
    """Get chance for wandering enemy to spawn"""
    return LOCATION_DANGER.get(location_id, (0, 0.0, 0.0))[2]


def get_random_npc_for_location(location_id: str) -> str:
    """
    Get a random NPC ID for the given location based on spawn weights.
    Returns None if no NPCs can spawn at this location.
    """
    import random
    
    spawn_table = LOCATION_SPAWNS.get(location_id, [])
    if not spawn_table:
        return None
    
    # Extract NPCs and weights
    npcs = [npc_id for npc_id, weight in spawn_table]
    weights = [weight for npc_id, weight in spawn_table]
    
    # Use random.choices with weights
    return random.choices(npcs, weights=weights, k=1)[0] if npcs else None
