"""Step definitions for container_id_flag.feature."""

from __future__ import annotations

from typing import Any

from behave import given, then, when
from behave.runner import Context
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from cleveragents.application.services.resource_registry_service import (
    ResourceRegistryService,
)
from cleveragents.domain.models.core.resource import PhysVirt, Resource
from cleveragents.infrastructure.database.models import Base
from cleveragents.resource.handlers.devcontainer import DevcontainerHandler


class _NoClose:
    """Proxy that suppresses ``close()`` on an in-memory SQLite session.

    Without this, SQLAlchemy's ``session.close()`` releases the
    connection, destroying the in-memory database between operations.
    """

    __slots__ = ("_s",)

    def __init__(self, s: object) -> None:
        object.__setattr__(self, "_s", s)

    def close(self) -> None:
        pass

    def __getattr__(self, n: str) -> object:
        return getattr(object.__getattribute__(self, "_s"), n)


@given("a resource registry service for container_id")
def step_setup_registry(context: Context) -> None:
    engine = create_engine("sqlite:///:memory:", echo=False)
    Base.metadata.create_all(engine)
    session = sessionmaker(bind=engine, expire_on_commit=False)()
    wrapper = _NoClose(session)
    svc = ResourceRegistryService(session_factory=lambda: wrapper)
    svc.bootstrap_builtin_types()
    context.ci_service = svc


@when('I add a container-instance with container-id "{cid}" for container_id')
def step_add_with_container_id(context: Context, cid: str) -> None:
    properties: dict[str, Any] = {"container_id": cid}
    res = context.ci_service.register_resource(
        type_name="container-instance",
        name="local/test-ctr-id",
        description="Test container with ID",
        properties=properties,
    )
    context.ci_resource = res


@when(
    'I validate container-instance with both container-id "{cid}" and image "{img}" for container_id'
)
def step_validate_both_flags(context: Context, cid: str, img: str) -> None:
    """Simulate the CLI validation that rejects --container-id + --image together."""
    error: str | None = None
    if cid is not None and img is not None:
        error = (
            "--container-id and --image are mutually exclusive; "
            "provide one or the other, not both."
        )
    context.ci_validation_error = error


@when(
    "I validate container-instance with neither container-id nor image for container_id"
)
def step_validate_neither_flag(context: Context) -> None:
    """Simulate the CLI validation that rejects container-instance with no image/id."""
    context.ci_validation_error = (
        "container-instance resources require either --image or --container-id."
    )


@when('I validate type "{type_name}" with container-id "{cid}" for container_id')
def step_validate_wrong_type(context: Context, type_name: str, cid: str) -> None:
    """Simulate the CLI validation that rejects --container-id on non-container types."""
    error: str | None = None
    if type_name != "container-instance":
        error = (
            f"--container-id is only valid for container-instance resources, "
            f"not '{type_name}'"
        )
    context.ci_validation_error = error


@given('a resource with container_id "{cid}" in properties for container_id')
def step_create_resource_with_container_id(context: Context, cid: str) -> None:
    """Create a minimal Resource domain object with container_id in properties."""
    context.ci_handler_resource = Resource(
        resource_id="01ARZ3NDEKTSV4RRFFQ69G5FAV",
        name="local/test-handler-ctr",
        resource_type_name="container-instance",
        classification=PhysVirt.PHYSICAL,
        properties={"container_id": cid},
    )


@when("I call _find_running_container for container_id")
def step_call_find_running_container(context: Context) -> None:
    """Call DevcontainerHandler._find_running_container with the test resource."""
    context.ci_handler_result = DevcontainerHandler._find_running_container(
        context.ci_handler_resource
    )


@then('the container_id resource should have container_id "{expected}"')
def step_check_container_id_stored(context: Context, expected: str) -> None:
    resource = context.ci_resource
    assert resource.properties.get("container_id") == expected, (
        f"Expected container_id '{expected}', "
        f"got: {resource.properties.get('container_id')!r}"
    )


@then('container_id validation should fail with "{message}"')
def step_validation_should_fail(context: Context, message: str) -> None:
    error = context.ci_validation_error
    assert error is not None, "Expected a validation error but none was set"
    assert message.lower() in error.lower(), (
        f"Expected '{message}' in validation error, got: {error!r}"
    )


@then('the container_id result should be "{expected}"')
def step_check_handler_result(context: Context, expected: str) -> None:
    result = context.ci_handler_result
    assert result == expected, (
        f"Expected _find_running_container to return '{expected}', got: {result!r}"
    )
