"""Intent router — classifies user requests and routes to the best agent."""

from __future__ import annotations

import logging
from typing import TYPE_CHECKING

from vastian.agents.registry import AgentRegistry

if TYPE_CHECKING:
    from vastian.providers.llm_provider import BaseLLMProvider

logger = logging.getLogger(__name__)

# Keyword-based routing table (used when LLM routing is unavailable)
KEYWORD_ROUTES: dict[str, list[str]] = {
    "liam": ["task", "todo", "sync", "daily", "schedule", "priority", "flow"],
    "theo": ["prompt", "design", "framework", "scenario", "methodology", "template"],
    "elias": [
        "knowledge",
        "memory",
        "insight",
        "tag",
        "integration",
        "bank",
        "vkb",
        "document backup",
        "backup",
    ],
    "dominic": ["strategy", "strategic", "integration", "escalation", "consolidation"],
    "victor": [
        "vision",
        "long-term",
        "roadmap",
        "health",
        "spiritual",
        "longevity",
        "mentor network",
    ],
    "orion": ["operations", "architecture", "system", "quest", "compass", "eos", "alignment"],
    "charles": ["status", "metrics", "milestone", "dashboard", "overview", "command center"],
    "henry": [
        "systems",
        "technical",
        "architecture",
        "engineering",
        "build",
        "performance",
        "system health",
    ],
    "finley": ["finance", "investor", "budget", "funding", "revenue", "money"],
    "concord": ["scenario", "coordination", "guide", "simulation"],
    "jake": ["test", "testing", "implementation", "validate", "qa"],
}

# ── Escalation Pathways ────────────────────────────────────────────
# Define structured escalation chains for specific problem domains.
# Each pathway is a list of agents from first contact → escalation tiers.
ESCALATION_PATHWAYS: dict[str, dict] = {
    "sync_coordination": {
        "description": "Sync-related issues (task flow, knowledge sync, schedule conflicts)",
        "chain": ["liam", "theo", "elias"],
        "keywords": [
            "sync issue",
            "sync problem",
            "coordination issue",
            "sync conflict",
            "out of sync",
            "sync failure",
            "role sync",
            "sync stuck",
        ],
    },
    "system_health": {
        "description": "System health, performance, recovery, and backup actions",
        "chain": ["henry", "adrian"],
        "keywords": [
            "system health",
            "performance issue",
            "slow",
            "degraded",
            "recovery",
            "system down",
            "not working",
            "broken",
            "performance problem",
            "system error",
        ],
    },
    "document_backup": {
        "description": "Document backups, data integrity, and backup management",
        "chain": ["elias", "henry"],
        "keywords": [
            "document backup",
            "backup",
            "data loss",
            "restore",
            "document recovery",
            "data integrity",
            "backup management",
            "lost document",
            "missing document",
        ],
    },
}


