"""Sentiment Analysis Engine — emotional memory layer.

Uses DistilBERT-based sentiment model to score memories on a -1.0 to 1.0 scale.
High-emotion memories get a configurable retrieval boost — just like real brains.
"""

from __future__ import annotations

import re
from typing import Optional


# Keyword-based sentiment for fast fallback (no model dependency)
POSITIVE_WORDS = {
    "love", "great", "excellent", "amazing", "happy", "wonderful",
    "fantastic", "awesome", "beautiful", "perfect", "enjoy", "best",
    "excited", "brilliant", "outstanding", "superb", "delighted",
    "pleased", "favorite", "incredible", "remarkable", "impressive",
    "prefer", "like", "good", "nice", "helpful", "useful",
}

NEGATIVE_WORDS = {
    "hate", "terrible", "awful", "horrible", "bad", "worst",
    "angry", "frustrated", "annoying", "disgusting", "wrong",
    "fail", "failed", "error", "broken", "crash", "bug",
    "disappointed", "useless", "pathetic", "regret", "stupid",
    "slow", "ugly", "boring", "confusing", "difficult", "problem",
}

INTENSIFIERS = {
    "very", "extremely", "really", "absolutely", "incredibly",
    "totally", "completely", "utterly", "highly", "deeply",
}


class SentimentEngine:
    """Scores memory content for emotional valence.

    Uses keyword-based analysis by default (fast, zero-dependency).
    Can optionally use DistilBERT for higher accuracy.
    """

    def __init__(self, config=None, use_model: bool = False):
        self.config = config
        self.use_model = use_model
        self._model = None
        self._tokenizer = None

    def score(self, text: str) -> float:
        """Score text sentiment from -1.0 (negative) to 1.0 (positive).

        Returns 0.0 for neutral text.
        """
        if self.use_model:
            return self._score_with_model(text)
        return self._score_keywords(text)

    def score_batch(self, texts: list[str]) -> list[float]:
        """Score multiple texts for sentiment."""
        return [self.score(t) for t in texts]

    def classify(self, text: str) -> str:
        """Classify as 'positive', 'negative', or 'neutral'."""
        score = self.score(text)
        if score > 0.2:
            return "positive"
        elif score < -0.2:
            return "negative"
        return "neutral"

    def _score_keywords(self, text: str) -> float:
        """Fast keyword-based sentiment scoring."""
        words = set(re.findall(r'\b\w+\b', text.lower()))

        pos_count = len(words & POSITIVE_WORDS)
        neg_count = len(words & NEGATIVE_WORDS)
        intensifier_count = len(words & INTENSIFIERS)

        if pos_count == 0 and neg_count == 0:
            return 0.0

        # Base score
        total = pos_count + neg_count
        raw_score = (pos_count - neg_count) / total

        # Intensifier boost (amplifies the score)
        if intensifier_count > 0:
            boost = 1.0 + (0.15 * intensifier_count)
            raw_score *= boost

        # Clamp to [-1.0, 1.0]
        return max(-1.0, min(1.0, raw_score))

    def _score_with_model(self, text: str) -> float:
        """Score using DistilBERT sentiment model."""
        if self._model is None:
            try:
                from transformers import pipeline
                self._model = pipeline(
                    "sentiment-analysis",
                    model="distilbert-base-uncased-finetuned-sst-2-english",
                    truncation=True,
                    max_length=512,
                )
            except ImportError:
                return self._score_keywords(text)

        result = self._model(text[:512])[0]
        score = result["score"]
        if result["label"] == "NEGATIVE":
            score = -score
        return score
