"""Tool usage evaluator."""

from __future__ import annotations

from typing import Any

from pydantic_ai_toolsets.evals.base import EvaluationResult


class ToolUsageEvaluator:
    """Evaluates tool usage patterns and correctness."""

    def evaluate_tool_calls_present(self, result: EvaluationResult) -> float:
        """Check if tools were called at all.

        Args:
            result: Evaluation result.

        Returns:
            1.0 if tools were called, 0.0 otherwise.
        """
        if result.error:
            return 0.0

        return 1.0 if result.tool_calls else 0.0

    def evaluate_tool_sequence(
        self, result: EvaluationResult, expected_sequence: list[str] | None = None
    ) -> float:
        """Evaluate if tool calls follow expected sequence.

        Args:
            result: Evaluation result.
            expected_sequence: Expected sequence of tool names.

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

        if not expected_sequence:
            # If no expected sequence, just check that tools were called
            return 1.0 if result.tool_calls else 0.0

        actual_sequence = [call["name"] for call in result.tool_calls]

        # Check if expected sequence is a subsequence of actual sequence
        expected_idx = 0
        for tool_name in actual_sequence:
            if expected_idx < len(expected_sequence):
                if tool_name == expected_sequence[expected_idx]:
                    expected_idx += 1

        return expected_idx / len(expected_sequence) if expected_sequence else 1.0

    def evaluate_tool_diversity(self, result: EvaluationResult) -> float:
        """Evaluate diversity of tools used.

        Args:
            result: Evaluation result.

        Returns:
            Score based on number of unique tools used.
        """
        if result.error or not result.tool_calls:
            return 0.0

        unique_tools = set(call["name"] for call in result.tool_calls)
        total_calls = len(result.tool_calls)

        if total_calls == 0:
            return 0.0

        # Score based on diversity (more unique tools = better, up to a point)
        diversity_ratio = len(unique_tools) / total_calls
        return min(diversity_ratio, 1.0)

    def evaluate_tool_appropriateness(
        self, result: EvaluationResult, required_tools: list[str] | None = None
    ) -> float:
        """Evaluate if appropriate tools were used.

        Args:
            result: Evaluation result.
            required_tools: List of tools that should be called.

        Returns:
            Score from 0.0 to 1.0.
        """
        if result.error or not result.tool_calls:
            return 0.0 if required_tools else 1.0

        if not required_tools:
            return 1.0

        called_tools = set(call["name"] for call in result.tool_calls)
        required_set = set(required_tools)

        # Check if all required tools were called
        if required_set.issubset(called_tools):
            return 1.0

        # Partial credit for some required tools
        overlap = len(required_set & called_tools)
        return overlap / len(required_set) if required_set else 1.0

    def evaluate_all(
        self,
        result: EvaluationResult,
        expected_sequence: list[str] | None = None,
        required_tools: list[str] | None = None,
    ) -> dict[str, float]:
        """Evaluate all tool usage metrics.

        Args:
            result: Evaluation result.
            expected_sequence: Expected tool call sequence.
            required_tools: Required tools to call.

        Returns:
            Dictionary with tool usage scores.
        """
        return {
            "tools_called": self.evaluate_tool_calls_present(result),
            "sequence_correctness": self.evaluate_tool_sequence(
                result, expected_sequence
            ),
            "tool_diversity": self.evaluate_tool_diversity(result),
            "tool_appropriateness": self.evaluate_tool_appropriateness(
                result, required_tools
            ),
        }

