"""Style validator using semantic similarity."""
from typing import Dict, Any, List
from loguru import logger
import numpy as np

from src.agents.base import BaseAgent


class StyleValidator(BaseAgent):
    """Agent for validating writing style using semantic similarity."""

    def __init__(self):
        """Initialize style validator."""
        super().__init__("StyleValidator")
        self.model = None
        self._initialize_model()

    def _initialize_model(self):
        """Initialize sentence transformer model."""
        try:
            from sentence_transformers import SentenceTransformer
            from sklearn.metrics.pairwise import cosine_similarity

            # Store for later use
            self.cosine_similarity = cosine_similarity

            # Load best multilingual model
            self.model = SentenceTransformer('paraphrase-multilingual-mpnet-base-v2')
            logger.info("SentenceTransformer model loaded successfully")
        except Exception as e:
            logger.error(f"Failed to load SentenceTransformer: {e}")
            self.model = None

    async def process(
        self,
        generated_text: str,
        reference_texts: List[str],
        threshold: float = 0.75
    ) -> Dict[str, Any]:
        """
        Validate if generated text matches the style of reference texts.

        Args:
            generated_text: The text to validate
            reference_texts: List of reference texts to compare against
            threshold: Minimum similarity score to pass (0-1)

        Returns:
            Validation result with similarity scores
        """
        if not self.model:
            logger.warning("SentenceTransformer not available, skipping style validation")
            return {
                "passed": True,
                "available": False,
                "avg_similarity": 0.0,
                "max_similarity": 0.0,
                "threshold": threshold
            }

        if not reference_texts or len(reference_texts) == 0:
            logger.warning("No reference texts provided for style validation")
            return {
                "passed": True,
                "available": True,
                "avg_similarity": 0.0,
                "max_similarity": 0.0,
                "threshold": threshold,
                "warning": "No reference texts available"
            }

        logger.info(f"Validating style against {len(reference_texts)} reference texts")

        try:
            # Generate embeddings
            gen_embedding = self.model.encode([generated_text])
            ref_embeddings = self.model.encode(reference_texts)

            # Calculate similarities
            similarities = self.cosine_similarity(gen_embedding, ref_embeddings)[0]
            avg_similarity = float(np.mean(similarities))
            max_similarity = float(np.max(similarities))
            min_similarity = float(np.min(similarities))
            std_similarity = float(np.std(similarities))

            # Find most similar reference
            most_similar_idx = int(np.argmax(similarities))

            # Determine if passed
            passed = avg_similarity >= threshold

            # Get verdict
            verdict = self._get_verdict(avg_similarity, threshold)

            result = {
                "passed": passed,
                "available": True,
                "avg_similarity": avg_similarity,
                "max_similarity": max_similarity,
                "min_similarity": min_similarity,
                "std_similarity": std_similarity,
                "threshold": threshold,
                "most_similar_ref_idx": most_similar_idx,
                "verdict": verdict,
                "similarity_scores": [float(s) for s in similarities]
            }

            if passed:
                logger.info(f"✅ Style validation passed (avg: {avg_similarity:.3f}, threshold: {threshold})")
            else:
                logger.warning(f"⚠️ Style validation failed (avg: {avg_similarity:.3f}, threshold: {threshold})")

            return result

        except Exception as e:
            logger.error(f"Style validation failed: {e}")
            return {
                "passed": False,
                "available": False,
                "error": str(e),
                "avg_similarity": 0.0,
                "max_similarity": 0.0,
                "threshold": threshold
            }

    def _get_verdict(self, similarity: float, threshold: float) -> str:
        """Get human-readable verdict based on similarity score."""
        if similarity >= 0.85:
            return "✅ Exzellenter Stil-Match - klingt sehr authentisch"
        elif similarity >= threshold:
            return "✅ Guter Stil-Match - passt zur Person"
        elif similarity >= threshold - 0.05:
            return "⚠️ Knapp unter Schwellwert - leichte Stil-Abweichung"
        elif similarity >= 0.60:
            return "⚠️ Deutliche Stil-Abweichung - zu KI-typisch?"
        else:
            return "❌ Starke Stil-Abweichung - klingt nicht authentisch"

    async def compare_texts(
        self,
        text1: str,
        text2: str
    ) -> Dict[str, Any]:
        """
        Compare two texts for semantic similarity.

        Args:
            text1: First text
            text2: Second text

        Returns:
            Similarity score and analysis
        """
        if not self.model:
            return {"available": False, "similarity": 0.0}

        try:
            embeddings = self.model.encode([text1, text2])
            similarity = float(self.cosine_similarity([embeddings[0]], [embeddings[1]])[0][0])

            return {
                "available": True,
                "similarity": similarity,
                "verdict": "Sehr ähnlich" if similarity > 0.8 else
                          "Ähnlich" if similarity > 0.6 else
                          "Unterschiedlich"
            }
        except Exception as e:
            logger.error(f"Text comparison failed: {e}")
            return {"available": False, "similarity": 0.0, "error": str(e)}

    def get_summary(self, validation_result: Dict[str, Any]) -> str:
        """
        Get human-readable summary of validation results.

        Args:
            validation_result: Result from process()

        Returns:
            Summary string
        """
        if not validation_result.get("available"):
            return "⚠️ Stil-Validierung nicht verfügbar"

        if validation_result.get("warning"):
            return f"⚠️ {validation_result['warning']}"

        avg_sim = validation_result["avg_similarity"]
        max_sim = validation_result["max_similarity"]
        threshold = validation_result["threshold"]

        summary = f"Stil-Ähnlichkeit: {avg_sim:.1%} (max: {max_sim:.1%}, threshold: {threshold:.1%})"
        summary += f"\n{validation_result['verdict']}"

        return summary

    async def batch_validate(
        self,
        generated_texts: List[str],
        reference_texts: List[str],
        threshold: float = 0.75
    ) -> List[Dict[str, Any]]:
        """
        Validate multiple generated texts at once.

        Args:
            generated_texts: List of texts to validate
            reference_texts: Reference texts for comparison
            threshold: Minimum similarity threshold

        Returns:
            List of validation results
        """
        results = []
        for text in generated_texts:
            result = await self.process(text, reference_texts, threshold)
            results.append(result)
        return results
