"""
World loader - NOW LOADS FROM JSON
Creates and connects all the game world objects from gamedata/locations.json
Uses template-based interactables from gamedata/interactables.json
"""

from .models import World, Location, Interactable, Action, Outcome
import json
from pathlib import Path


def load_interactable_templates():
    """Load interactable templates from interactables.json."""
    templates = {}
    json_path = Path(__file__).parent.parent / 'gamedata' / 'interactables.json'
    
    try:
        with open(json_path, 'r') as f:
            data = json.load(f)
        
        for template_id, template_data in data.get('interactables', {}).items():
            templates[template_id] = template_data
        
        print(f"📦 Loaded {len(templates)} interactable templates")
    except FileNotFoundError:
        print("⚠️  interactables.json not found, using inline data only")
    except Exception as e:
        print(f"⚠️  Error loading interactables.json: {e}")
    
    return templates


def create_interactable_from_template(template_id, template_data, instance_data):
    """Create an Interactable object from template and instance data."""
    interactable = Interactable(
        id=template_id,
        name=template_data.get('name', 'Unknown'),
        image_path=template_data.get('image_path', '')
    )
    
    # Get actions from template
    template_actions = template_data.get('actions', {})
    
    # Get outcomes from instance (template-based format)
    instance_outcomes = instance_data.get('outcomes', {})
    
    # Build actions by merging template actions with instance outcomes
    for action_id, action_template in template_actions.items():
        action = Action(
            id=action_template['id'],
            label=action_template['label'],
            stamina_cost=action_template.get('stamina_cost', 2)
        )
        
        # Get the instance-specific outcome data for this action
        if action_id in instance_outcomes:
            outcome_data = instance_outcomes[action_id]
            
            # Build outcomes from the instance data
            text_dict = outcome_data.get('text', {})
            rewards = outcome_data.get('rewards', {})
            
            # Add success outcome
            if text_dict.get('success'):
                items_reward = {}
                if 'items' in rewards:
                    for item in rewards['items']:
                        items_reward[item['item_id']] = item.get('quantity', 1)
                
                outcome = Outcome(
                    text=text_dict['success'],
                    items_reward=items_reward,
                    damage_taken=rewards.get('damage', 0)
                )
                action.add_outcome('success', outcome)
            
            # Add failure outcome
            if text_dict.get('failure'):
                outcome = Outcome(
                    text=text_dict['failure'],
                    items_reward={},
                    damage_taken=0
                )
                action.add_outcome('failure', outcome)
            
            # Add critical failure outcome
            if text_dict.get('crit_failure'):
                outcome = Outcome(
                    text=text_dict['crit_failure'],
                    items_reward={},
                    damage_taken=rewards.get('crit_damage', 0)
                )
                action.add_outcome('critical_failure', outcome)
        
        interactable.add_action(action)
    
    return interactable


def load_world() -> World:
    """Creates and connects all the game world objects from JSON."""
    world = World()
    
    # Load interactable templates first
    templates = load_interactable_templates()
    
    json_path = Path(__file__).parent.parent / 'gamedata' / 'locations.json'
    
    try:
        with open(json_path, 'r') as f:
            data = json.load(f)
        
        print(f"📍 Loading {len(data['locations'])} locations from JSON...")
        
        # First pass: Create all locations
        for loc_data in data['locations']:
            location = Location(
                id=loc_data['id'],
                name=loc_data['name'],
                description=loc_data['description'],
                image_path=loc_data['image_path'],
                x=loc_data.get('x', 0.0),
                y=loc_data.get('y', 0.0),
                tags=loc_data.get('tags', []),
                npcs=loc_data.get('npcs', []),
                danger_level=loc_data.get('danger_level', 0)
            )
            
            # Add interactables using template-based format
            for instance_id, instance_data in loc_data.get('interactables', {}).items():
                template_id = instance_data.get('template_id')
                
                if not template_id:
                    print(f"⚠️  Skipping interactable {instance_id} - no template_id")
                    continue
                
                # Get template data
                template_data = templates.get(template_id)
                
                if not template_data:
                    print(f"⚠️  Template '{template_id}' not found for {instance_id}")
                    continue
                
                # Create interactable from template + instance data
                interactable = create_interactable_from_template(
                    template_id, 
                    template_data, 
                    instance_data
                )
                
                location.add_interactable(instance_id, interactable)
            
            world.add_location(location)
        
        # Second pass: Add connections
        print(f"🔗 Adding {len(data['connections'])} connections...")
        for conn in data['connections']:
            from_loc = world.get_location(conn['from'])
            if from_loc:
                from_loc.add_exit(conn['direction'], conn['to'])
        
        print(f"✅ World loaded successfully!")
        return world
        
    except FileNotFoundError:
        print(f"⚠️  Warning: {json_path} not found, loading fallback world")
        return _load_fallback_world()
    except Exception as e:
        print(f"⚠️  Error loading world from JSON: {e}")
        import traceback
        traceback.print_exc()
        return _load_fallback_world()


