"""FactualityCheck: Validate factuality of AI-generated output."""

from __future__ import annotations

from ai_qa.checks.registry import register
from ai_qa.core.check import BaseCheck
from ai_qa.core.context import Context
from ai_qa.core.result import CheckResult
from ai_qa.exceptions import ContextValidationError
from ai_qa.providers import get_provider

JUDGE_PROMPT = """You are an expert fact-checker. Your job is to evaluate the
factuality of claims made in AI-generated output.

Compare the output against:
1. The provided context (if available)
2. Common knowledge
3. The input prompt

Determine how factually accurate the output is. Consider:
- Are the main claims supported by evidence?
- Are any claims contradicted by the context?
- Are there verifiable inaccuracies?

Respond with a JSON object:
{
  "score": <float 0.0-1.0, where 1.0 means entirely factually accurate>,
  "evidence": "<explanation of factual issues found, if any>"
}
"""


@register("factuality")
class FactualityCheck(BaseCheck):
    """Validate factuality of AI-generated output.

    Requires:
        - ctx.output: The AI-generated text to check
        - ctx.ground_truth: The correct/expected answer (optional but recommended)
        - ctx.context: Retrieved context for fact validation (optional)

    Evaluates whether claims made in the output are factually accurate.

    Example:
        check = FactualityCheck(threshold=0.8)
    """

    requires_llm = True
    version = "1.0.0"
    description = "Validate factuality of AI-generated output"

    def validate_context(self, ctx: Context) -> None:
        """Validate that output exists.

        Args:
            ctx: Context to validate.

        Raises:
            ContextValidationError: If output is missing.
        """
        if ctx.output is None:
            raise ContextValidationError(
                "FactualityCheck requires ctx.output to be set.\n"
                "Example: Context(output='The answer', "
                "ground_truth='Expected answer')"
            )

    def evaluate(self, ctx: Context) -> CheckResult:
        """Evaluate output for factuality using LLM.

        Args:
            ctx: Context with output to validate.

        Returns:
            CheckResult with factuality score and evidence.
        """
        self.validate_context(ctx)

        provider = get_provider()

        # Build context string
        context_str = ""
        if ctx.context:
            context_str = "\n".join(f"- {c}" for c in ctx.context)

        ground_truth_str = ""
        if ctx.ground_truth:
            ground_truth_str = f"\nGROUND TRUTH:\n{ctx.ground_truth}"

        prompt = f"""OUTPUT:
{ctx.output}

CONTEXT:
{context_str or 'None provided'}{ground_truth_str}

Evaluate the factuality of the output. Consider whether the claims are accurate and
supported by the context and/or ground truth."""

        resp = provider.judge(system=JUDGE_PROMPT, user=prompt)

        return CheckResult(
            name=self.name,
            score=resp.get("score", 0.5),
            passed=resp.get("score", 0.5) >= self.threshold,
            threshold=self.threshold,
            evidence=resp.get("evidence", ""),
            cost_usd=resp.get("cost_usd", 0.0),
            tokens_used=resp.get("tokens", {}),
            check_version=self.version,
        )
