"""Black-box integration tests for chat CLI command.

Spec source: plan step ``cli-chat-command.implement-chat-command``.
"""

from __future__ import annotations

import json
import io
import os
import subprocess
import sys
from pathlib import Path
from unittest.mock import AsyncMock, MagicMock, patch

import pytest
from rich.console import Console
from returns.result import Success


def _anima_cmd(*args: str) -> list[str]:
    return [sys.executable, "-m", "anima", *args]


def _write_persona(path: Path, *, name: str) -> None:
    path.write_text(
        json.dumps(
            {
                "spec_version": "0.1.0",
                "name": name,
                "prompt": "You are a chat integration test persona.",
                "model": "test",
            }
        )
    )


def test_chat_terminal_before_interact_cleans_up_by_default(
    tmp_state_dir: Path,
    tmp_path: Path,
) -> None:
    """Chat exits cleanly and removes state when run ends before interaction."""
    persona_file = tmp_path / "persona_chat_t20.json"
    _write_persona(persona_file, name="chat-t20")

    env = os.environ.copy()
    env["ANIMA_STATE"] = str(tmp_state_dir)
    env["HOME"] = str(tmp_state_dir.parent)

    result = subprocess.run(
        _anima_cmd(
            "chat",
            "T20 terminal before interact",
            "--persona",
            str(persona_file),
            "--model",
            "test",
        ),
        input="/quit\n",
        capture_output=True,
        text=True,
        timeout=15,
        env=env,
        check=False,
    )

    assert result.returncode == 0, (
        f"chat failed rc={result.returncode}\nstdout={result.stdout}\nstderr={result.stderr}"
    )

    agents_dir = tmp_state_dir / "agents"
    if not agents_dir.exists():
        return

    leftovers = [path for path in agents_dir.iterdir() if path.is_dir()]
    assert not leftovers, (
        "Expected chat default cleanup to remove spawned agent state, "
        f"found leftovers: {[str(path) for path in leftovers]}"
    )


def test_chat_accepts_legacy_attach_tuple_for_persona_resolution() -> None:
    """Chat remains compatible with legacy tuple attach helper return shape."""
    from anima.shell.cli_commands.chat_cmd import chat_impl

    talk_session = AsyncMock(return_value=None)
    console = Console(file=io.StringIO(), force_terminal=False)

    mock_state = MagicMock()
    mock_state.persona_name = "tuple-persona"

    with (
        patch(
            "anima.shell.cli_commands.chat_cmd._spawn_chat_agent",
            return_value="inst_tuple_compat",
        ),
        patch(
            "anima.shell.cli_commands.chat_cmd._wait_for_socket_or_terminal",
            return_value=(Path("/tmp/fake.sock"), False),
        ),
        patch("pathlib.Path.exists", return_value=True),
        patch(
            "anima.shell.cli_commands.chat_cmd.read_state",
            return_value=Success(mock_state),
        ),
        patch("anima.shell.cli_commands.chat_cmd.run_talk_session", new=talk_session),
        patch("anima.shell.cli_commands.chat_cmd._cleanup_chat_agent"),
    ):
        with pytest.raises(SystemExit) as exit_info:
            chat_impl(
                task="tuple compat",
                persona=None,
                system_prompt=None,
                job_file=None,
                model=None,
                llm_base_url=None,
                mcp=(),
                tools=(),
                timeout=None,
                max_turns=None,
                max_tokens=None,
                context_mode=None,
                context_bundle=None,
                instance_id=None,
                completion_policy=None,
                token_file=None,
                sandbox=False,
                sandbox_allow=(),
                keep=True,
                json_output=True,
                memory_provider=None,
                console=console,
            )

    assert exit_info.value.code == 0
    assert talk_session.await_count == 1
    assert talk_session.await_args is not None
    assert talk_session.await_args.kwargs["persona_name"] == "tuple-persona"
