"""Tests for the /new command functionality."""

from unittest.mock import MagicMock, patch
from uuid import UUID

from prompt_toolkit.input.defaults import create_pipe_input
from prompt_toolkit.output.defaults import DummyOutput

from openhands_cli.setup import (
    MissingAgentSpec,
    verify_agent_exists_or_setup_agent,
)
from openhands_cli.user_actions import UserConfirmation


@patch("openhands_cli.setup.load_agent_specs")
def test_verify_agent_exists_or_setup_agent_success(mock_load_agent_specs):
    """Test that verify_agent_exists_or_setup_agent returns agent successfully."""
    # Mock the agent object
    mock_agent = MagicMock()
    mock_load_agent_specs.return_value = mock_agent

    # Call the function
    result = verify_agent_exists_or_setup_agent()

    # Verify the result
    assert result == mock_agent
    mock_load_agent_specs.assert_called_once_with()


@patch("openhands_cli.setup.SettingsScreen")
@patch("openhands_cli.setup.load_agent_specs")
def test_verify_agent_exists_or_setup_agent_missing_agent_spec(
    mock_load_agent_specs, mock_settings_screen_class
):
    """Test that verify_agent_exists_or_setup_agent handles MissingAgentSpec exception."""
    # Mock the SettingsScreen instance
    mock_settings_screen = MagicMock()
    mock_settings_screen_class.return_value = mock_settings_screen

    # Mock load_agent_specs to raise MissingAgentSpec on first call, then succeed
    mock_agent = MagicMock()
    mock_load_agent_specs.side_effect = [
        MissingAgentSpec("Agent spec missing"),
        mock_agent,
    ]

    # Call the function
    result = verify_agent_exists_or_setup_agent()

    # Verify the result
    assert result == mock_agent
    # Should be called twice: first fails, second succeeds
    assert mock_load_agent_specs.call_count == 2
    # Settings screen should be called once with first_time=True (new behavior)
    mock_settings_screen.configure_settings.assert_called_once_with(first_time=True)


@patch("openhands_cli.agent_chat.exit_session_confirmation")
@patch("openhands_cli.agent_chat.get_session_prompter")
@patch("openhands_cli.agent_chat.setup_conversation")
@patch("openhands_cli.agent_chat.verify_agent_exists_or_setup_agent")
@patch("openhands_cli.agent_chat.ConversationRunner")
def test_new_command_resets_confirmation_mode(
    mock_runner_cls,
    mock_verify_agent,
    mock_setup_conversation,
    mock_get_session_prompter,
    mock_exit_confirm,
):
    # Auto-accept the exit prompt to avoid interactive UI and EOFError
    mock_exit_confirm.return_value = UserConfirmation.ACCEPT

    # Mock agent verification to succeed
    mock_agent = MagicMock()
    mock_verify_agent.return_value = mock_agent

    # Mock conversation - only one is created when /new is called
    conv1 = MagicMock()
    conv1.id = UUID("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
    mock_setup_conversation.return_value = conv1

    # One runner instance for the conversation
    runner1 = MagicMock()
    runner1.is_confirmation_mode_active = True
    mock_runner_cls.return_value = runner1

    # Real session fed by a pipe (no interactive confirmation now)
    from openhands_cli.user_actions.utils import (
        get_session_prompter as real_get_session_prompter,
    )

    with create_pipe_input() as pipe:
        output = DummyOutput()
        session = real_get_session_prompter(input=pipe, output=output)
        mock_get_session_prompter.return_value = session

        from openhands_cli.agent_chat import run_cli_entry

        # Trigger /new
        # First user message should trigger runner creation
        # Then /exit (exit will be auto-accepted)
        for ch in "/new\rhello\r/exit\r":
            pipe.send_text(ch)

        run_cli_entry(None)

    # Assert we created one runner for the conversation when a message was processed after /new
    assert mock_runner_cls.call_count == 1
    assert mock_runner_cls.call_args_list[0].args[0] is conv1
