"""Tests for camera, audio, and UI operations."""

from pathlib import Path

import pytest

from godot_mcp.server import (
    camera_add,
    audio_add_stream_player,
    ui_add_control,
    ui_add_container,
    autoload_add,
    autoload_list,
    scene_create,
    node_add,
    script_create,
)


class TestCameraAdd:
    """Test cases for the camera_add tool."""

    def test_add_camera2d(self, temp_godot_project: Path) -> None:
        """Test adding a Camera2D to a scene."""
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            root_node_type="Node2D",
        )

        result = camera_add(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            parent_node_path=".",
            camera_name="MainCamera",
            camera_type="Camera2D",
        )

        assert "successfully" in result.lower() or "added" in result.lower()
        assert "MainCamera" in result

    def test_add_camera3d(self, temp_godot_project: Path) -> None:
        """Test adding a Camera3D to a scene."""
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            root_node_type="Node3D",
        )

        result = camera_add(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            parent_node_path=".",
            camera_name="Camera3D",
            camera_type="Camera3D",
            make_current=True,
        )

        assert "successfully" in result.lower() or "added" in result.lower()

    def test_add_camera_invalid_type(self, temp_godot_project: Path) -> None:
        """Test error handling for invalid camera type."""
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
        )

        result = camera_add(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            parent_node_path=".",
            camera_name="Camera",
            camera_type="InvalidCamera",
        )

        assert "Invalid camera type" in result


class TestAudioStreamPlayer:
    """Test cases for the audio_add_stream_player tool."""

    def test_add_audio_stream_player(self, temp_godot_project: Path) -> None:
        """Test adding an AudioStreamPlayer to a scene."""
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            root_node_type="Node2D",
        )

        result = audio_add_stream_player(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            parent_node_path=".",
            player_name="MusicPlayer",
            player_type="AudioStreamPlayer",
        )

        assert "successfully" in result.lower() or "added" in result.lower()
        assert "MusicPlayer" in result

    def test_add_audio_stream_player_2d(self, temp_godot_project: Path) -> None:
        """Test adding an AudioStreamPlayer2D."""
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            root_node_type="Node2D",
        )

        result = audio_add_stream_player(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            parent_node_path=".",
            player_name="SFXPlayer",
            player_type="AudioStreamPlayer2D",
            autoplay=False,
        )

        assert "successfully" in result.lower() or "added" in result.lower()

    def test_add_audio_stream_player_invalid_type(
        self, temp_godot_project: Path
    ) -> None:
        """Test error handling for invalid player type."""
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
        )

        result = audio_add_stream_player(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            parent_node_path=".",
            player_name="Player",
            player_type="InvalidPlayer",
        )

        assert "Invalid player type" in result


class TestUIControl:
    """Test cases for the ui_add_control tool."""

    def test_add_button_control(self, temp_godot_project: Path) -> None:
        """Test adding a Button control to a scene."""
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            root_node_type="Control",
        )

        result = ui_add_control(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            parent_node_path=".",
            control_type="Button",
            control_name="StartButton",
            text="Start Game",
        )

        assert "successfully" in result.lower() or "added" in result.lower()
        assert "StartButton" in result

    def test_add_label_control(self, temp_godot_project: Path) -> None:
        """Test adding a Label control."""
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            root_node_type="Control",
        )

        result = ui_add_control(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            parent_node_path=".",
            control_type="Label",
            control_name="TitleLabel",
            text="Game Title",
        )

        assert "successfully" in result.lower() or "added" in result.lower()

    def test_add_ui_container(self, temp_godot_project: Path) -> None:
        """Test adding a VBoxContainer."""
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            root_node_type="Control",
        )

        result = ui_add_container(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            parent_node_path=".",
            container_type="VBoxContainer",
            container_name="MenuContainer",
        )

        assert "successfully" in result.lower() or "added" in result.lower()


class TestAutoload:
    """Test cases for autoload tools."""

    def test_add_autoload(self, temp_godot_project: Path) -> None:
        """Test adding an autoload singleton."""
        # Create a script first
        script_path = "global.gd"
        script_create(
            project_path=str(temp_godot_project),
            script_path=script_path,
            extends_type="Node",
        )

        result = autoload_add(
            project_path=str(temp_godot_project),
            name="Global",
            script_path=script_path,
        )

        assert "successfully" in result.lower() or "added" in result.lower()
        assert "Global" in result

    def test_list_autoloads_empty(self, temp_godot_project: Path) -> None:
        """Test listing autoloads when none exist."""
        result = autoload_list(
            project_path=str(temp_godot_project),
        )

        # Should return valid JSON
        assert "autoloads" in result or "{" in result

    def test_add_and_list_autoloads(self, temp_godot_project: Path) -> None:
        """Test adding and then listing autoloads."""
        # Create and add autoload
        script_path = "game_manager.gd"
        script_create(
            project_path=str(temp_godot_project),
            script_path=script_path,
            extends_type="Node",
        )

        add_result = autoload_add(
            project_path=str(temp_godot_project),
            name="GameManager",
            script_path=script_path,
        )

        # Verify add was successful
        assert "successfully" in add_result.lower() or "added" in add_result.lower()

        # List autoloads - this should work but we can't guarantee JSON parsing
        result = autoload_list(
            project_path=str(temp_godot_project),
        )

        # Just check that we got a result (not an error)
        assert result and len(result) > 0
