"""AI-QA-SDK: Universal AI validation SDK.

Validate LLM outputs, RAG pipelines, and agent workflows with a single function call.
"""

from __future__ import annotations

from typing import Any

from ai_qa._version import __version__
from ai_qa.cache import Cache
from ai_qa.checks import CheckRegistry, get_check, list_checks, register
from ai_qa.core.check import BaseCheck
from ai_qa.core.config import configure, get_config
from ai_qa.core.context import Context
from ai_qa.core.result import CheckResult, ValidationResult
from ai_qa.core.runner import Runner
from ai_qa.mcp import MCPToolCall, MCPTrace, MCPWorkflow


def validate(
    output: str | dict[str, Any] | list[Any],
    checks: list[str | dict[str, Any]],
    input: str | dict[str, Any] | None = None,
    ground_truth: str | dict[str, 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] | None = None,
    threshold: float | None = None,
    parallelism: int | None = None,
    cache: bool | None = None,
) -> ValidationResult:
    """Validate AI outputs against a suite of checks.

    The primary entry point for the ai-qa-sdk. Validates LLM outputs,
    RAG pipelines, and agent workflows with a single function call.

    Args:
        output: The AI system's response (required).
        checks: List of check names or {name: ..., **kwargs} dicts.
        input: The original prompt/query (optional).
        ground_truth: Expected/correct answer for comparison (optional).
        context: Retrieved chunks for RAG validation (optional).
        tool_calls: Agent tool invocations (optional).
        conversation: Multi-turn conversation history (optional).
        metadata: Arbitrary metadata (model name, temperature, etc.).
        threshold: Override default threshold for all checks (optional).
        parallelism: Override default parallelism for LLM checks (optional).
        cache: Enable/disable caching for LLM check results (optional).

    Returns:
        ValidationResult with all check outcomes and summary statistics.

    Examples:
        >>> from ai_qa import validate
        >>> result = validate(
        ...     output="The capital of France is Paris",
        ...     checks=["factuality"],
        ... )
        >>> print(result.summary())

        >>> result = validate(
        ...     output="Paris is in France",
        ...     checks=[
        ...         "factuality",
        ...         "relevance",
        ...         {"name": "custom", "criteria": "mentions a city"},
        ...     ],
        ...     input="Where is Paris?",
        ...     ground_truth="Paris is the capital of France",
        ... )
        >>> result.assert_passed()  # Raise if any check failed
    """
    # Build context
    ctx = Context(
        input=input,
        output=output,
        ground_truth=ground_truth,
        context=context,
        tool_calls=tool_calls,
        conversation=conversation,
        metadata=metadata or {},
    )

    # Resolve checks to instances
    check_instances: list[BaseCheck] = []
    for check_spec in checks:
        if isinstance(check_spec, str):
            # Just a name: get_check("pii")
            check_instances.append(get_check(check_spec))
        elif isinstance(check_spec, dict):
            # Dict with name and kwargs: {"name": "custom", "criteria": "..."}
            check_dict = check_spec.copy()
            name = check_dict.pop("name")
            check_instances.append(get_check(name, **check_dict))
        else:
            msg = f"Invalid check spec: {check_spec}"
            raise TypeError(msg)

    # Override thresholds if provided
    if threshold is not None:
        for check in check_instances:
            check.threshold = threshold

    # Create runner
    runner_cache = None
    if cache is True:
        runner_cache = Cache()
    elif cache is False:
        runner_cache = None
    # If None, let Runner use config

    runner = Runner(parallelism=parallelism, cache=runner_cache)

    # Run checks
    return runner.run(ctx, check_instances)


__all__ = [
    "__version__",
    # Main API
    "validate",
    # Core classes
    "Context",
    "CheckResult",
    "ValidationResult",
    "BaseCheck",
    # Configuration
    "configure",
    "get_config",
    # Registry
    "register",
    "get_check",
    "list_checks",
    "CheckRegistry",
    # Runner & Cache
    "Runner",
    "Cache",
    # MCP
    "MCPToolCall",
    "MCPTrace",
    "MCPWorkflow",
]
