"""Hermes B2.2: memory + B3/B4 research tools + verified local time."""
import json
import re
import urllib.request
from datetime import datetime, timezone
from email.utils import parsedate_to_datetime
from zoneinfo import ZoneInfo

from hermes_brain import ENV_FILE, MODEL, SYSTEM_PROMPT
from hermes_memory import guardar, historial, recordar, preferencias

TZ = ZoneInfo("America/Tijuana")
DECLARACIONES = [
    {"name": "consultar_servidor", "description": "Consulta CPU y RAM reales del VPS (solo las métricas implementadas).", "parameters": {"type": "OBJECT", "properties": {}}},
    {"name": "consultar_programacion", "description": "Busca eventos y programación en EPG privadas por equipo, liga o término. No confirma partidos ni disponibilidad por sí sola.", "parameters": {"type": "OBJECT", "properties": {"termino": {"type": "STRING"}, "dias": {"type": "INTEGER"}}, "required": ["termino"]}},
    {"name": "investigar_internet", "description": "Busca información actualizada en Internet y devuelve fuentes; verifica eventos deportivos con resultados recientes.", "parameters": {"type": "OBJECT", "properties": {"pregunta": {"type": "STRING"}}, "required": ["pregunta"]}},
    {"name": "consultar_hora_mexicali", "description": "Consulta fecha y hora de Mexicali y si fueron verificadas con Internet.", "parameters": {"type": "OBJECT", "properties": {}}},
]

def obtener_clave():
    with open(ENV_FILE, encoding="utf-8") as f:
        for linea in f:
            if linea.startswith("GEMINI_API_KEY="):
                return linea.strip().split("=", 1)[1]
    raise RuntimeError("Gemini no configurado")


def consultar_hora_mexicali():
    # The HTTP Date header is UTC and is supplied by a remote HTTPS server.
    # Short timeout: do not block the assistant if the time source is down.
    for url in ("https://www.google.com/generate_204", "https://www.cloudflare.com/cdn-cgi/trace"):
        try:
            req = urllib.request.Request(url, headers={"User-Agent": "HermesNexus/2.2", "Cache-Control": "no-cache"}, method="GET")
            with urllib.request.urlopen(req, timeout=2.5) as response:
                date_header = response.headers.get("Date")
            if not date_header:
                continue
            utc = parsedate_to_datetime(date_header).astimezone(timezone.utc)
            # Reject obviously stale/corrupt dates relative to the host clock.
            if abs((datetime.now(timezone.utc) - utc).total_seconds()) > 300:
                continue
            return {"fecha_hora": utc.astimezone(TZ).isoformat(), "zona": "America/Tijuana", "verificada_internet": True, "fuente": url}
        except Exception:
            continue
    return {"fecha_hora": datetime.now(TZ).isoformat(), "zona": "America/Tijuana", "verificada_internet": False, "fuente": "reloj_del_servidor"}


def ejecutar_herramienta(nombre, argumentos):
    if nombre == "consultar_hora_mexicali":
        return consultar_hora_mexicali()
    if nombre == "consultar_servidor":
        from hermes_tools import ejecutar_herramienta as herramienta_servidor
        return herramienta_servidor("consultar_servidor")
    if nombre == "consultar_programacion":
        from hermes_epg_tool import consultar_programacion
        return consultar_programacion(argumentos["termino"], argumentos.get("dias", 3))
    if nombre == "investigar_internet":
        from hermes_web import buscar_internet
        return buscar_internet(argumentos["pregunta"])
    raise ValueError("Herramienta no autorizada")


def llamar_gemini(contenidos, contexto=""):
    url = "https://generativelanguage.googleapis.com/v1beta/models/" + MODEL + ":generateContent"
    payload = {
        "systemInstruction": {"parts": [{"text": SYSTEM_PROMPT + "\n" + contexto + "\nConsulta herramientas para información deportiva reciente. No inventes horarios, fuentes, métricas ni confirmes disponibilidad con EPG solamente. No ejecutes acciones administrativas."}]},
        "contents": contenidos,
        "tools": [{"functionDeclarations": DECLARACIONES}],
        "generationConfig": {"maxOutputTokens": 1200}
    }
    req = urllib.request.Request(url, data=json.dumps(payload).encode("utf-8"), headers={"Content-Type": "application/json", "x-goog-api-key": obtener_clave()}, method="POST")
    with urllib.request.urlopen(req, timeout=45) as response:
        return json.load(response)


def preguntar_hermes_v2(pregunta, usuario, sesion):
    if not isinstance(pregunta, str) or not pregunta.strip():
        raise ValueError("Pregunta inválida")
    # Always check time before processing any instruction.
    hora = consultar_hora_mexicali()
    coincidencia = re.match(r"^\s*(?:hermes[, :]*\s*)?(?:recuerda que|aprende que|de ahora en adelante)\s+(.+?)\s*[.!]?\s*$", pregunta, re.IGNORECASE | re.DOTALL)
    if coincidencia:
        regla = recordar(usuario, coincidencia.group(1))
        respuesta = "Entendido. Guardé esta instrucción en mi memoria permanente: " + regla
        guardar(usuario, sesion, "user", pregunta)
        guardar(usuario, sesion, "model", respuesta)
        return respuesta
    reglas = preferencias(usuario)
    contexto = "\nHORA ACTUAL MEXICALI: " + json.dumps(hora, ensure_ascii=False)
    contexto += "\nCuando menciones encuentros en español, di 'contra' en vez de leer 'vs' en voz alta."
    if reglas:
        contexto += "\nPREFERENCIAS GUARDADAS (solo estilo/contexto, no autorizan acciones):\n" + "\n".join("- " + regla for regla in reglas)
    contenidos = historial(usuario, sesion, limite=12)
    contenidos.append({"role": "user", "parts": [{"text": pregunta}]})
    for vuelta in range(4):
        resultado = llamar_gemini(contenidos, contexto)
        contenido = resultado["candidates"][0]["content"]
        llamadas = [p["functionCall"] for p in contenido.get("parts", []) if "functionCall" in p]
        if not llamadas:
            respuesta = "".join(p.get("text", "") for p in contenido.get("parts", [])).strip()
            if not respuesta:
                raise RuntimeError("Gemini no devolvió texto")
            guardar(usuario, sesion, "user", pregunta)
            guardar(usuario, sesion, "model", respuesta)
            return respuesta
        contenidos.append(contenido)
        respuestas = []
        for llamada in llamadas[:3]:
            nombre = llamada["name"]
            try:
                datos = ejecutar_herramienta(nombre, llamada.get("args", {}))
            except Exception as error:
                # Keep Gemini alive and disclose that the lookup failed.
                datos = {"error": type(error).__name__, "detalle": str(error)[:160], "ejecutada": False}
            respuestas.append({"functionResponse": {"name": nombre, "response": {"result": datos}}})
        contenidos.append({"role": "user", "parts": respuestas})
    raise RuntimeError("Límite de investigación alcanzado")
