"""测试鼠标位置功能"""

import sys
from pathlib import Path
import pytest
from unittest.mock import AsyncMock, MagicMock

# 添加 src 目录到 Python 路径
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))

from novnc_client.client import NoVNCClient
from novnc_client.types import ServerInfo, PixelFormat


@pytest.fixture
def mock_server_info():
    """创建模拟服务器信息"""
    pixel_format = PixelFormat(
        bits_per_pixel=32,
        depth=24,
        big_endian=False,
        true_colour=True,
        red_max=255,
        green_max=255,
        blue_max=255,
        red_shift=16,
        green_shift=8,
        blue_shift=0,
    )
    return ServerInfo(
        width=1920, height=1080, pixel_format=pixel_format, server_name="Test Server"
    )


@pytest.fixture
def mock_client(mock_server_info):
    """创建模拟客户端"""
    client = NoVNCClient("localhost", 6080)

    # 模拟 handler
    client._handler = MagicMock()
    client._handler.server_info = mock_server_info
    client._handler.connect = AsyncMock()
    client._handler.perform_handshake = AsyncMock()
    client._handler.send_binary = AsyncMock()
    client._handler.disconnect = AsyncMock()

    return client


class TestMousePosition:
    """测试鼠标位置功能"""

    def test_initial_mouse_position(self):
        """测试初始鼠标位置"""
        client = NoVNCClient("localhost", 6080)
        assert client.mouse_position == (0, 0)

    @pytest.mark.asyncio
    async def test_mouse_position_after_connect(self, mock_client, mock_server_info):
        """测试连接后鼠标位置初始化"""
        # 连接
        await mock_client.connect()

        # 检查鼠标位置是否初始化为屏幕中心
        expected_x = mock_server_info.width // 2
        expected_y = mock_server_info.height // 2

        assert mock_client.mouse_position == (expected_x, expected_y)

    @pytest.mark.asyncio
    async def test_mouse_move_updates_position(self, mock_client):
        """测试鼠标移动更新位置"""
        await mock_client.connect()

        # 移动鼠标
        new_x, new_y = 100, 200
        await mock_client.mouse_move(new_x, new_y)

        # 检查位置是否更新
        assert mock_client.mouse_position == (new_x, new_y)

    @pytest.mark.asyncio
    async def test_mouse_click_updates_position(self, mock_client):
        """测试鼠标点击更新位置"""
        await mock_client.connect()

        # 点击鼠标
        click_x, click_y = 300, 400
        await mock_client.mouse_click(click_x, click_y)

        # 检查位置是否更新
        assert mock_client.mouse_position == (click_x, click_y)

    @pytest.mark.asyncio
    async def test_mouse_scroll_updates_position(self, mock_client):
        """测试鼠标滚轮更新位置"""
        await mock_client.connect()

        # 滚动鼠标
        scroll_x, scroll_y = 500, 600
        await mock_client.mouse_scroll(scroll_x, scroll_y, "up", 3)

        # 检查位置是否更新
        assert mock_client.mouse_position == (scroll_x, scroll_y)

    @pytest.mark.asyncio
    async def test_multiple_mouse_operations(self, mock_client):
        """测试多个鼠标操作的位置追踪"""
        await mock_client.connect()

        # 执行多个鼠标操作
        operations = [
            ("move", 100, 100),
            ("click", 200, 200),
            ("scroll", 300, 300),
            ("move", 400, 400),
        ]

        for operation, x, y in operations:
            if operation == "move":
                await mock_client.mouse_move(x, y)
            elif operation == "click":
                await mock_client.mouse_click(x, y)
            elif operation == "scroll":
                await mock_client.mouse_scroll(x, y, "up", 1)

            # 检查每次操作后位置是否正确更新
            assert mock_client.mouse_position == (x, y)

    @pytest.mark.asyncio
    async def test_mouse_position_with_different_buttons(self, mock_client):
        """测试不同鼠标按钮的位置追踪"""
        await mock_client.connect()

        # 测试不同的鼠标按钮
        buttons = ["left", "right", "middle"]

        for i, button in enumerate(buttons):
            x, y = 100 + i * 50, 200 + i * 50
            await mock_client.mouse_click(x, y, button)

            # 检查位置是否正确更新
            assert mock_client.mouse_position == (x, y)

    @pytest.mark.asyncio
    async def test_mouse_position_with_scroll_directions(self, mock_client):
        """测试不同滚动方向的位置追踪"""
        await mock_client.connect()

        # 测试不同的滚动方向
        directions = ["up", "down"]

        for i, direction in enumerate(directions):
            x, y = 150 + i * 50, 250 + i * 50
            await mock_client.mouse_scroll(x, y, direction, 2)

            # 检查位置是否正确更新
            assert mock_client.mouse_position == (x, y)

    def test_mouse_position_property_access(self, mock_client):
        """测试鼠标位置属性访问"""
        # 检查初始位置
        assert mock_client.mouse_position == (0, 0)

        # 修改内部位置
        mock_client._mouse_x = 123
        mock_client._mouse_y = 456

        # 检查属性是否正确返回位置
        assert mock_client.mouse_position == (123, 456)

    @pytest.mark.asyncio
    async def test_mouse_position_without_server_info(self):
        """测试没有服务器信息时的鼠标位置初始化"""
        client = NoVNCClient("localhost", 6080)

        # 模拟没有服务器信息的情况
        client._handler = MagicMock()
        client._handler.server_info = None
        client._handler.connect = AsyncMock()
        client._handler.perform_handshake = AsyncMock()
        client._handler.disconnect = AsyncMock()

        # 连接
        await client.connect()

        # 检查鼠标位置是否初始化为 (0, 0)
        assert client.mouse_position == (0, 0)
