"""Reply sentiment classifier.

Classifies LinkedIn reply messages into:
- positive: "Let's talk!", "Sounds interesting"
- negative: "Not interested", "Stop messaging me"
- question: "How much?", "What do you do?"
- neutral: "Thanks", "OK"
- out_of_office: "I'm currently out of office"
- opt_out: "Unsubscribe", "Remove me", "Don't contact me"
"""

from __future__ import annotations

import logging
import re
from typing import Any

from .llm import LLMClient

logger = logging.getLogger(__name__)

# ──────────────────────────────────────────────
# Rule-based fast path (no LLM needed)
# ──────────────────────────────────────────────

OPT_OUT_KEYWORDS = [
    "not interested",
    "stop messaging",
    "stop contacting",
    "don't contact me",
    "do not contact",
    "unsubscribe",
    "remove me",
    "take me off",
    "leave me alone",
    "don't message me",
    "no thanks",
    "no thank you",
    "please stop",
    "opt out",
    "opt-out",
]

OOO_KEYWORDS = [
    "out of office",
    "out of the office",
    "on vacation",
    "on leave",
    "on holiday",
    "currently away",
    "will be back",
    "i'll be back",
    "limited access to email",
    "auto-reply",
    "automatic reply",
]

POSITIVE_SIGNALS = [
    "let's talk",
    "let's chat",
    "sounds interesting",
    "sounds great",
    "I'd love to",
    "i'd love to",
    "tell me more",
    "i'm interested",
    "am interested",
    "happy to chat",
    "let's set up",
    "let's schedule",
    "free next week",
    "book a time",
    "send me a link",
    "send your calendar",
    "calendly",
    "cal.com",
]


def classify_fast(reply_text: str) -> str | None:
    """Rule-based fast classification. Returns sentiment or None if uncertain."""
    text_lower = reply_text.lower().strip()

    # Check opt-out first (highest priority)
    for kw in OPT_OUT_KEYWORDS:
        if kw in text_lower:
            return "opt_out"

    # Check out-of-office
    for kw in OOO_KEYWORDS:
        if kw in text_lower:
            return "out_of_office"

    # Check positive signals
    for signal in POSITIVE_SIGNALS:
        if signal in text_lower:
            return "positive"

    # Check if it's a question
    if text_lower.endswith("?") or text_lower.count("?") >= 1:
        return "question"

    # Very short neutral responses
    if len(text_lower) < 15 and text_lower in ("thanks", "thank you", "ok", "okay", "cool", "noted", "got it"):
        return "neutral"

    # Can't determine — need LLM
    return None


SENTIMENT_SYSTEM = """You classify LinkedIn reply messages. Output ONLY one word: positive, negative, question, neutral, out_of_office, or opt_out.

Definitions:
- positive: Interested in talking, meeting, or learning more
- negative: Explicitly not interested but not hostile
- question: Asking for more info (pricing, features, details)
- neutral: Acknowledgment without clear intent
- out_of_office: Auto-reply or vacation notice
- opt_out: Asking to stop being contacted"""


async def classify_sentiment(reply_text: str) -> str:
    """Classify the sentiment of a LinkedIn reply.

    Tries fast rule-based classification first.
    Falls back to LLM for ambiguous messages.

    Returns one of: positive, negative, question, neutral, out_of_office, opt_out
    """
    # Fast path (always runs, no LLM needed)
    fast_result = classify_fast(reply_text)
    if fast_result:
        return fast_result

    # Route through backend if in backend mode and no local LLM key
    from ..config import has_local_llm_key, is_backend_mode
    if is_backend_mode() and not has_local_llm_key():
        from ..linkedin import get_linkedin_client
        backend_client = get_linkedin_client()
        try:
            return await backend_client.classify_sentiment(reply_text)
        except Exception as e:
            logger.warning(f"Backend sentiment classification failed: {e}, defaulting to neutral")
            return "neutral"
        finally:
            await backend_client.close()

    # LLM path
    try:
        client = LLMClient()
        prompt = f'Classify this LinkedIn reply message:\n\n"{reply_text}"\n\nOutput ONLY one word: positive, negative, question, neutral, out_of_office, or opt_out.'
        result = await client.generate(prompt, system=SENTIMENT_SYSTEM, temperature=0.1, max_tokens=20)
        sentiment = result.strip().lower().replace('"', "").replace("'", "")
        if not sentiment:
            return "neutral"

        valid_sentiments = {"positive", "negative", "question", "neutral", "out_of_office", "opt_out"}
        if sentiment in valid_sentiments:
            return sentiment

        # Try to extract from a longer response
        for s in valid_sentiments:
            if s in sentiment:
                return s

        logger.warning(f"LLM returned unexpected sentiment: {sentiment}, defaulting to neutral")
        return "neutral"

    except Exception as e:
        logger.warning(f"Sentiment classification failed: {e}, defaulting to neutral")
        return "neutral"
