"""Step definitions for ResourceHandler protocol coverage.

Targets uncovered lines in src/cleveragents/resource/handlers/protocol.py:
- Line 76:  Content.text raises ValueError for binary (encoding=None)
- Line 236: ResourceHandler.resolve default stub
- Line 254: ResourceHandler.read default stub
- Line 271: ResourceHandler.write default stub
- Line 288: ResourceHandler.delete default stub
- Line 299: ResourceHandler.list_children default stub
- Line 311: ResourceHandler.diff default stub
- Line 315: ResourceHandler.discover_children default stub
- Line 327: ResourceHandler.create_sandbox default stub
- Line 338: ResourceHandler.create_checkpoint default stub
- Line 349: ResourceHandler.rollback_to default stub
- Line 360: ResourceHandler.project_access default stub

All steps use the ``phcov`` prefix to avoid collisions with other step files.
"""

from __future__ import annotations

from unittest.mock import MagicMock

from behave import given, then, when
from behave.runner import Context

from cleveragents.domain.models.core.resource import PhysVirt, Resource
from cleveragents.resource.handlers.protocol import Content, ResourceHandler

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

# A valid ULID for constructing Resource instances.
_DUMMY_ULID = "01ARZ3NDEKTSV4RRFFQ69G5FAV"


class _BareResourceHandler(ResourceHandler):
    """Minimal subclass that inherits all Protocol default stubs.

    Does NOT override any methods, so calling them executes the ``...``
    body in the Protocol and returns ``None``.
    """

    pass


def _make_dummy_resource() -> Resource:
    """Create a minimal valid Resource for test use."""
    return Resource(
        resource_id=_DUMMY_ULID,
        resource_type_name="test-type",
        classification=PhysVirt.PHYSICAL,
        location="/tmp/test",
    )


def _make_mock_sandbox_manager() -> MagicMock:
    """Create a MagicMock standing in for SandboxManager."""
    return MagicMock(name="SandboxManager")


# ---------------------------------------------------------------------------
# Given steps
# ---------------------------------------------------------------------------


@given("phcov a Content instance with binary data and encoding None")
def step_given_phcov_binary_content(context: Context) -> None:
    context.phcov_content = Content(data=b"\x89PNG\r\n", encoding=None)
    context.phcov_error = None


@given("phcov a bare ResourceHandler protocol subclass instance")
def step_given_phcov_bare_handler(context: Context) -> None:
    context.phcov_handler = _BareResourceHandler()
    context.phcov_result = None
    context.phcov_error = None


@given("phcov a dummy Resource and SandboxManager")
def step_given_phcov_dummy_resource_and_manager(context: Context) -> None:
    context.phcov_resource = _make_dummy_resource()
    context.phcov_sandbox_manager = _make_mock_sandbox_manager()


# ---------------------------------------------------------------------------
# When steps
# ---------------------------------------------------------------------------


@when("phcov the text property is accessed")
def step_when_phcov_text_property(context: Context) -> None:
    try:
        _ = context.phcov_content.text
    except ValueError as exc:
        context.phcov_error = exc


@when("phcov the resolve method is called")
def step_when_phcov_resolve(context: Context) -> None:
    try:
        context.phcov_result = context.phcov_handler.resolve(
            resource=context.phcov_resource,
            plan_id="plan-001",
            slot_name="repo",
            sandbox_manager=context.phcov_sandbox_manager,
            access="read_only",
        )
    except Exception as exc:
        context.phcov_error = exc


@when("phcov the read method is called")
def step_when_phcov_read(context: Context) -> None:
    try:
        context.phcov_result = context.phcov_handler.read(
            resource=context.phcov_resource,
            path="",
        )
    except Exception as exc:
        context.phcov_error = exc


@when("phcov the write method is called")
def step_when_phcov_write(context: Context) -> None:
    try:
        context.phcov_result = context.phcov_handler.write(
            resource=context.phcov_resource,
            path="test.txt",
            data=b"hello",
        )
    except Exception as exc:
        context.phcov_error = exc


@when("phcov the delete method is called")
def step_when_phcov_delete(context: Context) -> None:
    try:
        context.phcov_result = context.phcov_handler.delete(
            resource=context.phcov_resource,
            path="",
        )
    except Exception as exc:
        context.phcov_error = exc


@when("phcov the list_children method is called")
def step_when_phcov_list_children(context: Context) -> None:
    try:
        context.phcov_result = context.phcov_handler.list_children(
            resource=context.phcov_resource,
        )
    except Exception as exc:
        context.phcov_error = exc


@when("phcov the diff method is called")
def step_when_phcov_diff(context: Context) -> None:
    try:
        context.phcov_result = context.phcov_handler.diff(
            resource=context.phcov_resource,
            other_location="/tmp/other",
        )
    except Exception as exc:
        context.phcov_error = exc


@when("phcov the discover_children method is called")
def step_when_phcov_discover_children(context: Context) -> None:
    try:
        context.phcov_result = context.phcov_handler.discover_children(
            resource=context.phcov_resource,
        )
    except Exception as exc:
        context.phcov_error = exc


@when("phcov the create_sandbox method is called")
def step_when_phcov_create_sandbox(context: Context) -> None:
    try:
        context.phcov_result = context.phcov_handler.create_sandbox(
            resource=context.phcov_resource,
            plan_id="plan-001",
            sandbox_manager=context.phcov_sandbox_manager,
        )
    except Exception as exc:
        context.phcov_error = exc


@when("phcov the create_checkpoint method is called")
def step_when_phcov_create_checkpoint(context: Context) -> None:
    try:
        context.phcov_result = context.phcov_handler.create_checkpoint(
            resource=context.phcov_resource,
            plan_id="plan-001",
            sandbox_manager=context.phcov_sandbox_manager,
            phase="execution",
        )
    except Exception as exc:
        context.phcov_error = exc


@when("phcov the rollback_to method is called")
def step_when_phcov_rollback_to(context: Context) -> None:
    try:
        context.phcov_result = context.phcov_handler.rollback_to(
            resource=context.phcov_resource,
            plan_id="plan-001",
            checkpoint_id="chk-001",
            sandbox_manager=context.phcov_sandbox_manager,
        )
    except Exception as exc:
        context.phcov_error = exc


@when("phcov the project_access method is called")
def step_when_phcov_project_access(context: Context) -> None:
    try:
        context.phcov_result = context.phcov_handler.project_access(
            resource=context.phcov_resource,
            principal="user-alice",
            action="read",
            project_id="proj-001",
        )
    except Exception as exc:
        context.phcov_error = exc


# ---------------------------------------------------------------------------
# Then steps
# ---------------------------------------------------------------------------


@then('phcov a ValueError should be stored with message "{expected_msg}"')
def step_then_phcov_valueerror(context: Context, expected_msg: str) -> None:
    assert context.phcov_error is not None, (
        "Expected a ValueError but no exception was raised"
    )
    assert isinstance(context.phcov_error, ValueError), (
        f"Expected ValueError, got {type(context.phcov_error).__name__}"
    )
    actual_msg = str(context.phcov_error)
    assert expected_msg in actual_msg, (
        f"Expected message to contain '{expected_msg}', got: '{actual_msg}'"
    )


@then("phcov the result should be None")
def step_then_phcov_result_none(context: Context) -> None:
    assert context.phcov_error is None, f"Unexpected exception: {context.phcov_error}"
    assert context.phcov_result is None, (
        f"Expected None but got: {context.phcov_result!r}"
    )
