import json
import random
import requests
from .npc_data import NPC_DATABASE  # <-- Add this import

def query_llm(prompt, model="neural-chat", url="http://100.103.117.14:11434/api/generate"):
    # Add instruction for short answers
    short_prompt = prompt + "\n\nKeep your answer short and concise (1-2 sentences)."
    payload = {
        "model": model,
        "prompt": short_prompt,
        "stream": False
    }
    try:
        response = requests.post(url, json=payload, timeout=120)
        response.raise_for_status()
        data = response.json()
        return data.get("response", "").strip()
    except Exception as e:
        print(f"LLM error: {e}")
        return None

class DynamicNPC:
    def __init__(self, name, data):
        self.name = name
        self.personality = data["personality"]
        self.backstory = data["backstory"]
        self.quirks = data["quirks"]

class NPCHandler:
    def __init__(self, memory):
        self.memory = memory
        self.npcs = {name: DynamicNPC(name, data) for name, data in NPC_DATABASE.items()}

    def chat_with_npc(self, npc_name, message, player_context):
        npc = self.npcs.get(npc_name)
        if not npc:
            return "That NPC doesn't exist."

        player_id = player_context['id']

        # Fetch recent conversation history (last 3 exchanges)
        history = self.memory.get_conversation(npc_name, player_id)
        history_str = ""
        if history:
            history_str = "\nRecent conversation:\n"
            for player_msg, npc_reply in history[-3:]:
                history_str += f"Player: {player_msg}\n{npc.name}: {npc_reply}\n"

        # Fetch affinity
        affinity = self.memory.get_affinity(npc_name, player_id)
        affinity_str = f"Affinity with player: {affinity}\n"

        prompt = (
            f"You are {npc.name}, an NPC in a fantasy world.\n"
            f"Personality: {npc.personality}\n"
            f"Backstory: {npc.backstory}\n"
            f"Quirks: {', '.join(npc.quirks)}\n"
            f"{history_str}"
            f"{affinity_str}"
            f"Player (level {player_context.get('level', 1)}): {message}\n"
            f"Respond in character as {npc.name}."
        )
        llm_response = query_llm(prompt)
        if not llm_response:
            llm_response = f"{npc.name} seems lost in thought and doesn't reply."
        self.memory.log_conversation(npc_name, player_id, message, llm_response)
        self.memory.update_affinity(npc_name, player_id, 1)
        return llm_response

    def generate_quest(self, npc_name, player_level):
        npc = self.npcs.get(npc_name)
        if not npc:
            return None
        prompt = (
            f"As {npc.name}, create a short quest for a level {player_level} adventurer.\n"
            f"Personality: {npc.personality}\n"
            f"Backstory: {npc.backstory}\n"
            f"Format as JSON:\n"
            "{{\n"
            '  "title": "Quest name",\n'
            '  "description": "What the player must do",\n'
            '  "reward": "coins/items/reputation",\n'
            '  "difficulty": "easy/medium/hard"\n'
            "}}"
        )
        llm_response = query_llm(prompt)
        try:
            if not llm_response:
                raise ValueError("No response from LLM")
            quest = json.loads(llm_response)
            return quest
        except Exception:
            quest = {
                "title": f"{npc.name}'s Request",
                "description": f"Help {npc.name} with a task suitable for level {player_level}.",
                "reward": f"{random.randint(10, 100)} coins",
                "difficulty": random.choice(["easy", "medium", "hard"])
            }
            return quest