"""Context dataclass for check validation."""

from __future__ import annotations

from typing import Any

from pydantic import BaseModel, field_validator


class Context(BaseModel):
    """Immutable container holding everything a check needs to evaluate.

    Attributes:
        input: The prompt/query sent to the AI system.
        output: The AI system's response (the thing being validated).
        ground_truth: Expected/correct answer for comparison.
        context: Retrieved chunks (RAG context).
        tool_calls: Agent tool invocations.
        conversation: Multi-turn conversation history.
        metadata: Arbitrary metadata (model name, temperature, etc.).
    """

    model_config = {"frozen": True}

    input: str | dict[str, Any] | list[Any] | None = None
    output: str | dict[str, Any] | list[Any]
    ground_truth: str | dict[str, Any] | list[Any] | None = None
    context: list[str] | None = None
    tool_calls: list[dict[str, Any]] | None = None
    conversation: list[dict[str, Any]] | None = None
    metadata: dict[str, Any] = {}

    @field_validator("output", mode="before")
    @classmethod
    def output_not_none(cls, v: Any) -> Any:
        """Validate that output is not None."""
        if v is None:
            raise ValueError("output is required and cannot be None")
        return v

    @field_validator("conversation", mode="before")
    @classmethod
    def validate_conversation(cls, v: Any) -> Any:
        """Validate conversation format: each item must have role and content."""
        if v is None:
            return None
        if not isinstance(v, list):
            raise ValueError("conversation must be a list")
        for item in v:
            if not isinstance(item, dict):
                raise ValueError(
                    "Each conversation item must be a dict"
                )
            if "role" not in item or "content" not in item:
                raise ValueError(
                    "Each conversation item must have 'role' and 'content' keys"
                )
        return v

    @field_validator("tool_calls", mode="before")
    @classmethod
    def validate_tool_calls(cls, v: Any) -> Any:
        """Validate tool_calls format: each item must have name key."""
        if v is None:
            return None
        if not isinstance(v, list):
            raise ValueError("tool_calls must be a list")
        for item in v:
            if not isinstance(item, dict):
                raise ValueError("Each tool call must be a dict")
            if "name" not in item:
                raise ValueError("Each tool call must have a 'name' key")
        return v

    @field_validator("metadata", mode="before")
    @classmethod
    def validate_metadata_serializable(cls, v: Any) -> Any:
        """Validate that metadata is JSON-serializable."""
        if v is None:
            return {}
        if not isinstance(v, dict):
            raise ValueError("metadata must be a dict")
        # Test JSON serializability
        import json

        try:
            json.dumps(v)
        except (TypeError, ValueError) as e:
            raise ValueError(
                f"metadata must be JSON-serializable: {e}"
            ) from e
        return v

    def __repr__(self) -> str:
        """Return truncated repr."""
        fields = {}
        for key, value in self.model_dump().items():
            if isinstance(value, str) and len(value) > 100:
                fields[key] = value[:100] + "..."
            else:
                fields[key] = value
        return f"Context({fields})"
