import json
from typing import Tuple, List, Dict
from xulcan.protocol.tools import ToolDefinition

class ToolingStrategy:
    """Interfaz base para estrategias de Tool Calling."""
    def apply(self, messages: list[dict], tools: list[ToolDefinition]) -> Tuple[list[dict], list[dict] | None]:
        raise NotImplementedError

class NativeToolStrategy(ToolingStrategy):
    """Para modelos Tier 1 (Qwen 32B, Llama 3.3). Usa la API oficial."""
    def apply(self, messages: list[dict], tools: list[ToolDefinition]) -> Tuple[list[dict], list[dict] | None]:
        ollama_tools =[]
        if tools:
            for t in tools:
                ollama_tools.append({
                    "type": "function",
                    "function": {
                        "name": t.function.name,
                        "description": t.function.description or "",
                        "parameters": t.function.parameters
                    }
                })
        return messages, ollama_tools if ollama_tools else None

class PromptInjectionStrategy(ToolingStrategy):
    """Para modelos Tier 2 (7B, R1). Inyecta manuales de instrucciones en el System Prompt."""
    def apply(self, messages: list[dict], tools: list[ToolDefinition]) -> Tuple[list[dict], list[dict] | None]:
        if not tools:
            return messages, None
            
        prompt = "\n\n*** INSTRUCCIONES ESTRICTAS PARA EL USO DE HERRAMIENTAS ***\nTienes las siguientes herramientas disponibles:\n"
        for t in tools:
            prompt += f"- Nombre: {t.function.name}\n  Descripción: {t.function.description}\n  Argumentos requeridos: {json.dumps(t.function.parameters)}\n\n"
        
        prompt += (
            "Si necesitas usar una herramienta, DEBES responder ÚNICAMENTE con un bloque JSON "
            "exactamente con este formato, sin texto adicional fuera del bloque:\n"
            "```json\n{\n  \"tool_call\": {\n    \"name\": \"nombre_de_la_herramienta\",\n    \"arguments\": {\"arg1\": \"valor\"}\n  }\n}\n```"
        )
        
        new_messages = list(messages)
        if new_messages and new_messages[0]["role"] == "system":
            new_messages[0]["content"] += prompt
        else:
            new_messages.insert(0, {"role": "system", "content": prompt})
            
        return new_messages, None # Retorna None en tools para no romper la API de Ollama