"""ASV benchmarks for action_arguments table ORM round-trip performance.

Measures the performance of:
- ActionArgument construction and serialization for ORM child rows
- Bulk argument serialization for actions with many arguments
- ActionArgumentModel construction patterns
"""

from __future__ import annotations

import json
import sys
from pathlib import Path

try:
    from cleveragents.domain.models.core.action import (
        Action,
        ActionArgument,
        ArgumentRequirement,
        ArgumentType,
    )
    from cleveragents.domain.models.core.plan import NamespacedName
    from cleveragents.infrastructure.database.models import (
        ActionArgumentModel,
        LifecycleActionModel,
    )
except ModuleNotFoundError:
    sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
    from cleveragents.domain.models.core.action import (
        Action,
        ActionArgument,
        ArgumentRequirement,
        ArgumentType,
    )
    from cleveragents.domain.models.core.plan import NamespacedName
    from cleveragents.infrastructure.database.models import (
        ActionArgumentModel,
        LifecycleActionModel,
    )


def _make_argument(name: str, idx: int) -> ActionArgument:
    """Create a typed argument cycling through types by index."""
    types = list(ArgumentType)
    arg_type = types[idx % len(types)]
    return ActionArgument(
        name=name,
        arg_type=arg_type,
        requirement=ArgumentRequirement.REQUIRED
        if idx % 2 == 0
        else ArgumentRequirement.OPTIONAL,
        description=f"Argument {name} for benchmarking",
        default_value="default" if idx % 2 == 1 else None,
        min_value=0 if arg_type == ArgumentType.INTEGER else None,
        max_value=100 if arg_type == ArgumentType.INTEGER else None,
        validation_pattern=r"^[a-z]+$" if arg_type == ArgumentType.STRING else None,
    )


def _make_action_with_n_args(n: int) -> Action:
    """Create an action with N arguments."""
    return Action(
        namespaced_name=NamespacedName(
            server=None, namespace="local", name=f"multi-arg-{n}"
        ),
        description=f"Action with {n} arguments",
        definition_of_done="All args validated",
        strategy_actor="openai/gpt-4",
        execution_actor="openai/gpt-4",
        arguments=[_make_argument(f"arg_{i}", i) for i in range(n)],
    )


class ArgumentModelConstructionSuite:
    """Benchmark ActionArgumentModel construction patterns."""

    def setup(self) -> None:
        self.args = [_make_argument(f"arg_{i}", i) for i in range(20)]

    def time_construct_single_model(self) -> None:
        """Construct a single ActionArgumentModel from values."""
        arg = self.args[0]
        ActionArgumentModel(
            action_name="local/bench-action",
            name=arg.name,
            arg_type=arg.arg_type.value,
            requirement=arg.requirement.value,
            description=arg.description,
            default_value_json=json.dumps(arg.default_value)
            if arg.default_value is not None
            else None,
            min_value=arg.min_value,
            max_value=arg.max_value,
            validation_pattern=arg.validation_pattern,
            position=0,
        )

    def time_construct_20_models(self) -> None:
        """Construct 20 ActionArgumentModel instances."""
        for i, arg in enumerate(self.args):
            ActionArgumentModel(
                action_name="local/bench-action",
                name=arg.name,
                arg_type=arg.arg_type.value,
                requirement=arg.requirement.value,
                description=arg.description,
                default_value_json=json.dumps(arg.default_value)
                if arg.default_value is not None
                else None,
                min_value=arg.min_value,
                max_value=arg.max_value,
                validation_pattern=arg.validation_pattern,
                position=i,
            )


class ArgumentRoundTripSuite:
    """Benchmark action ORM round-trip with varying argument counts."""

    def setup(self) -> None:
        self.action_2_args = _make_action_with_n_args(2)
        self.action_10_args = _make_action_with_n_args(10)
        self.action_20_args = _make_action_with_n_args(20)

    def time_round_trip_2_args(self) -> None:
        """Round-trip an action with 2 arguments through ORM."""
        model = LifecycleActionModel.from_domain(self.action_2_args)
        model.to_domain()

    def time_round_trip_10_args(self) -> None:
        """Round-trip an action with 10 arguments through ORM."""
        model = LifecycleActionModel.from_domain(self.action_10_args)
        model.to_domain()

    def time_round_trip_20_args(self) -> None:
        """Round-trip an action with 20 arguments through ORM."""
        model = LifecycleActionModel.from_domain(self.action_20_args)
        model.to_domain()


class ArgumentSerializationSuite:
    """Benchmark JSON serialization of argument default values."""

    def setup(self) -> None:
        self.string_val = "default-string-value"
        self.int_val = 42
        self.float_val = 3.14159
        self.bool_val = True
        self.list_val = ["alpha", "beta", "gamma", "delta"]

    def time_serialize_string(self) -> None:
        """Serialize a string default value to JSON."""
        json.dumps(self.string_val)

    def time_serialize_integer(self) -> None:
        """Serialize an integer default value to JSON."""
        json.dumps(self.int_val)

    def time_serialize_list(self) -> None:
        """Serialize a list default value to JSON."""
        json.dumps(self.list_val)

    def time_deserialize_string(self) -> None:
        """Deserialize a JSON string default value."""
        json.loads('"default-string-value"')

    def time_deserialize_list(self) -> None:
        """Deserialize a JSON list default value."""
        json.loads('["alpha", "beta", "gamma", "delta"]')