def _load_fallback_world() -> World:
    """Fallback world with minimal locations if JSON loading fails"""
    world = World()
    
    # Create a simple fallback location
    start = Location(
        id="start_point",
        name="🌆 Ruined Downtown Core",
        description="The wind howls through skeletal skyscrapers. Debris litters the cracked asphalt.",
        image_path="images/locations/downtown.webp",
        x=0.0,
        y=0.0
    )
    
    # Add a simple interactable
    rubble = Interactable(
        id="rubble",
        name="Pile of Rubble",
        image_path="images/interactables/rubble.webp"
    )
    search_action = Action(id="search", label="🔎 Search Rubble", stamina_cost=2)
    search_action.add_outcome("success", Outcome(
        text="You find some scrap metal.",
        items_reward={"scrap_metal": 2}
    ))
    search_action.add_outcome("failure", Outcome(
        text="Nothing useful here."
    ))
    rubble.add_action(search_action)
    start.add_interactable("start_rubble", rubble)
    
    world.add_location(start)
    
    return world


def export_map_data() -> dict:
    """
    Export map data for external visualization.
    Returns a dictionary with locations, connections, interactables, and enemy spawns.
    Can be saved as JSON for use in web-based or other visualizers.
    """
    from data.npcs import LOCATION_SPAWNS, NPCS, LOCATION_DANGER, get_danger_level, get_location_encounter_rate, get_wandering_enemy_chance
    
    map_data = {
        "locations": [],
        "connections": [],
        "interactables": [],
        "spawn_tables": {}
    }
    
    for location in game_world.locations.values():
        # Get danger information
        danger_level = get_danger_level(location.id)
        encounter_rate = get_location_encounter_rate(location.id)
        wandering_chance = get_wandering_enemy_chance(location.id)
        
        # Add location data with image and danger info
        map_data["locations"].append({
            "id": location.id,
            "name": location.name,
            "description": location.description,
            "x": location.x,
            "y": location.y,
            "image_path": location.image_path,
            "interactable_count": len(location.interactables),
            "danger_level": danger_level,
            "encounter_rate": round(encounter_rate * 100, 1),  # As percentage
            "wandering_chance": round(wandering_chance * 100, 1)  # As percentage
        })
        
        # Add interactable data with images and loot chances
        for instance_id, interactable in location.interactables.items():
            interactable_data = {
                "instance_id": instance_id,
                "location_id": location.id,
                "id": interactable.id,
                "name": interactable.name,
                "image_path": interactable.image_path,
                "actions": []
            }
            
            # Process each action and its outcomes
            for action in interactable.actions.values():
                action_data = {
                    "id": action.id,
                    "label": action.label,
                    "stamina_cost": action.stamina_cost,
                    "outcomes": []
                }
                
                # Add outcome information (for loot chances)
                for outcome_name, outcome in action.outcomes.items():
                    outcome_data = {
                        "type": outcome_name,
                        "text": outcome.text,
                        "items": outcome.items_reward,
                        "damage": outcome.damage_taken
                    }
                    action_data["outcomes"].append(outcome_data)
                
                interactable_data["actions"].append(action_data)
            
            map_data["interactables"].append(interactable_data)
        
        # Add connections
        for direction, destination in location.exits.items():
            # Calculate stamina cost based on distance between locations
            dest_loc = game_world.get_location(destination)
            if dest_loc:
                from .travel_helpers import calculate_base_stamina_cost
                stamina_cost = calculate_base_stamina_cost(location, dest_loc)
            else:
                stamina_cost = 5  # Fallback
            
            map_data["connections"].append({
                "from": location.id,
                "to": destination,
                "direction": direction,
                "stamina_cost": stamina_cost
            })
        
        # Add spawn table for this location
        if location.id in LOCATION_SPAWNS:
            spawn_data = []
            for npc_id, weight in LOCATION_SPAWNS[location.id]:
                if npc_id in NPCS:
                    npc = NPCS[npc_id]
                    spawn_data.append({
                        "npc_id": npc_id,
                        "name": npc.name,
                        "emoji": npc.emoji,
                        "weight": weight,
                        "level_range": f"{npc.hp_min}-{npc.hp_max} HP"
                    })
            map_data["spawn_tables"][location.id] = spawn_data
    
    return map_data


# Create singleton world instance on module import
game_world = load_world()
