"""
Implementation of the ScorerData class.

ScorerData holds the information related to a single, completed Scorer evaluation run.
"""

from typing import List, Union, Optional, Dict
from pydantic import BaseModel

from judgeval.scorers import JudgevalScorer

class ScorerData(BaseModel):
    """
    ScorerData holds the information related to a single, completed Scorer evaluation run.

    For example, if running the Judgment Faithfulness scorer on an example, the ScorerData
    object will contain whether the example passed its threshold expectation, as well as more detailed
    information surrounding the evaluation run such as the claims and verdicts generated by the
    judge model(s).
    """
    name: str
    threshold: float
    success: bool
    score: Optional[float] = None
    reason: Optional[str] = None
    strict_mode: Optional[bool] = None
    evaluation_model: Union[List[str], str] = None
    error: Optional[str] = None
    evaluation_cost: Union[float, None] = None
    verbose_logs: Optional[str] = None
    additional_metadata: Optional[Dict] = None

    def to_dict(self) -> dict:
        """Convert the ScorerData instance to a JSON-serializable dictionary."""
        return {
            "name": self.name,
            "threshold": self.threshold,
            "success": self.success,
            "score": self.score,
            "reason": self.reason,
            "strict_mode": self.strict_mode,
            "evaluation_model": self.evaluation_model,
            "error": self.error,
            "evaluation_cost": self.evaluation_cost,
            "verbose_logs": self.verbose_logs,
            "additional_metadata": self.additional_metadata
        }


def create_scorer_data(scorer: JudgevalScorer) -> ScorerData:
    """
    After a `scorer` is run, it contains information about the example that was evaluated
    using the scorer. For example, after computing Faithfulness, the `scorer` object will contain
    whether the example passed its threshold, the score, the reason for score, etc.

    This function takes an executed `scorer` object and produces a ScorerData object that
    contains the output of the scorer run that can be exported to be logged as a part of
    the ScorerResult.
    """
    if scorer.error is not None:  # error occurred during eval run
        return ScorerData(
            name=scorer.__name__,
            threshold=scorer.threshold,
            score=None,
            reason=None,
            success=False,
            strict_mode=scorer.strict_mode,
            evaluation_model=scorer.evaluation_model,
            error=scorer.error,
            evaluation_cost=scorer.evaluation_cost,
            verbose_logs=scorer.verbose_logs,
        )
    else:  # standard execution, no error
        return ScorerData(
            name=scorer.__name__,
            score=scorer.score,
            threshold=scorer.threshold,
            reason=scorer.reason,
            success=scorer._success_check(),
            strict_mode=scorer.strict_mode,
            evaluation_model=scorer.evaluation_model,
            error=None,
            evaluation_cost=scorer.evaluation_cost,
            verbose_logs=scorer.verbose_logs,
            additional_metadata=scorer.additional_metadata,
        )
