"""JsonFormatCheck: Validate output is valid JSON."""

from __future__ import annotations

import json
from typing import Any

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


@register("json_format")
class JsonFormatCheck(BaseCheck):
    """Validate output is valid JSON.

    Requires:
        - ctx.output: JSON string or already parsed dict/list

    Example:
        check = JsonFormatCheck()
    """

    requires_llm = False
    version = "1.0.0"
    description = "Validate output is valid JSON"

    def __init__(self, threshold: float = 0.5, **kwargs: Any) -> None:
        """Initialize JsonFormatCheck.

        Args:
            threshold: Score threshold (0.0-1.0).
            **kwargs: Additional config kwargs.
        """
        super().__init__(threshold=threshold, **kwargs)

    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(
                "JsonFormatCheck requires ctx.output to be set.\n"
                'Example: Context(output=\'{"key": "value"}\')'
            )

    def evaluate(self, ctx: Context) -> CheckResult:
        """Evaluate if output is valid JSON.

        Args:
            ctx: Context with output to validate.

        Returns:
            CheckResult with pass/fail and evidence.
        """
        self.validate_context(ctx)

        # If output is already a dict/list, it's valid JSON
        if isinstance(ctx.output, (dict, list)):
            return CheckResult(
                name=self.name,
                passed=True,
                score=1.0,
                threshold=self.threshold,
                evidence="Output is valid JSON (dict/list)",
                check_version=self.version,
            )

        # If output is a string, try to parse it
        if isinstance(ctx.output, str):
            try:
                json.loads(ctx.output)
                return CheckResult(
                    name=self.name,
                    passed=True,
                    score=1.0,
                    threshold=self.threshold,
                    evidence="Output is valid JSON string",
                    check_version=self.version,
                )
            except json.JSONDecodeError as e:
                return CheckResult(
                    name=self.name,
                    passed=False,
                    score=0.0,
                    threshold=self.threshold,
                    evidence=f"Output is not valid JSON: {str(e)}",
                    check_version=self.version,
                )

        # Other types are not valid JSON
        return CheckResult(
            name=self.name,
            passed=False,
            score=0.0,
            threshold=self.threshold,
            evidence=f"Output type {type(ctx.output).__name__} is not valid JSON",
            check_version=self.version,
        )
