"""Output quality evaluator."""

from __future__ import annotations

from typing import Any

from pydantic_ai_toolsets.evals.base import EvaluationResult


class OutputQualityEvaluator:
    """Evaluates output quality: correctness, relevance, completeness."""

    def evaluate_correctness(
        self, result: EvaluationResult, expected_output: str | None = None
    ) -> float:
        """Evaluate correctness of output.

        Args:
            result: Evaluation result.
            expected_output: Expected output string.

        Returns:
            Score from 0.0 to 1.0.
        """
        if result.error:
            return 0.0

        if not expected_output:
            # If no expected output, assume correctness if no error
            return 1.0 if result.output else 0.0

        # Simple string matching (can be enhanced with semantic similarity)
        output_lower = result.output.lower()
        expected_lower = expected_output.lower()

        # Check if expected keywords/phrases are present
        expected_words = set(expected_lower.split())
        output_words = set(output_lower.split())

        if not expected_words:
            return 1.0 if result.output else 0.0

        # Calculate overlap
        overlap = len(expected_words & output_words)
        total = len(expected_words)

        return overlap / total if total > 0 else 0.0

    def evaluate_relevance(self, result: EvaluationResult, prompt: str) -> float:
        """Evaluate relevance of output to prompt.

        Args:
            result: Evaluation result.
            prompt: Original prompt.

        Returns:
            Score from 0.0 to 1.0.
        """
        if result.error or not result.output:
            return 0.0

        # Simple heuristic: check if output contains keywords from prompt
        prompt_words = set(prompt.lower().split())
        output_words = set(result.output.lower().split())

        # Remove common stop words
        stop_words = {"the", "a", "an", "and", "or", "but", "in", "on", "at", "to", "for", "of", "with", "by"}
        prompt_words = prompt_words - stop_words
        output_words = output_words - stop_words

        if not prompt_words:
            return 1.0

        # Check overlap
        overlap = len(prompt_words & output_words)
        total = len(prompt_words)

        return min(overlap / total if total > 0 else 0.0, 1.0)

    def evaluate_completeness(
        self, result: EvaluationResult, required_aspects: list[str] | None = None
    ) -> float:
        """Evaluate completeness of output.

        Args:
            result: Evaluation result.
            required_aspects: List of aspects that should be covered.

        Returns:
            Score from 0.0 to 1.0.
        """
        if result.error or not result.output:
            return 0.0

        if not required_aspects:
            # If no specific aspects required, check if output is non-empty
            return 1.0 if result.output.strip() else 0.0

        output_lower = result.output.lower()
        covered = sum(
            1 for aspect in required_aspects if aspect.lower() in output_lower
        )

        return covered / len(required_aspects) if required_aspects else 1.0

    def evaluate_all(
        self,
        result: EvaluationResult,
        prompt: str,
        expected_output: str | None = None,
        required_aspects: list[str] | None = None,
    ) -> dict[str, float]:
        """Evaluate all quality metrics.

        Args:
            result: Evaluation result.
            prompt: Original prompt.
            expected_output: Expected output.
            required_aspects: Required aspects to cover.

        Returns:
            Dictionary with quality scores.
        """
        return {
            "correctness": self.evaluate_correctness(result, expected_output),
            "relevance": self.evaluate_relevance(result, prompt),
            "completeness": self.evaluate_completeness(result, required_aspects),
        }

