"""
Tests for Script Attachment functionality.

Tests the ability to attach GDScript files to nodes in Godot scenes.
"""

from pathlib import Path


from godot_mcp.server import script_attach, scene_create


class TestAttachScript:
    """Tests for the script_attach tool."""

    def test_script_attach_to_root_node(
        self, temp_godot_project: Path, temp_script_file: Path
    ) -> None:
        """
        Test attaching a script to the root node of a scene.

        This is the basic use case: create a scene, create a script,
        and attach the script to the root node.
        """
        # Create a scene first
        scene_path = "attach_test_scene.tscn"
        create_result = scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            root_node_type="Node2D",
        )
        assert "successfully" in create_result.lower() or "created" in create_result.lower(), (
            f"Failed to create scene: {create_result}"
        )

        # Verify the scene file exists
        scene_file = temp_godot_project / scene_path
        assert scene_file.exists(), f"Scene file not created at {scene_file}"

        # Attach the script to the root node
        result = script_attach(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            node_path="root",
            script_path=str(temp_script_file),
        )

        # Check the result indicates success
        assert "successfully" in result.lower() or "attached" in result.lower(), (
            f"script_attach failed: {result}"
        )

        # Verify the scene file now contains a script reference
        scene_content = scene_file.read_text(encoding="utf-8")

        # The .tscn file should contain an ext_resource for the script
        # and the root node should have a script property
        assert "test_script.gd" in scene_content, (
            f"Script reference not found in scene file. Content:\n{scene_content}"
        )

    def test_script_attach_invalid_scene_path(
        self, temp_godot_project: Path, temp_script_file: Path
    ) -> None:
        """Test that attaching a script to a non-existent scene fails gracefully."""
        result = script_attach(
            project_path=str(temp_godot_project),
            scene_path="nonexistent_scene.tscn",
            node_path="root",
            script_path=str(temp_script_file),
        )

        # Should return an error message
        assert (
            "error" in result.lower() or "not exist" in result.lower() or "failed" in result.lower()
        ), f"Expected error for non-existent scene, got: {result}"

    def test_script_attach_invalid_project_path(self) -> None:
        """Test that attaching a script with invalid project path fails."""
        result = script_attach(
            project_path="/nonexistent/project/path",
            scene_path="scene.tscn",
            node_path="root",
            script_path="script.gd",
        )

        # Should return an error message
        assert (
            "error" in result.lower() or "not" in result.lower() or "invalid" in result.lower()
        ), f"Expected error for invalid project, got: {result}"

    def test_script_attach_missing_parameters(self) -> None:
        """Test that missing required parameters are handled."""
        # Missing project_path
        result = script_attach(
            project_path="",
            scene_path="scene.tscn",
            node_path="root",
            script_path="script.gd",
        )
        assert "required" in result.lower() or "invalid" in result.lower(), (
            f"Expected error for empty project_path, got: {result}"
        )

    def test_script_attach_to_child_node(self, temp_godot_project: Path) -> None:
        """
        Test attaching a script to a child node (not the root).

        This tests the node_path parameter with nested paths.
        """
        # Create a scene with a child node using add_node
        from godot_mcp.server import node_add, scene_create

        scene_path = "child_node_test.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            root_node_type="Node2D",
        )

        # Add a child node
        node_add(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            node_type="Sprite2D",
            node_name="MySprite",
            parent_node_path="root",
        )

        # Create a script for the child node
        child_script_content = """extends Sprite2D

func _ready():
    print("Child sprite ready!")
"""
        child_script_path = temp_godot_project / "child_script.gd"
        child_script_path.write_text(child_script_content, encoding="utf-8")

        # Attach script to the child node
        result = script_attach(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            node_path="root/MySprite",
            script_path="child_script.gd",
        )

        assert "successfully" in result.lower() or "attached" in result.lower(), (
            f"script_attach to child failed: {result}"
        )

        # Verify the script reference is in the scene
        scene_file = temp_godot_project / scene_path
        scene_content = scene_file.read_text(encoding="utf-8")
        assert "child_script.gd" in scene_content, (
            f"Child script reference not found. Content:\n{scene_content}"
        )
