from __future__ import annotations

import re

from costrouter.models import CostTier
from costrouter.router.base import BaseRouter

_GREETING_PATTERNS = re.compile(
    r"^(hi|hello|hey|thanks|thank you|bye|goodbye|good morning|good night)\b",
    re.IGNORECASE,
)

_CODE_KEYWORDS = re.compile(
    r"\b(write a function|debug|implement|refactor|code review|fix the bug|write code|write a script|write a program)\b",
    re.IGNORECASE,
)

_CODE_BLOCK = re.compile(r"```")

_EXPERT_MARKERS = re.compile(
    r"\b(prove|derive|theorem|differential equation|eigenvalue|asymptotic|formal verification|type theory)\b",
    re.IGNORECASE,
)

_CREATIVE_WRITING = re.compile(
    r"\b(write a story|write a poem|compose|write an essay|write a novel|creative writing)\b",
    re.IGNORECASE,
)

_SIMPLE_FACTUAL = re.compile(
    r"^(what is|who is|when did|where is|define|what does|how old)\b",
    re.IGNORECASE,
)

_ANALYSIS_REASONING = re.compile(
    r"\b(compare|analyze|explain why|evaluate|assess|critique|contrast|discuss the implications)\b",
    re.IGNORECASE,
)


def _get_last_user_content(messages: list[dict]) -> str:
    """Extract the last user message content."""
    for msg in reversed(messages):
        if msg.get("role") == "user":
            content = msg.get("content", "")
            return content if isinstance(content, str) else str(content)
    return ""


class HeuristicRouter(BaseRouter):
    """Free, instant, rule-based router. No API calls."""

    def classify(self, messages: list[dict]) -> tuple[CostTier, float, float]:
        text = _get_last_user_content(messages)
        stripped = text.strip()

        # Rule 1: Very short prompts
        if len(stripped) < 20:
            return CostTier.SIMPLE, 0.7, 0.0

        # Rule 2: Code keywords or code blocks (check before greetings so
        # "Hey, write a function..." isn't misclassified as SIMPLE)
        if _CODE_KEYWORDS.search(stripped) or _CODE_BLOCK.search(stripped):
            return CostTier.COMPLEX, 0.7, 0.0

        # Rule 3: Expert markers (before greetings for the same reason)
        if _EXPERT_MARKERS.search(stripped):
            return CostTier.EXPERT, 0.6, 0.0

        # Rule 4: Greeting patterns (only reaches here if no complex/expert markers)
        if _GREETING_PATTERNS.search(stripped):
            return CostTier.SIMPLE, 0.9, 0.0

        # Rule 5: Creative writing
        if _CREATIVE_WRITING.search(stripped):
            return CostTier.COMPLEX, 0.6, 0.0

        # Rule 6: Simple factual questions
        if _SIMPLE_FACTUAL.search(stripped):
            return CostTier.SIMPLE, 0.6, 0.0

        # Rule 7: Analysis / reasoning
        if _ANALYSIS_REASONING.search(stripped):
            return CostTier.MODERATE, 0.5, 0.0

        # Rule 8: Default
        return CostTier.MODERATE, 0.3, 0.0

    async def aclassify(self, messages: list[dict]) -> tuple[CostTier, float, float]:
        return self.classify(messages)
