"""ASV benchmarks for Action CLI command throughput.

Measures the performance of:
- Config-only create (YAML load + validate + Action.from_config)
- List command rendering
- Show command rendering
- Archive command rendering
"""

from __future__ import annotations

import importlib
import os
import sys
import tempfile
from datetime import datetime
from pathlib import Path
from unittest.mock import MagicMock, patch

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

import cleveragents  # noqa: E402

importlib.reload(cleveragents)

from typer.testing import CliRunner  # noqa: E402

from cleveragents.cli.commands.action import app as action_app  # noqa: E402
from cleveragents.domain.models.core.action import Action, ActionState  # noqa: E402
from cleveragents.domain.models.core.plan import NamespacedName  # noqa: E402

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

_runner = CliRunner()


def _mock_action(name: str = "local/bench-action") -> Action:
    return Action(
        namespaced_name=NamespacedName.parse(name),
        description="Benchmark action",
        definition_of_done="Benchmarks pass",
        strategy_actor="openai/gpt-4",
        execution_actor="openai/gpt-4",
        state=ActionState.AVAILABLE,
        created_at=datetime.now(),
        updated_at=datetime.now(),
    )


class ActionCLICreateSuite:
    """Benchmark action create --config throughput."""

    def setup(self) -> None:
        """Write a temporary YAML file and set up mock service."""
        fd, self._path = tempfile.mkstemp(suffix=".yaml")
        with os.fdopen(fd, "w") as fh:
            fh.write(_VALID_YAML)
        self._mock_service = MagicMock()
        self._mock_service.create_action.return_value = _mock_action()
        self._patcher = patch(
            "cleveragents.cli.commands.action._get_lifecycle_service",
            return_value=self._mock_service,
        )
        self._patcher.start()

    def teardown(self) -> None:
        """Clean up."""
        self._patcher.stop()
        Path(self._path).unlink(missing_ok=True)

    def time_create_from_config(self) -> None:
        """Benchmark create --config end-to-end."""
        _runner.invoke(action_app, ["create", "--config", self._path])


class ActionCLIListSuite:
    """Benchmark action list throughput."""

    def setup(self) -> None:
        """Set up mock service with actions."""
        self._mock_service = MagicMock()
        self._mock_service.list_actions.return_value = [
            _mock_action(f"local/action-{i}") for i in range(50)
        ]
        self._patcher = patch(
            "cleveragents.cli.commands.action._get_lifecycle_service",
            return_value=self._mock_service,
        )
        self._patcher.start()

    def teardown(self) -> None:
        self._patcher.stop()

    def time_list_all(self) -> None:
        """Benchmark listing all actions."""
        _runner.invoke(action_app, ["list"])

    def time_list_with_namespace(self) -> None:
        """Benchmark listing with namespace filter."""
        _runner.invoke(action_app, ["list", "--namespace", "local"])

    def time_list_with_state(self) -> None:
        """Benchmark listing with state filter."""
        _runner.invoke(action_app, ["list", "--state", "available"])


class ActionCLIShowSuite:
    """Benchmark action show throughput."""

    def setup(self) -> None:
        self._mock_service = MagicMock()
        self._mock_service.get_action_by_name.return_value = _mock_action()
        self._patcher = patch(
            "cleveragents.cli.commands.action._get_lifecycle_service",
            return_value=self._mock_service,
        )
        self._patcher.start()

    def teardown(self) -> None:
        self._patcher.stop()

    def time_show(self) -> None:
        """Benchmark showing an action."""
        _runner.invoke(action_app, ["show", "local/bench-action"])
