"""
E2E tests for basic MCP tools functionality.

Tests the fundamental tools using real Godot demo projects:
- godot_get_version
- project_list
- project_get_info
- launch_editor (command construction only)
- run_project (command construction only)
- project_stop
- project_get_debug_output
"""

import json
from pathlib import Path

import pytest

from godot_mcp.server import (
    GodotServer,
    project_get_debug_output,
    godot_get_version,
    project_get_info,
    godot_server,
    project_list,
    project_stop,
)


class TestGetGodotVersion:
    """E2E tests for godot_get_version tool."""

    def test_godot_get_version_returns_valid_version(self) -> None:
        """Test that godot_get_version returns a valid version string."""
        result = godot_get_version()

        # Should return a version string containing a number
        assert isinstance(result, str)
        # Godot version format is typically "4.x.x" or similar
        # If Godot is not installed, it should return an error message
        if "error" not in result.lower():
            # Version should contain at least one digit
            assert any(char.isdigit() for char in result)


class TestListProjects:
    """E2E tests for project_list tool."""

    def test_project_list_in_demo_repo(self, godot_demo_projects: Path) -> None:
        """Test listing Godot projects in the demo repository."""
        result = project_list(str(godot_demo_projects), recursive=True)

        # Should return valid JSON
        data = json.loads(result)

        # Should find multiple projects
        assert len(data) > 0, "Expected to find multiple demo projects"

        # Each project should have required fields
        for project in data:
            assert "name" in project
            assert "path" in project

    def test_project_list_non_recursive(self, godot_demo_projects: Path) -> None:
        """Test listing projects without recursion."""
        result = project_list(str(godot_demo_projects), recursive=False)

        data = json.loads(result)
        # Non-recursive search in root may find nothing (projects are in subdirs)
        assert isinstance(data, list)

    def test_project_list_in_2d_folder(self, godot_demo_projects: Path) -> None:
        """Test listing projects in the 2d demos folder."""
        twod_path = godot_demo_projects / "2d"
        if not twod_path.exists():
            pytest.skip("2d folder not found in demo projects")

        result = project_list(str(twod_path), recursive=True)
        data = json.loads(result)

        # Should find 2D demo projects
        assert len(data) > 0, "Expected to find 2D demo projects"


class TestGetProjectInfo:
    """E2E tests for project_get_info tool."""

    def test_project_get_info_on_demo(self, any_demo_project: Path) -> None:
        """Test getting project info from a real demo project."""
        result = project_get_info(str(any_demo_project))

        # Should return valid JSON
        data = json.loads(result)

        # Check basic structure
        assert "name" in data
        assert "path" in data
        assert "structure" in data

        # Name should not be empty
        assert data["name"], "Project name should not be empty"

        # Path should match
        assert data["path"] == str(any_demo_project)

    def test_project_get_info_2d_platformer(self, demo_2d_platformer: Path) -> None:
        """Test getting project info from the 2D Platformer demo."""
        result = project_get_info(str(demo_2d_platformer))

        data = json.loads(result)

        # Should have scenes in structure
        assert "structure" in data
        structure = data["structure"]

        # Check for typical project elements
        assert "total_scenes" in structure or "scenes" in structure

    def test_project_get_info_3d_platformer(self, demo_3d_platformer: Path) -> None:
        """Test getting project info from the 3D Platformer demo."""
        result = project_get_info(str(demo_3d_platformer))

        data = json.loads(result)
        assert "name" in data
        assert "structure" in data

    def test_project_get_info_contains_scenes(self, any_demo_project: Path) -> None:
        """Test that project info includes scene information."""
        result = project_get_info(str(any_demo_project))
        data = json.loads(result)

        # Demo projects should have scenes
        structure = data.get("structure", {})
        # Either has scenes listed or scene count
        has_scene_info = (
            "scenes" in structure
            or "total_scenes" in structure
            or any("scene" in str(v).lower() for v in structure.values())
        )
        assert has_scene_info or structure, "Project should have structure info"


class TestStopProject:
    """E2E tests for project_stop tool."""

    def test_project_stop_when_nothing_running(self) -> None:
        """Test project_stop when no project is running."""
        result = project_stop()

        # Should handle gracefully
        assert isinstance(result, str)
        # Should indicate nothing to stop or success
        assert "no" in result.lower() or "stop" in result.lower()


class TestGetDebugOutput:
    """E2E tests for project_get_debug_output tool."""

    def test_project_get_debug_output_returns_string(self) -> None:
        """Test that project_get_debug_output returns a string."""
        result = project_get_debug_output()

        assert isinstance(result, str)
        # May be empty if no project is running


class TestGodotServerWithDemo:
    """E2E tests for GodotServer class using demo projects."""

    def test_server_instance(self) -> None:
        """Test that we can get a GodotServer instance."""
        assert godot_server is not None
        assert isinstance(godot_server, GodotServer)

    def test_normalize_parameters_with_demo_paths(self, any_demo_project: Path) -> None:
        """Test parameter normalization with real project paths."""
        params = {
            "projectPath": str(any_demo_project),
            "scenePath": "main.tscn",
            "nodeType": "Node2D",
        }
        result = godot_server.normalize_parameters(params)

        assert result["project_path"] == str(any_demo_project)
        assert result["scene_path"] == "main.tscn"
        assert result["node_type"] == "Node2D"
