"""Step definitions for legacy plan persistence removal tests."""

from __future__ import annotations

import warnings
from typing import Any
from unittest.mock import MagicMock

from behave import given, then, when  # type: ignore[import-untyped]


@given("a clean test environment for legacy removal")
def step_clean_env(context: Any) -> None:
    """Set up a clean test environment."""
    context.caught_warnings = []
    context.deprecation_found = False


# --- PlanService deprecation ---


@when("I instantiate PlanService")
def step_instantiate_plan_service(context: Any) -> None:
    """Instantiate legacy PlanService and capture warnings."""
    from cleveragents.config.settings import Settings

    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        from cleveragents.application.services.plan_service import PlanService

        mock_settings = MagicMock(spec=Settings)
        mock_settings.database_url = "sqlite:///:memory:"
        mock_uow = MagicMock()
        context.legacy_service = PlanService(
            settings=mock_settings,
            unit_of_work=mock_uow,
        )
        context.caught_warnings = list(caught)


@when("I call create_plan on the legacy service")
def step_call_create_plan(context: Any) -> None:
    """Call create_plan on the deprecated PlanService."""
    from pathlib import Path

    from cleveragents.domain.models.core import Project, ProjectSettings

    mock_project = Project(
        id=1,
        name="test-project",
        path=Path("/tmp/test"),
        settings=ProjectSettings(),
    )
    mock_ctx = MagicMock()
    mock_plan = MagicMock()
    mock_plan.id = 1
    mock_plan.name = "test-plan"
    mock_ctx.plans.create.return_value = mock_plan
    context.legacy_service.unit_of_work.transaction.return_value.__enter__ = MagicMock(
        return_value=mock_ctx
    )
    context.legacy_service.unit_of_work.transaction.return_value.__exit__ = MagicMock(
        return_value=False
    )
    context.created_plan = context.legacy_service.create_plan(
        project=mock_project, prompt="test prompt", name="test-plan"
    )


@then("the plan is created successfully")
def step_plan_created(context: Any) -> None:
    """Verify the plan was created."""
    assert context.created_plan is not None


# --- PlanRepository deprecation ---


@when("I instantiate PlanRepository")
def step_instantiate_plan_repository(context: Any) -> None:
    """Instantiate PlanRepository and capture warnings."""
    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        from cleveragents.infrastructure.database.repositories import PlanRepository

        mock_session = MagicMock()
        PlanRepository(mock_session)
        context.caught_warnings = list(caught)


# --- ChangeRepository deprecation ---


@when("I instantiate ChangeRepository")
def step_instantiate_change_repository(context: Any) -> None:
    """Instantiate ChangeRepository and capture warnings."""
    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        from cleveragents.infrastructure.database.repositories import ChangeRepository

        mock_session = MagicMock()
        ChangeRepository(mock_session)
        context.caught_warnings = list(caught)


# --- CLI programmatic wrappers deprecation ---


@when("I call tell_command programmatically")
def step_call_tell_command(context: Any) -> None:
    """Call the deprecated tell_command wrapper."""
    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        try:
            from cleveragents.cli.commands.plan import tell_command

            tell_command(prompt="test")
        except Exception:
            pass  # Expected - no real container in test
        context.caught_warnings = list(caught)


@when("I call build_command programmatically")
def step_call_build_command(context: Any) -> None:
    """Call the deprecated build_command wrapper."""
    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        try:
            from cleveragents.cli.commands.plan import build_command

            build_command()
        except Exception:
            pass
        context.caught_warnings = list(caught)


@when("I call apply_command programmatically")
def step_call_apply_command(context: Any) -> None:
    """Call the deprecated apply_command wrapper."""
    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        try:
            from cleveragents.cli.commands.plan import apply_command

            apply_command()
        except Exception:
            pass
        context.caught_warnings = list(caught)


@when("I call new_command programmatically")
def step_call_new_command(context: Any) -> None:
    """Call the deprecated new_command wrapper."""
    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        try:
            from cleveragents.cli.commands.plan import new_command

            new_command(name="test")
        except Exception:
            pass
        context.caught_warnings = list(caught)


@when("I call current_command programmatically")
def step_call_current_command(context: Any) -> None:
    """Call the deprecated current_command wrapper."""
    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        try:
            from cleveragents.cli.commands.plan import current_command

            current_command()
        except Exception:
            pass
        context.caught_warnings = list(caught)


@when("I call list_command programmatically")
def step_call_list_command(context: Any) -> None:
    """Call the deprecated list_command wrapper."""
    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        try:
            from cleveragents.cli.commands.plan import list_command

            list_command()
        except Exception:
            pass
        context.caught_warnings = list(caught)


@when("I call cd_command programmatically")
def step_call_cd_command(context: Any) -> None:
    """Call the deprecated cd_command wrapper."""
    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        try:
            from cleveragents.cli.commands.plan import cd_command

            cd_command(name="test")
        except Exception:
            pass
        context.caught_warnings = list(caught)


@when("I call continue_command programmatically")
def step_call_continue_command(context: Any) -> None:
    """Call the deprecated continue_command wrapper."""
    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        try:
            from cleveragents.cli.commands.plan import continue_command

            continue_command(prompt="test")
        except Exception:
            pass
        context.caught_warnings = list(caught)


# --- PlanLifecycleService is NOT deprecated ---


@when("I instantiate PlanLifecycleService")
def step_instantiate_lifecycle_service(context: Any) -> None:
    """Instantiate PlanLifecycleService and capture warnings."""
    from cleveragents.config.settings import Settings

    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        from cleveragents.application.services.plan_lifecycle_service import (
            PlanLifecycleService,
        )

        mock_settings = MagicMock(spec=Settings)
        PlanLifecycleService(settings=mock_settings)
        context.caught_warnings = list(caught)


@then("no DeprecationWarning is raised")
def step_no_deprecation_warning(context: Any) -> None:
    """Verify no DeprecationWarning was raised."""
    deprecation_warnings = [
        w for w in context.caught_warnings if issubclass(w.category, DeprecationWarning)
    ]
    assert len(deprecation_warnings) == 0, (
        f"Expected no DeprecationWarning but got {len(deprecation_warnings)}: "
        f"{[str(w.message) for w in deprecation_warnings]}"
    )


# --- UnitOfWorkContext plans accessor ---


@when("I access the plans property on UnitOfWorkContext")
def step_access_plans_property(context: Any) -> None:
    """Access the legacy plans property on UnitOfWorkContext."""
    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        from cleveragents.infrastructure.database.unit_of_work import UnitOfWorkContext

        mock_session = MagicMock()
        uow_ctx = UnitOfWorkContext(mock_session)
        _plans = uow_ctx.plans  # triggers the deprecation in PlanRepository
        context.caught_warnings = list(caught)


# --- Shared assertion steps ---


@then('a DeprecationWarning mentioning "{text}" is raised')
def step_deprecation_warning_with_text(context: Any, text: str) -> None:
    """Verify a DeprecationWarning containing the given text was raised."""
    deprecation_warnings = [
        w for w in context.caught_warnings if issubclass(w.category, DeprecationWarning)
    ]
    assert len(deprecation_warnings) > 0, (
        f"Expected a DeprecationWarning mentioning '{text}' but got none. "
        f"All warnings: {[str(w.message) for w in context.caught_warnings]}"
    )
    messages = [str(w.message) for w in deprecation_warnings]
    found = any(text.lower() in msg.lower() for msg in messages)
    assert found, (
        f"Expected a DeprecationWarning containing '{text}' but got: {messages}"
    )
