"""Tests for editor screenshot routing."""

import pytest
from unittest.mock import AsyncMock, patch

from godotiq.tools.bridge.screenshot import screenshot


class TestEditorScreenshot:
    @pytest.mark.asyncio
    async def test_editor_viewport(self):
        """Editor viewport routes to 'editor_screenshot' method."""
        mock_bridge = AsyncMock()
        mock_bridge.request = AsyncMock(return_value={
            "image": "base64data",
            "width": 540,
            "height": 960,
            "format": "webp",
            "viewport": "editor",
        })
        with patch("godotiq.tools.bridge.screenshot.get_bridge", return_value=mock_bridge):
            result = await screenshot(viewport="editor", scale=0.5)
            call_args = mock_bridge.request.call_args
            assert call_args[0][0] == "editor_screenshot"
            assert result["viewport"] == "editor"

    @pytest.mark.asyncio
    async def test_editor_with_camera(self):
        """Camera params should be included in editor screenshot request."""
        mock_bridge = AsyncMock()
        mock_bridge.request = AsyncMock(return_value={"image": "base64data"})
        with patch("godotiq.tools.bridge.screenshot.get_bridge", return_value=mock_bridge):
            await screenshot(
                viewport="editor",
                camera_position=[5, 3, 5],
                camera_target=[0, 0, 0],
            )
            params = mock_bridge.request.call_args[1]["params"]
            assert params["camera_position"] == [5, 3, 5]
            assert params["camera_target"] == [0, 0, 0]

    @pytest.mark.asyncio
    async def test_game_viewport_unchanged(self):
        """Game viewport should still use 'screenshot' method with retry."""
        mock_bridge = AsyncMock()
        mock_bridge.request_with_retry = AsyncMock(return_value={"image": "base64"})
        with patch("godotiq.tools.bridge.screenshot.get_bridge", return_value=mock_bridge):
            await screenshot(viewport="game", scale=0.25)
            call_args = mock_bridge.request_with_retry.call_args
            assert call_args[0][0] == "screenshot"

    @pytest.mark.asyncio
    async def test_default_viewport_is_game(self):
        """Default viewport should be 'game'."""
        mock_bridge = AsyncMock()
        mock_bridge.request_with_retry = AsyncMock(return_value={"image": "base64"})
        with patch("godotiq.tools.bridge.screenshot.get_bridge", return_value=mock_bridge):
            await screenshot()
            call_args = mock_bridge.request_with_retry.call_args
            assert call_args[0][0] == "screenshot"

    @pytest.mark.asyncio
    async def test_editor_no_camera_params(self):
        """Editor without camera should not include camera params."""
        mock_bridge = AsyncMock()
        mock_bridge.request = AsyncMock(return_value={"image": "base64"})
        with patch("godotiq.tools.bridge.screenshot.get_bridge", return_value=mock_bridge):
            await screenshot(viewport="editor")
            params = mock_bridge.request.call_args[1]["params"]
            assert "camera_position" not in params
            assert "camera_target" not in params

    @pytest.mark.asyncio
    async def test_invalid_viewport_returns_error(self):
        """Invalid viewport should return error without bridge call."""
        result = await screenshot(viewport="foo")
        assert "error" in result
        assert "Invalid viewport" in result["error"]

    @pytest.mark.asyncio
    async def test_camera_position_validation(self):
        """camera_position with != 3 elements should return error."""
        result = await screenshot(viewport="editor", camera_position=[1, 2])
        assert "error" in result
        assert "3 elements" in result["error"]

    @pytest.mark.asyncio
    async def test_camera_target_validation(self):
        """camera_target with != 3 elements should return error."""
        result = await screenshot(viewport="editor", camera_target=[1])
        assert "error" in result
        assert "3 elements" in result["error"]

    @pytest.mark.asyncio
    async def test_quality_param_passed_to_editor(self):
        """Quality parameter should be included in editor screenshot params."""
        mock_bridge = AsyncMock()
        mock_bridge.request = AsyncMock(return_value={"image": "base64"})
        with patch("godotiq.tools.bridge.screenshot.get_bridge", return_value=mock_bridge):
            await screenshot(viewport="editor", quality=0.3)
            params = mock_bridge.request.call_args[1]["params"]
            assert params["quality"] == 0.3

    @pytest.mark.asyncio
    async def test_quality_param_passed_to_game(self):
        """Quality parameter should be included in game screenshot params."""
        mock_bridge = AsyncMock()
        mock_bridge.request_with_retry = AsyncMock(return_value={"image": "base64"})
        with patch("godotiq.tools.bridge.screenshot.get_bridge", return_value=mock_bridge):
            await screenshot(viewport="game", quality=0.7)
            params = mock_bridge.request_with_retry.call_args.kwargs["params"]
            assert params["quality"] == 0.7

    @pytest.mark.asyncio
    async def test_quality_default(self):
        """Default quality should be 0.5."""
        mock_bridge = AsyncMock()
        mock_bridge.request = AsyncMock(return_value={"image": "base64"})
        with patch("godotiq.tools.bridge.screenshot.get_bridge", return_value=mock_bridge):
            await screenshot(viewport="editor")
            params = mock_bridge.request.call_args[1]["params"]
            assert params["quality"] == 0.5

    @pytest.mark.asyncio
    async def test_quality_invalid_clamped(self):
        """Invalid quality should be clamped to 0.5."""
        mock_bridge = AsyncMock()
        mock_bridge.request = AsyncMock(return_value={"image": "base64"})
        with patch("godotiq.tools.bridge.screenshot.get_bridge", return_value=mock_bridge):
            await screenshot(viewport="editor", quality=-1.0)
            params = mock_bridge.request.call_args[1]["params"]
            assert params["quality"] == 0.5

    @pytest.mark.asyncio
    async def test_size_warning_added(self):
        """Large images should include size_warning in result."""
        large_image = "x" * 50000
        mock_bridge = AsyncMock()
        mock_bridge.request = AsyncMock(return_value={"image": large_image})
        with patch("godotiq.tools.bridge.screenshot.get_bridge", return_value=mock_bridge):
            result = await screenshot(viewport="editor")
            assert "size_warning" in result
            assert "50000" in result["size_warning"]

    @pytest.mark.asyncio
    async def test_no_size_warning_for_small_images(self):
        """Small images should not have size_warning."""
        mock_bridge = AsyncMock()
        mock_bridge.request = AsyncMock(return_value={"image": "small"})
        with patch("godotiq.tools.bridge.screenshot.get_bridge", return_value=mock_bridge):
            result = await screenshot(viewport="editor")
            assert "size_warning" not in result
