"""Utility functions for validating Vega-Lite charts."""

import json
from pathlib import Path
from typing import Any, Optional

import jsonschema
from jsonschema import ValidationError

# Path to local Vega-Lite v5 schema file
VEGA_LITE_SCHEMA_V5 = Path(__file__).parent / "vega-lite-schema-v5.json"

# Cache for the schema to avoid repeated file reads
_schema_cache: dict[Path, Any] = {}


def _fetch_schema(schema_path: Path | str = VEGA_LITE_SCHEMA_V5) -> dict[str, Any]:
    """Load the Vega-Lite schema from local file or cache.

    Args:
        schema_path: Path to the Vega-Lite JSON schema file

    Returns:
        The JSON schema as a dictionary
    """
    # Convert to Path if string
    if isinstance(schema_path, str):
        schema_path = Path(schema_path)

    if schema_path in _schema_cache:
        return _schema_cache[schema_path]

    try:
        with open(schema_path, "r", encoding="utf-8") as f:
            schema = json.load(f)
            _schema_cache[schema_path] = schema
            return schema
    except Exception as e:
        raise RuntimeError(f"Failed to load Vega-Lite schema from {schema_path}: {e}")


def normalize_chart_spec(content: Any) -> dict:
    """Parse Vega-Lite chart JSON response from LLM, handling both dict and string formats.

    Args:
        content: The LLM response content (could be dict, str, or other types)

    Returns:
        Parsed dictionary if successful, empty dict otherwise

    Example:
        >>> normalize_chart_spec('{"$schema": "https://vega.github.io/schema/vega-lite/v5.json"}')
        {'$schema': 'https://vega.github.io/schema/vega-lite/v5.json'}
        >>> normalize_chart_spec({"mark": "bar"})
        {'mark': 'bar'}
        >>> normalize_chart_spec("invalid json")
        {}
    """
    if isinstance(content, dict):
        chart_schema = content
    elif isinstance(content, str):
        try:
            chart_schema = json.loads(content)
        except json.JSONDecodeError:
            return {}
    else:
        return {}

    chart_schema["data"] = {"values": []}
    return chart_schema


def validate_chart(
    chart: dict, schema_url: Path | str = VEGA_LITE_SCHEMA_V5
) -> tuple[bool, Optional[str]]:
    """Validate a Vega-Lite chart specification against the JSON schema.

    Args:
        chart: The Vega-Lite chart specification as a dictionary
        schema_url: URL to the Vega-Lite JSON schema (default: v5)

    Returns:
        A tuple of (ok, err) where:
        - ok: True if the chart is valid, False otherwise
        - err: None if valid, the exception if invalid

    Example:
        >>> chart_spec = {
        ...     "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
        ...     "data": {"values": [{"a": "A", "b": 28}]},
        ...     "mark": "bar",
        ...     "encoding": {
        ...         "x": {"field": "a", "type": "nominal"},
        ...         "y": {"field": "b", "type": "quantitative"}
        ...     }
        ... }
        >>> ok, err = validate_chart(chart_spec)
        >>> ok
        True
        >>> err is None
        True
    """

    # Fetch the schema
    schema = _fetch_schema(schema_url)

    # Validate the chart against the schema
    try:
        jsonschema.validate(instance=chart, schema=schema)
        return True, None
    except ValidationError as e:
        return False, str(e)
