"""Tests for animation operations."""

import json
from pathlib import Path

import pytest

from godot_mcp.server import (
    animation_create,
    animation_add_track,
    animation_set_keyframe,
    animation_get_info,
    animation_list,
    scene_create,
)


class TestAnimationCreate:
    """Test cases for the animation_create tool."""

    def test_create_basic_animation(
        self, temp_godot_project: Path
    ) -> None:
        """Test creating a basic animation in a scene."""
        # First create a test scene
        scene_path = "test_scene.tscn"
        scene_result = scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            root_node_type="Node2D",
        )
        assert "successfully" in scene_result.lower()

        # Now create an animation
        result = animation_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            animation_name="test_animation",
        )

        assert "successfully" in result.lower()
        assert "test_animation" in result

    def test_create_looping_animation(
        self, temp_godot_project: Path
    ) -> None:
        """Test creating a looping animation with custom duration."""
        # Create test scene
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            root_node_type="Node2D",
        )

        # Create looping animation
        result = animation_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            animation_name="loop_animation",
            duration=2.5,
            loop=True,
        )

        assert "successfully" in result.lower()
        assert "2.5" in result

    def test_animation_create_invalid_project(self) -> None:
        """Test error handling for invalid project path."""
        result = animation_create(
            project_path="/nonexistent/path",
            scene_path="test.tscn",
            animation_name="test",
        )

        assert "Not a valid Godot project" in result

    def test_animation_create_invalid_scene(
        self, temp_godot_project: Path
    ) -> None:
        """Test error handling for non-existent scene."""
        result = animation_create(
            project_path=str(temp_godot_project),
            scene_path="nonexistent.tscn",
            animation_name="test",
        )

        assert "does not exist" in result

    def test_animation_create_missing_params(self) -> None:
        """Test error handling for missing required parameters."""
        result = animation_create(
            project_path="",
            scene_path="",
            animation_name="",
        )

        assert "Missing required parameters" in result


class TestAnimationAddTrack:
    """Test cases for the animation_add_track tool."""

    def test_add_value_track(
        self, temp_godot_project: Path
    ) -> None:
        """Test adding a value track to an animation."""
        # Setup: create scene and animation
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            root_node_type="Node2D",
        )
        animation_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            animation_name="test_anim",
        )

        # Add track
        result = animation_add_track(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            animation_name="test_anim",
            track_type="value",
            track_path=".:position",
        )

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

    def test_add_track_invalid_type(
        self, temp_godot_project: Path
    ) -> None:
        """Test error handling for invalid track type."""
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
        )
        animation_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            animation_name="test_anim",
        )

        result = animation_add_track(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            animation_name="test_anim",
            track_type="invalid_type",
            track_path=".:position",
        )

        assert "Invalid track type" in result


class TestAnimationList:
    """Test cases for the animation_list tool."""

    def test_list_animations_empty(
        self, temp_godot_project: Path
    ) -> None:
        """Test listing animations in a scene with no AnimationPlayer."""
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
        )

        result = animation_list(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
        )

        # Should return valid JSON even if empty
        data = json.loads(result)
        assert "animations" in data
        assert isinstance(data["animations"], list)

    def test_list_animations_with_data(
        self, temp_godot_project: Path
    ) -> None:
        """Test listing animations in a scene with animations."""
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
        )

        # Create two animations
        animation_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            animation_name="anim1",
            duration=1.0,
        )
        animation_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            animation_name="anim2",
            duration=2.0,
        )

        result = animation_list(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
        )

        data = json.loads(result)
        assert len(data["animations"]) == 2
        animation_names = [anim["name"] for anim in data["animations"]]
        assert "anim1" in animation_names
        assert "anim2" in animation_names


class TestAnimationGetInfo:
    """Test cases for the animation_get_info tool."""

    def test_get_animation_info(
        self, temp_godot_project: Path
    ) -> None:
        """Test getting information about an animation."""
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
        )
        animation_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            animation_name="test_anim",
            duration=3.5,
            loop=True,
        )

        result = animation_get_info(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            animation_name="test_anim",
        )

        data = json.loads(result)
        assert data["name"] == "test_anim"
        assert data["length"] == 3.5
        assert data["loop_mode"] == "linear"
        assert "tracks" in data

    def test_get_info_nonexistent_animation(
        self, temp_godot_project: Path
    ) -> None:
        """Test error handling for nonexistent animation."""
        scene_path = "test_scene.tscn"
        scene_create(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
        )

        result = animation_get_info(
            project_path=str(temp_godot_project),
            scene_path=scene_path,
            animation_name="nonexistent",
        )

        assert "not found" in result.lower() or "error" in result.lower()
