"""Step definitions for plan merge strategy feature tests."""

from typing import Any

from behave import given, then, when

from cleveragents.domain.models.core.merge_strategy import MergeStrategy
from cleveragents.domain.models.core.merge_strategy_service import (
    MergeConflict,
    MergeStrategyService,
)


@given("a merge strategy service is initialized")
def step_initialize_service(context: Any) -> None:
    """Initialize a merge strategy service."""
    context.service = MergeStrategyService()
    context.conflicts = []
    context.resolved = {}
    context.error = None


@given('the merge strategy is set to "{strategy}"')
def step_set_merge_strategy(context: Any, strategy: str) -> None:
    """Set the merge strategy."""
    context.service = MergeStrategyService(strategy=MergeStrategy.from_string(strategy))


@when(
    'a conflict occurs with parent value "{parent_value}" and subplan value "{subplan_value}"'
)
def step_create_conflict(context: Any, parent_value: str, subplan_value: str) -> None:
    """Create a conflict."""
    conflict = MergeConflict(
        path="test_field", parent_value=parent_value, subplan_value=subplan_value
    )
    context.conflicts = [conflict]


@then('the conflict should be auto-resolved with value "{expected_value}"')
def step_verify_auto_resolution(context: Any, expected_value: str) -> None:
    """Verify that the conflict was auto-resolved with the expected value."""
    try:
        context.resolved = context.service.resolve_conflicts(context.conflicts)
        assert "test_field" in context.resolved
        assert context.resolved["test_field"] == expected_value
    except ValueError as e:
        context.error = e


@then("the strategy should support auto-resolution")
def step_verify_auto_resolve_support(context: Any) -> None:
    """Verify that the strategy supports auto-resolution."""
    assert context.service.can_auto_resolve()


@then("the conflict should require manual resolution")
def step_verify_manual_resolution(context: Any) -> None:
    """Verify that the conflict requires manual resolution."""
    try:
        context.service.resolve_conflicts(context.conflicts)
    except ValueError as e:
        context.error = e
        assert "manual" in str(e).lower()


@then("the strategy should not support auto-resolution")
def step_verify_no_auto_resolve_support(context: Any) -> None:
    """Verify that the strategy does not support auto-resolution."""
    assert not context.service.can_auto_resolve()


@when("multiple conflicts occur:")
def step_create_multiple_conflicts(context: Any) -> None:
    """Create multiple conflicts from table."""
    context.conflicts = []
    for row in context.table:
        conflict = MergeConflict(
            path=row["path"],
            parent_value=row["parent_value"],
            subplan_value=row["subplan_value"],
        )
        context.conflicts.append(conflict)


@then("all conflicts should be resolved with parent values")
def step_verify_all_parent_resolution(context: Any) -> None:
    """Verify that all conflicts are resolved with parent values."""
    context.resolved = context.service.resolve_conflicts(context.conflicts)
    for conflict in context.conflicts:
        assert conflict.path in context.resolved
        assert context.resolved[conflict.path] == conflict.parent_value


@when("attempting to auto-resolve conflicts")
def step_attempt_auto_resolve(context: Any) -> None:
    """Attempt to auto-resolve conflicts."""
    try:
        context.service.resolve_conflicts(context.conflicts)
        context.error = None
    except ValueError as e:
        context.error = e


@then("an error should be raised indicating manual resolution is required")
def step_verify_manual_resolution_error(context: Any) -> None:
    """Verify that an error was raised for manual resolution."""
    assert context.error is not None
    assert "manual" in str(context.error).lower()


@when('a merge strategy is created from string "{strategy_str}"')
def step_create_strategy_from_string(context: Any, strategy_str: str) -> None:
    """Create a merge strategy from a string."""
    try:
        context.strategy = MergeStrategy.from_string(strategy_str)
        context.error = None
    except ValueError as e:
        context.error = e


@then('the strategy should be "{expected_strategy}"')
def step_verify_strategy_value(context: Any, expected_strategy: str) -> None:
    """Verify the strategy value."""
    assert context.strategy.value == expected_strategy


@then('the strategy string representation should be "{expected_str}"')
def step_verify_strategy_string(context: Any, expected_str: str) -> None:
    """Verify the strategy string representation."""
    assert str(context.strategy) == expected_str


@when('attempting to create a merge strategy from invalid string "{invalid_str}"')
def step_create_invalid_strategy(context: Any, invalid_str: str) -> None:
    """Attempt to create a strategy from an invalid string."""
    try:
        MergeStrategy.from_string(invalid_str)
        context.error = None
    except ValueError as e:
        context.error = e


@then('an error should be raised with message containing "{message_part}"')
def step_verify_error_message(context: Any, message_part: str) -> None:
    """Verify that an error was raised with the expected message."""
    assert context.error is not None
    assert message_part in str(context.error)


@when("there are no conflicts")
def step_no_conflicts(context: Any) -> None:
    """Set up a scenario with no conflicts."""
    context.conflicts = []


@then("the resolution should return an empty result")
def step_verify_empty_resolution(context: Any) -> None:
    """Verify that resolution returns an empty result."""
    context.resolved = context.service.resolve_conflicts(context.conflicts)
    assert context.resolved == {}


@then("no conflicts should be detected")
def step_verify_no_conflicts_detected(context: Any) -> None:
    """Verify that no conflicts are detected."""
    assert not context.service.has_conflicts(context.conflicts)
