"""3 katmanlı intent router: RuleMatcher → SemanticRouter → LLM kararı.

ARCHITECTURE §14: strateji zinciri. Karar (layer, intent, reply) döner; reply None
veya marker'sa orchestrator (FlovyService) işler.
"""
import logging
from dataclasses import dataclass

from fastapi import Depends

from app.services.ai.rule_matcher import RuleMatcher
from app.services.ai.semantic_router import SemanticRouter
from app.utils.exceptions import ExternalServiceError

logger = logging.getLogger("flovy")


@dataclass
class RouteDecision:
    layer: str  # "rule" | "semantic" | "llm"
    intent: str | None
    reply: str | None  # hazır cevap, marker, veya None (LLM)
    score: float | None = None


class IntentRouter:
    def __init__(
        self,
        rule_matcher: RuleMatcher = Depends(),
        semantic_router: SemanticRouter = Depends(),
    ):
        self.rule_matcher = rule_matcher
        self.semantic_router = semantic_router

    async def decide(self, message: str) -> RouteDecision:
        # Katman 1 — regex
        rule = self.rule_matcher.match(message)
        if rule and rule.reply is not None:
            return RouteDecision(layer="rule", intent=rule.intent, reply=rule.reply)
        # affirmation gibi reply=None → context bağımlı, LLM'e bırak

        # Katman 2 — semantic (embedding hatası olursa LLM'e düş)
        try:
            sem = await self.semantic_router.match(message)
        except ExternalServiceError as e:
            logger.warning("semantic router atlandı: %s", e.code)
            sem = None
        if sem is not None:
            return RouteDecision(
                layer="semantic", intent=sem.intent, reply=sem.reply, score=sem.score
            )

        # Katman 3 — LLM
        return RouteDecision(layer="llm", intent=None, reply=None)
