"""
Router Agent — Punto di ingresso del grafo.

Classifica l'intent dell'utente e smista la richiesta al sotto-agente appropriato.

Funzionamento:
1. Riceve la query dell'utente
2. Cerca esempi simili nell'indice FAISS few-shot (~2750 esempi etichettati)
3. Invia query + esempi all'LLM con structured output (Pydantic)
4. L'LLM restituisce un RouteDecision con il nome dell'agente destinazione
5. RISOLUZIONE CONTESTO: se ci sono messaggi precedenti, l'LLM riscrive
   la query come frase autocontenuta (es. "di rosse?" → "scarpe rosse")
   e la salva in resolved_query per gli agenti a valle

Destinazioni possibili:
- agent_ricerca      → prodotti specifici ("cerco scarpe rosse taglia 42")
- agent_recommender  → consigli generici ("consigliami un regalo")
- agent_saluti       → saluti ("ciao", "grazie")
- agent_default      → fuori scope ("come faccio un reso?")

Usa il factory pattern: create_nodo_router(llm, router_retriever) → funzione nodo.
"""

from typing import Literal
from pydantic import BaseModel, Field  # Schema strutturato: forza l'LLM a rispondere in JSON validato
from langchain_core.messages import SystemMessage


# --- Schema di output strutturato per il Router ---

class RouteDecision(BaseModel):
    """Decisione del Router: quale agente deve gestire la richiesta."""
    step: Literal["agent_saluti", "agent_ricerca", "agent_recommender", "agent_default"] = Field(
        description="L'agente a cui assegnare la richiesta"
    )
    reasoning: str = Field(description="Motivo della scelta")


# --- Factory del nodo Router ---

def create_nodo_router(llm, router_retriever):
    """Crea il nodo Router con le dipendenze iniettate.

    Args:
        llm: istanza ChatOpenAI per la classificazione intent e risoluzione contesto
        router_retriever: retriever FAISS con esempi few-shot etichettati
    """
    def nodo_router(state):
        print(f"\n--- [ROUTER] Analisi semantica in corso... ---")
        last_msg = state["messages"][-1].content

        # Recupera esempi few-shot simili alla query dell'utente
        examples_context = ""
        if router_retriever:
            try:
                similar_docs = router_retriever.invoke(last_msg)
                ex_list = [f"- '{d.page_content}' -> {d.metadata['target_agent']}" for d in similar_docs]
                examples_context = "\n".join(ex_list)
            except:
                pass

        # Prompt di sistema con regole di routing + esempi recuperati
        sys_msg = SystemMessage(content=f"""Sei il Router. Scegli l'agente:
    1. agent_ricerca: Per prodotti specifici (scarpe rosse, jeans, taglia M).
    2. agent_recommender: Per CONSIGLI generici, idee regalo, outfit.
    3. agent_default: Assistenza, spedizioni, resi.
    4. agent_saluti: Ciao, grazie.

    ESEMPI:
    {examples_context}
    """)

        # Invoca l'LLM con structured output per ottenere un RouteDecision
        try:
            router_llm = llm.with_structured_output(RouteDecision)
            response = router_llm.invoke([sys_msg] + state["messages"])
            decision = response.step
            print(f"   Query Utente: '{last_msg}'")
            print(f"   Decisione AI: {decision.upper()}")
        except Exception as e:
            print(f"   Errore Router ({e}), vado su Default.")
            return {"decision": "agent_default", "resolved_query": last_msg}

        # --- Risoluzione contesto conversazionale ---
        # Se ci sono messaggi precedenti, l'ultimo potrebbe essere ambiguo
        # (es. "di rosse?" senza soggetto). L'LLM riscrive la query come
        # frase autocontenuta usando il contesto della conversazione.
        if len(state["messages"]) > 1:
            try:
                resolve_prompt = f"""Task: Extract search keywords from the conversation context.

Previous conversation context and current message are provided. Output only the product keywords (nouns/adjectives) that describe what the user is searching for. Remove conversational words like "consigliami", "simili", "cerco", "voglio", etc.

Examples:
- Context: ["voglio scarpe", "di rosse?"] → Output: scarpe rosse
- Context: ["cerco jeans", "quale modello simile?"] → Output: jeans
- Context: ["scarpe rosse da donna", "me ne consigli?"] → Output: scarpe rosse donna
- Context: ["consigliami un regalo", "per mia sorella"] → Output: regalo donna

Current message: "{last_msg}"
Output keywords only:"""
                resolved_msg = llm.invoke([sys_msg] + state["messages"][:-1] + [SystemMessage(content=resolve_prompt)])
                resolved_query = resolved_msg.content.strip().strip('"').strip("'")
                print(f"   Query risolta: '{last_msg}' -> '{resolved_query}'")
            except Exception:
                resolved_query = last_msg
        else:
            # Primo turno: la query e' gia' autocontenuta
            resolved_query = last_msg

        return {"decision": decision, "resolved_query": resolved_query}

    return nodo_router
