"""Step definitions for TDD issue #2588.

Verifies that ``agents resource stop`` accepts both ``container-instance``
and ``devcontainer-instance`` resource types, and still rejects other types.
"""

from __future__ import annotations

from unittest.mock import MagicMock, patch

from behave import given, then, when
from behave.runner import Context
from typer.testing import CliRunner

from cleveragents.cli.commands.resource import _STOPPABLE_TYPES
from cleveragents.cli.commands.resource import app as resource_app
from cleveragents.domain.models.core.container_lifecycle import (
    ContainerLifecycleState,
    ContainerLifecycleTracker,
)
from cleveragents.resource.handlers.devcontainer import set_lifecycle_tracker

_CLI_PATCH_SERVICE = "cleveragents.cli.commands.resource._get_registry_service"
_CLI_PATCH_STOP = "cleveragents.cli.commands.resource.stop_container"


def _make_mock_resource(
    *,
    resource_id: str,
    name: str,
    resource_type_name: str,
    location: str | None = None,
) -> MagicMock:
    res = MagicMock()
    res.resource_id = resource_id
    res.name = name
    res.resource_type_name = resource_type_name
    res.location = location
    res.properties = None
    return res


@given('a running container-instance resource "{name}" with id "{resource_id}"')
def step_running_container_instance(
    context: Context, name: str, resource_id: str
) -> None:
    """Set up a running container-instance resource for stop tests."""
    mock_service = MagicMock()
    mock_resource = _make_mock_resource(
        resource_id=resource_id,
        name=name,
        resource_type_name="container-instance",
        location="/workspace/project",
    )
    mock_service.show_resource.return_value = mock_resource
    context.tdd2588_mock_service = mock_service
    context.tdd2588_resource_id = resource_id
    # Set up lifecycle tracker in running state
    tracker = ContainerLifecycleTracker(
        resource_id=resource_id,
        current_state=ContainerLifecycleState.RUNNING,
        container_id="ctr-2588-ci",
        workspace_path="/workspace/project",
    )
    set_lifecycle_tracker(tracker)


@given('a running devcontainer-instance resource "{name}" with id "{resource_id}"')
def step_running_devcontainer_instance(
    context: Context, name: str, resource_id: str
) -> None:
    """Set up a running devcontainer-instance resource for stop tests."""
    mock_service = MagicMock()
    mock_resource = _make_mock_resource(
        resource_id=resource_id,
        name=name,
        resource_type_name="devcontainer-instance",
        location="/workspace/project",
    )
    mock_service.show_resource.return_value = mock_resource
    context.tdd2588_mock_service = mock_service
    context.tdd2588_resource_id = resource_id
    # Set up lifecycle tracker in running state
    tracker = ContainerLifecycleTracker(
        resource_id=resource_id,
        current_state=ContainerLifecycleState.RUNNING,
        container_id="ctr-2588-dc",
        workspace_path="/workspace/project",
    )
    set_lifecycle_tracker(tracker)


@given('a git-checkout resource "{name}" with id "{resource_id}"')
def step_git_checkout_resource(context: Context, name: str, resource_id: str) -> None:
    """Set up a git-checkout resource (non-stoppable) for stop tests."""
    mock_service = MagicMock()
    mock_resource = _make_mock_resource(
        resource_id=resource_id,
        name=name,
        resource_type_name="git-checkout",
    )
    mock_service.show_resource.return_value = mock_resource
    context.tdd2588_mock_service = mock_service
    context.tdd2588_resource_id = resource_id


@when('I invoke resource stop for "{name}" with --yes')
def step_invoke_resource_stop(context: Context, name: str) -> None:
    """Invoke the resource stop CLI command with --yes flag."""
    runner = CliRunner()
    mock_service = context.tdd2588_mock_service

    with (
        patch(_CLI_PATCH_SERVICE, return_value=mock_service),
        patch(_CLI_PATCH_STOP) as mock_stop,
    ):
        mock_stop.return_value = MagicMock()
        result = runner.invoke(resource_app, ["stop", name, "--yes"])

    context.tdd2588_result = result
    context.tdd2588_mock_stop = mock_stop


@when("I inspect the _STOPPABLE_TYPES constant")
def step_inspect_stoppable_types(context: Context) -> None:
    """Capture the _STOPPABLE_TYPES constant for inspection."""
    context.tdd2588_stoppable_types = _STOPPABLE_TYPES


@then("the stop exit code should be 0")
def step_stop_exit_code_zero(context: Context) -> None:
    result = context.tdd2588_result
    assert result.exit_code == 0, (
        f"Expected exit code 0, got {result.exit_code}. Output:\n{result.output}"
    )


@then("the stop exit code should be non-zero")
def step_stop_exit_code_nonzero(context: Context) -> None:
    result = context.tdd2588_result
    assert result.exit_code != 0, (
        f"Expected non-zero exit code, got {result.exit_code}. Output:\n{result.output}"
    )


@then('the stop output should contain "{text}"')
def step_stop_output_contains(context: Context, text: str) -> None:
    result = context.tdd2588_result
    assert text in result.output, f"Expected '{text}' in output, got:\n{result.output}"


@then('_STOPPABLE_TYPES should contain "{resource_type}"')
def step_stoppable_types_contains(context: Context, resource_type: str) -> None:
    stoppable = context.tdd2588_stoppable_types
    assert resource_type in stoppable, (
        f"Expected '{resource_type}' in _STOPPABLE_TYPES, got: {stoppable}"
    )


@then('_STOPPABLE_TYPES should not contain "{resource_type}"')
def step_stoppable_types_not_contains(context: Context, resource_type: str) -> None:
    stoppable = context.tdd2588_stoppable_types
    assert resource_type not in stoppable, (
        f"Expected '{resource_type}' NOT in _STOPPABLE_TYPES, got: {stoppable}"
    )
