"""TmuxWrapper 单元测试。"""

import pytest
from unittest.mock import Mock
from butler.session.wrapper import TmuxWrapper, PtyState, SessionMode


@pytest.fixture
def tmux_wrapper():
    """创建 TmuxWrapper 实例。"""
    return TmuxWrapper(session_prefix="test_")


class TestTmuxWrapperBasic:
    """TmuxWrapper 基础功能测试。"""

    def test_create_session(self, mock_subprocess, tmux_wrapper):
        """测试创建 tmux session。"""
        mock_subprocess.return_value = Mock(returncode=0)

        session_name = tmux_wrapper.create_session("user123")

        assert session_name == "test_user123"
        mock_subprocess.assert_called_once()
        args = mock_subprocess.call_args[0][0]
        assert "tmux" in args
        assert "new-session" in args
        assert "test_user123" in args

    def test_session_exists_true(self, mock_subprocess, tmux_wrapper):
        """测试 session 存在检测 - 存在。"""
        mock_subprocess.return_value = Mock(returncode=0)

        result = tmux_wrapper.session_exists("test_user123")

        assert result is True

    def test_session_exists_false(self, mock_subprocess, tmux_wrapper):
        """测试 session 存在检测 - 不存在。"""
        mock_subprocess.return_value = Mock(returncode=1)

        result = tmux_wrapper.session_exists("test_user123")

        assert result is False

    def test_kill_session(self, mock_subprocess, tmux_wrapper):
        """测试销毁 session。"""
        tmux_wrapper.kill_session("test_user123")

        args = mock_subprocess.call_args[0][0]
        assert "kill-session" in args
        assert "test_user123" in args

    def test_send_keys_normal(self, mock_subprocess, tmux_wrapper):
        """测试发送普通命令。"""
        tmux_wrapper.send_keys("test_session", "ls -la", enter=True)

        assert mock_subprocess.call_count == 2

    def test_send_keys_no_enter(self, mock_subprocess, tmux_wrapper):
        """测试发送不含 Enter 的命令。"""
        tmux_wrapper.send_keys("test_session", "ls -la", enter=False)

        assert mock_subprocess.call_count == 1

    def test_send_keys_special_key(self, mock_subprocess, tmux_wrapper):
        """测试发送特殊键。"""
        tmux_wrapper.send_keys("test_session", "C-c")

        args = mock_subprocess.call_args[0][0]
        assert "C-c" in args

    def test_send_raw(self, mock_subprocess, tmux_wrapper):
        """测试发送原始数据。"""
        tmux_wrapper.send_raw("test_session", "raw data")

        args = mock_subprocess.call_args[0][0]
        assert "-l" in args
        assert "raw data" in args

    def test_capture_pane(self, mock_subprocess, tmux_wrapper):
        """测试抓取终端内容。"""
        mock_subprocess.return_value = Mock(stdout="line1\nline2\nline3", returncode=0)

        result = tmux_wrapper.capture_pane("test_session")

        assert "line1" in result
        args = mock_subprocess.call_args[0][0]
        assert "capture-pane" in args


class TestTmuxWrapperModeDetection:
    """TmuxWrapper 模式检测测试。"""

    def test_get_active_process_vim(self, mock_subprocess, tmux_wrapper):
        """测试检测 vim 进程。"""
        mock_subprocess.side_effect = [
            Mock(stdout="12345\n", returncode=0),
            Mock(stdout="vim\nbash\n", returncode=0),
        ]

        proc = tmux_wrapper.get_active_process("test_session")
        assert proc == "vim"

    def test_get_active_process_top(self, mock_subprocess, tmux_wrapper):
        """测试检测 top 进程。"""
        mock_subprocess.side_effect = [
            Mock(stdout="12345\n", returncode=0),
            Mock(stdout="top\nbash\n", returncode=0),
        ]

        proc = tmux_wrapper.get_active_process("test_session")
        assert proc == "top"

    def test_get_active_process_shell_only(self, mock_subprocess, tmux_wrapper):
        """测试只有 shell 时返回 None。"""
        mock_subprocess.side_effect = [
            Mock(stdout="12345\n", returncode=0),
            Mock(stdout="bash\n", returncode=0),
        ]

        proc = tmux_wrapper.get_active_process("test_session")
        assert proc is None

    def test_detect_mode_vim(self, mock_subprocess, tmux_wrapper):
        """测试 vim 触发交互模式。"""
        mock_subprocess.side_effect = [
            Mock(stdout="12345\n", returncode=0),
            Mock(stdout="vim\nbash\n", returncode=0),
        ]

        mode = tmux_wrapper.detect_mode("test_session")
        assert mode == SessionMode.INTERACTIVE

    def test_detect_mode_normal(self, mock_subprocess, tmux_wrapper):
        """测试普通命令保持自然语言模式。"""
        mock_subprocess.side_effect = [
            Mock(stdout="12345\n", returncode=0),
            Mock(stdout="bash\n", returncode=0),
        ]

        mode = tmux_wrapper.detect_mode("test_session")
        assert mode == SessionMode.NATURAL_LANGUAGE