class IntentRouter:
    """
    Routes user requests to the most appropriate agent.

    Uses LLM-based classification when available, falls back to keyword matching.
    Supports structured escalation pathways for specific problem domains.
    """

    def __init__(
        self,
        registry: AgentRegistry,
        llm: BaseLLMProvider | None = None,
    ) -> None:
        self.registry = registry
        self.llm = llm

    async def route(self, user_message: str) -> str:
        """
        Determine which agent should handle a user message.

        Returns the agent_id of the best match.
        """
        # Check escalation pathways first (high-priority domain routing)
        escalation_agent = self._check_escalation_pathways(user_message)
        if escalation_agent:
            return escalation_agent

        # Try LLM-based routing first
        if self.llm:
            try:
                return await self._llm_route(user_message)
            except Exception:
                logger.warning("LLM routing failed, falling back to keywords")

        # Keyword-based fallback
        return self._keyword_route(user_message)

    def _check_escalation_pathways(self, user_message: str) -> str | None:
        """
        Check if the message matches a known escalation pathway.

        Escalation pathways route to the FIRST agent in the chain (primary contact).
        The chain defines who to escalate to if the primary can't resolve it.

        Returns the primary agent_id, or None if no pathway matches.
        """
        message_lower = user_message.lower()
        best_pathway: str | None = None
        best_score = 0

        for pathway_id, pathway in ESCALATION_PATHWAYS.items():
            score = sum(1 for kw in pathway["keywords"] if kw in message_lower)
            if score > best_score:
                best_score = score
                best_pathway = pathway_id

        if best_pathway and best_score > 0:
            chain = ESCALATION_PATHWAYS[best_pathway]["chain"]
            # Route to the first available agent in the chain
            for agent_id in chain:
                if self.registry.get_config(agent_id):
                    logger.info(
                        "Escalation pathway '%s' activated → %s (chain: %s)",
                        best_pathway,
                        agent_id,
                        " → ".join(chain),
                    )
                    return agent_id

        return None

    def get_escalation_chain(self, pathway_id: str) -> list[str]:
        """Get the full escalation chain for a pathway."""
        pathway = ESCALATION_PATHWAYS.get(pathway_id)
        return pathway["chain"] if pathway else []

    def get_all_pathways(self) -> dict[str, dict]:
        """Return all defined escalation pathways."""
        return ESCALATION_PATHWAYS

    async def _llm_route(self, user_message: str) -> str:
        """Use the LLM to classify intent and select an agent."""
        agent_descriptions = []
        for config in self.registry.all_configs:
            agent_descriptions.append(
                f"- **{config.agent_id}** ({config.name}, {config.title}): "
                f"{config.role_description[:150]}"
            )

        escalation_info = "\n\nESCALATION PATHWAYS (use these for matching issues):\n"
        for pid, pathway in ESCALATION_PATHWAYS.items():
            chain_str = " → ".join(pathway["chain"])
            escalation_info += f"- {pid}: {pathway['description']} | Chain: {chain_str}\n"

        system_prompt = (
            "You are the Vastian Network router. Given a user message, determine which "
            "agent should handle it. Respond with ONLY the agent_id, nothing else.\n\n"
            "Available agents:\n" + "\n".join(agent_descriptions) + escalation_info
        )

        response = await self.llm.generate(
            system_prompt=system_prompt,
            messages=[{"role": "user", "content": user_message}],
            temperature=0.0,
            max_tokens=50,
        )

        agent_id = response.strip().lower().replace('"', "").replace("'", "")
        # Validate the response is a known agent
        if self.registry.get_config(agent_id):
            return agent_id

        # Try to extract agent_id from response
        for aid in self.registry.agent_ids:
            if aid in agent_id:
                return aid

        logger.warning("LLM router returned unknown agent: %s, defaulting to charles", response)
        return "charles"

    def _keyword_route(self, user_message: str) -> str:
        """Simple keyword-based routing."""
        message_lower = user_message.lower()
        scores: dict[str, int] = {}

        for agent_id, keywords in KEYWORD_ROUTES.items():
            # Only route to agents that exist in the registry
            if not self.registry.get_config(agent_id):
                continue
            score = sum(1 for kw in keywords if kw in message_lower)
            if score > 0:
                scores[agent_id] = score

        if scores:
            best = max(scores, key=scores.get)  # type: ignore[arg-type]
            logger.debug("Keyword route: %s (score: %d)", best, scores[best])
            return best

        # Default to Charles as the intake coordinator
        return "charles"

    def explain_route(self, user_message: str) -> dict:
        """Explain why a particular route was chosen (for debugging)."""
        message_lower = user_message.lower()
        scores: dict[str, dict] = {}

        for agent_id, keywords in KEYWORD_ROUTES.items():
            matches = [kw for kw in keywords if kw in message_lower]
            if matches:
                scores[agent_id] = {"score": len(matches), "matched_keywords": matches}

        chosen = self._keyword_route(user_message)
        return {
            "chosen_agent": chosen,
            "all_scores": scores,
            "method": "keyword",
        }
