"""ASV benchmarks for Action YAML schema validation throughput.

Measures the performance of:
- YAML string parsing + schema validation
- YAML file loading + schema validation
- Key normalization overhead
- Invariant normalization overhead
- model_dump() serialization
"""

from __future__ import annotations

import importlib
import os
import sys
import tempfile
from pathlib import Path

# Ensure the local *source* tree is importable even when ASV has an
# older build of the package installed that lacks the ``action`` sub-package.
_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
    sys.path.insert(0, _SRC)

# Force-reload the top-level package so Python picks up the source tree
# version (which contains the ``action`` sub-package) instead of the
# potentially stale installed copy.
import cleveragents  # noqa: E402

importlib.reload(cleveragents)

from cleveragents.action.schema import ActionConfigSchema  # noqa: E402

_MINIMAL_YAML = """\
name: local/bench-action
description: Benchmark action
strategy_actor: openai/gpt-4
execution_actor: openai/gpt-4
definition_of_done: Benchmarks pass
"""

_FULL_YAML = """\
schema_version: "1"
name: local/bench-full
description: Full benchmark action
long_description: |
  This is a detailed description for benchmarking
  with multiple lines of text.
strategy_actor: openai/gpt-4
execution_actor: openai/gpt-4
estimation_actor: local/estimator
review_actor: local/reviewer
apply_actor: local/applier
invariant_actor: local/invariant-resolver
definition_of_done: All benchmarks pass with zero errors
reusable: true
read_only: false
state: available
automation_profile: local/trusted
invariants:
  - "No secrets in code"
  - "All tests must pass"
  - "Coverage above 97%"
arguments:
  - name: target_coverage
    type: integer
    required: true
    description: Target coverage percentage
    min_value: 1
    max_value: 100
  - name: test_command
    type: string
    required: false
    description: Test framework command
    default: "pytest --cov"
"""

_CAMEL_CASE_YAML = """\
name: local/bench-camel
description: camelCase benchmark
strategyActor: openai/gpt-4
executionActor: openai/gpt-4
definitionOfDone: Benchmarks pass
"""


class ActionSchemaValidationSuite:
    """Benchmark ActionConfigSchema.from_yaml() throughput."""

    def time_validate_minimal(self) -> None:
        """Benchmark minimal YAML validation."""
        ActionConfigSchema.from_yaml(_MINIMAL_YAML)

    def time_validate_full(self) -> None:
        """Benchmark fully-populated YAML validation."""
        ActionConfigSchema.from_yaml(_FULL_YAML)

    def time_validate_camel_case_normalization(self) -> None:
        """Benchmark YAML with camelCase key normalization."""
        ActionConfigSchema.from_yaml(_CAMEL_CASE_YAML)


class ActionSchemaFileLoadSuite:
    """Benchmark ActionConfigSchema.from_yaml_file() throughput."""

    def setup(self) -> None:
        """Write a temporary YAML file for file-load benchmarks."""
        fd, self._path = tempfile.mkstemp(suffix=".yaml")
        with os.fdopen(fd, "w") as fh:
            fh.write(_FULL_YAML)

    def teardown(self) -> None:
        """Remove the temporary file."""
        Path(self._path).unlink(missing_ok=True)

    def time_load_from_file(self) -> None:
        """Benchmark loading and validating a YAML file."""
        ActionConfigSchema.from_yaml_file(self._path)


class ActionSchemaSerializationSuite:
    """Benchmark serialization of a validated ActionConfigSchema."""

    def setup(self) -> None:
        """Parse YAML once for serialization benchmarks."""
        self._config = ActionConfigSchema.from_yaml(_FULL_YAML)

    def time_model_dump(self) -> None:
        """Benchmark model_dump() serialization."""
        self._config.model_dump()

    def time_model_dump_json(self) -> None:
        """Benchmark model_dump_json() JSON serialization."""
        self._config.model_dump_json()
