# pyright: reportRedeclaration=false
"""Step definitions for actor CLI exception handling contract tests."""

from __future__ import annotations

import tempfile
from pathlib import Path
from typing import Any
from unittest.mock import MagicMock, patch

from behave import given, then, when
from sqlalchemy.exc import OperationalError

from cleveragents.cli.commands.actor import _compute_actor_impact
from cleveragents.core.exceptions import CleverAgentsError, ValidationError


def _register_cleanup_exc(context: Any, path: Path) -> None:
    if not hasattr(context, "_cleanup_handlers"):
        context._cleanup_handlers = []
    context._cleanup_handlers.append(lambda: path.unlink(missing_ok=True))


@given("I have a malformed YAML actor config file")
def step_given_malformed_yaml_config(context: Any) -> None:
    # Write a file that is valid text but invalid YAML (bad indentation with tabs)
    content = "provider: openai\n  model: bad-indent\n\t  broken: true\n"
    with tempfile.NamedTemporaryFile(
        delete=False, suffix=".yaml", mode="w", encoding="utf-8"
    ) as handle:
        handle.write(content)
        handle.flush()
    context.actor_config_path = Path(handle.name)
    context.actor_config_data = {}
    _register_cleanup_exc(context, context.actor_config_path)
    context.expected_error = "Failed to parse config"


@when(
    "I call _compute_actor_impact with a session service that raises CleverAgentsError"
)
def step_when_compute_impact_clever_agents_error(context: Any) -> None:
    mock_container = MagicMock()
    mock_container.session_service.side_effect = CleverAgentsError("DB unavailable")
    with patch(
        "cleveragents.cli.commands.actor.get_container",
        return_value=mock_container,
    ):
        context.impact_result = _compute_actor_impact("local/test-actor")


@when(
    "I call _compute_actor_impact with a session service that raises OperationalError"
)
def step_when_compute_impact_operational_error(context: Any) -> None:
    mock_container = MagicMock()
    mock_container.session_service.side_effect = OperationalError(
        "connection refused", params=None, orig=None
    )
    with patch(
        "cleveragents.cli.commands.actor.get_container",
        return_value=mock_container,
    ):
        context.impact_result = _compute_actor_impact("local/test-actor")


@when("I call _compute_actor_impact with a session service that raises ValidationError")
def step_when_compute_impact_validation_error(context: Any) -> None:
    mock_container = MagicMock()
    mock_container.session_service.side_effect = ValidationError("invalid state")
    with patch(
        "cleveragents.cli.commands.actor.get_container",
        return_value=mock_container,
    ):
        context.impact_result = _compute_actor_impact("local/test-actor")


@then("the impact result should be zero counts")
def step_then_impact_result_zero(context: Any) -> None:
    result = context.impact_result
    assert result == (0, 0, 0), (
        f"Expected (0, 0, 0) but got {result}. "
        "The defensive exception handler should return zero counts when DB is unavailable."
    )
