"""
Convenience wrapper functions.

These functions provide a simple function-based API that wraps the Validator class.
For better performance and more control, prefer using the Validator class directly.

PRIMARY INTERFACE: Validator Class
==================================

For most use cases, use the Validator class directly:

    >>> from pycharter.runtime_validator import Validator
    >>> validator = Validator(contract_dir="data/contracts/user")
    >>> result = validator.validate({"name": "Alice", "age": 30})

These wrapper functions are provided for convenience when you need a quick
one-off validation without creating a Validator instance.
"""

from __future__ import annotations

from pathlib import Path
from typing import Any, Type

from pydantic import BaseModel

from pycharter.contract_parser import ContractMetadata
from pycharter.metadata_store import MetadataStoreClient
from pycharter.runtime_validator.validator_core import ValidationResult


def _create_validator_from_contract(
    contract: dict[str, Any] | ContractMetadata | str,
) -> Any:  # Returns Validator, but using Any to avoid circular import
    """
    Create a Validator instance from various contract formats.

    This helper function centralizes the logic for creating validators
    from different contract representations, reducing code duplication.

    Args:
        contract: Contract data (dict, ContractMetadata, contract file path, or contract directory)

    Returns:
        Validator instance

    Raises:
        ValueError: If contract type is invalid
    """
    # Lazy import to avoid circular dependency
    from pycharter.runtime_validator.validator import Validator

    if isinstance(contract, str):
        path = Path(contract)
        if path.is_dir():
            return Validator(contract_dir=str(contract))
        else:
            return Validator(contract_file=str(contract))
    elif isinstance(contract, dict):
        return Validator(contract_dict=contract)
    elif isinstance(contract, ContractMetadata):
        return Validator(contract_metadata=contract)
    else:
        raise ValueError(
            f"Invalid contract type: {type(contract)}. "
            f"Expected dict, ContractMetadata, or str (file/dir path)"
        )


def validate_with_store(
    store: MetadataStoreClient,
    contract_name: str,
    contract_version: str,
    data: dict[str, Any],
    strict: bool = False,
) -> ValidationResult:
    """
    Validate data using contract from store by name and version.

    Args:
        store: MetadataStoreClient instance
        contract_name: Data contract name
        contract_version: Data contract version
        data: Data dictionary to validate
        strict: If True, raise exceptions on validation errors

    Returns:
        ValidationResult object
    """
    from pycharter.runtime_validator.validator import Validator

    validator = Validator(
        store=store, contract_name=contract_name, contract_version=contract_version
    )
    return validator.validate(data, strict=strict)


def validate_batch_with_store(
    store: MetadataStoreClient,
    contract_name: str,
    contract_version: str,
    data_list: list[dict[str, Any]],
    strict: bool = False,
) -> list[ValidationResult]:
    """
    Validate a batch of data using contract from store by name and version.
    """
    from pycharter.runtime_validator.validator import Validator

    validator = Validator(
        store=store, contract_name=contract_name, contract_version=contract_version
    )
    return validator.validate_batch(data_list, strict=strict)


def get_model_from_store(
    store: MetadataStoreClient,
    contract_name: str,
    contract_version: str,
    model_name: str | None = None,
) -> Type[BaseModel]:
    """
    Generate a Pydantic model from a contract in the metadata store by name and version.
    """
    from pycharter.runtime_validator.validator import Validator

    validator = Validator(
        store=store, contract_name=contract_name, contract_version=contract_version
    )
    return validator.get_model()


def get_model_from_contract(
    contract: dict[str, Any] | ContractMetadata | str | None,
    model_name: str = None,
) -> Type[BaseModel]:
    """
    Generate a Pydantic model from a data contract (uses Validator internally).

    Args:
        contract: Contract data (dict, ContractMetadata, contract file path, or contract directory)
        model_name: Optional model name (ignored, kept for compatibility)

    Returns:
        Pydantic model class
    """
    validator = _create_validator_from_contract(contract)
    return validator.get_model()


def validate_with_contract(
    contract: dict[str, Any] | ContractMetadata | str | None,
    data: dict[str, Any],
    model_name: str = None,
    strict: bool = False,
) -> ValidationResult:
    """
    Validate data against a data contract (uses Validator internally).

    Args:
        contract: Contract data (dict, ContractMetadata, contract file path, or contract directory)
        data: Data dictionary to validate
        model_name: Optional model name (ignored, kept for compatibility)
        strict: If True, raise exceptions on validation errors

    Returns:
        ValidationResult object
    """
    validator = _create_validator_from_contract(contract)
    return validator.validate(data, strict=strict)


def validate_batch_with_contract(
    contract: dict[str, Any] | ContractMetadata | str | None,
    data_list: list[dict[str, Any]],
    model_name: str | None = None,
    strict: bool = False,
) -> list[ValidationResult]:
    """
    Validate a batch of data against a data contract (uses Validator internally).

    Args:
        contract: Contract data (dict, ContractMetadata, contract file path, or contract directory)
        data_list: List of data dictionaries to validate
        model_name: Optional model name (ignored, kept for compatibility)
        strict: If True, stop on first validation error

    Returns:
        List of ValidationResult objects
    """
    validator = _create_validator_from_contract(contract)
    return validator.validate_batch(data_list, strict=strict)
