"""Step definitions for tdd_persona_state_set_active_persona_reset.feature.

These steps capture bug #10500: PersonaState.set_active_persona() does not
reset the active preset to "default" when switching to a different persona.

The current implementation only initialises the preset when the session has
no preset entry at all.  If the session already has a non-default preset
(e.g. because the user cycled through presets), switching persona leaves
that preset unchanged instead of resetting it to "default".

Expected (correct) behaviour:
    state.set_active_persona(session_id, new_persona)
    -> state.current_preset(session_id) == "default"

Actual (buggy) behaviour:
    state.set_active_persona(session_id, new_persona)
    -> state.current_preset(session_id) == <previous non-default preset>
"""

from unittest.mock import MagicMock

from behave import given, then, when

from cleveragents.tui.persona.schema import Persona
from cleveragents.tui.persona.state import PersonaState

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


def _make_persona(name, actor="ns/actor"):
    """Build a minimal real Persona for testing."""
    return Persona(name=name, actor=actor)


def _make_mock_registry(personas):
    """Return a MagicMock that quacks like PersonaRegistry."""
    registry = MagicMock()
    default = next(iter(personas.values()))
    registry.ensure_default.return_value = default
    registry.get_last_persona.return_value = None
    registry.set_last_persona = MagicMock()

    def _get(name):
        return personas.get(name)

    registry.get.side_effect = _get
    return registry


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


@given(
    'a session "{session_id}" with persona "{persona_name}"'
    ' and a non-default preset "{preset_name}"'
)
def step_session_with_persona_and_preset(
    context, session_id, persona_name, preset_name
):
    """Set up a session that already has a non-default preset."""
    coder = _make_persona("coder", actor="ns/coder")
    analyst = _make_persona("analyst", actor="ns/analyst")
    registry = _make_mock_registry({"coder": coder, "analyst": analyst})
    context.state = PersonaState(
        registry=registry,
        active_by_session={session_id: persona_name},
        preset_by_session={session_id: preset_name},
    )


@given('the preset for session "{session_id}" has been updated to "{preset_name}"')
def step_update_preset(context, session_id, preset_name):
    """Directly update the preset for a session (simulates cycling)."""
    context.state.preset_by_session[session_id] = preset_name


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


@when('I switch session "{session_id}" to persona "{persona_name}"')
def step_switch_persona(context, session_id, persona_name):
    """Call set_active_persona to switch the active persona."""
    context.state.set_active_persona(session_id, persona_name)


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


@then('the preset for session "{session_id}" should be "{expected_preset}"')
def step_verify_preset(context, session_id, expected_preset):
    """Assert that the preset has been reset to the expected value.

    This assertion will FAIL while bug #10500 is unfixed because
    set_active_persona() does not reset an existing preset to "default".
    The @tdd_expected_fail tag inverts this failure so CI passes.
    """
    actual = context.state.current_preset(session_id)
    assert actual == expected_preset, (
        f"Bug #10500: expected preset '{expected_preset}' after switching persona "
        f"but got '{actual}'. set_active_persona() does not reset an existing "
        f"non-default preset to 'default'."
    )
