"""Tests for MCP tools.

Generated by GRIMLOCK MCP Factory
"""

import json

import httpx
import pytest
import respx

from loom_mcp.tools.list_recorded_videos import list_recorded_videos
from loom_mcp.tools.get_video import get_video
from loom_mcp.tools.edit_video import edit_video
from loom_mcp.tools.merge_videos import merge_videos


class TestListRecordedVideosTool:
    """Tests for list_recorded_videos tool."""

    @pytest.mark.asyncio
    async def test_list_videos_success(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
        sample_videos_response: dict,
    ) -> None:
        """Test successful video listing."""
        mock_httpx_client.get("https://api.loom.com/v1/videos").mock(
            return_value=httpx.Response(200, json=sample_videos_response)
        )

        result = await list_recorded_videos({})
        content = json.loads(result[0].text)

        assert content["success"] is True
        assert content["total_videos"] == 3
        assert len(content["videos"]) == 3

    @pytest.mark.asyncio
    async def test_list_videos_with_limit(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
        sample_videos_response: dict,
    ) -> None:
        """Test video listing with limit parameter."""
        mock_httpx_client.get("https://api.loom.com/v1/videos").mock(
            return_value=httpx.Response(200, json=sample_videos_response)
        )

        result = await list_recorded_videos({"limit": 10})
        content = json.loads(result[0].text)

        assert content["success"] is True

    @pytest.mark.asyncio
    async def test_list_videos_with_offset(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
        sample_videos_response: dict,
    ) -> None:
        """Test video listing with offset parameter."""
        mock_httpx_client.get("https://api.loom.com/v1/videos").mock(
            return_value=httpx.Response(200, json=sample_videos_response)
        )

        result = await list_recorded_videos({"offset": 20})
        content = json.loads(result[0].text)

        assert content["success"] is True
        assert content["offset"] == 20

    @pytest.mark.asyncio
    async def test_list_videos_with_folder_id(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
        sample_videos_response: dict,
    ) -> None:
        """Test video listing with folder filter."""
        mock_httpx_client.get("https://api.loom.com/v1/videos").mock(
            return_value=httpx.Response(200, json=sample_videos_response)
        )

        result = await list_recorded_videos({"folder_id": "folder-abc"})
        content = json.loads(result[0].text)

        assert content["success"] is True

    @pytest.mark.asyncio
    async def test_list_videos_auth_error(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
    ) -> None:
        """Test authentication error handling."""
        mock_httpx_client.get("https://api.loom.com/v1/videos").mock(
            return_value=httpx.Response(401, json={"error": "Unauthorized"})
        )

        result = await list_recorded_videos({})
        content = json.loads(result[0].text)

        assert content["error"] is True
        assert content["code"] == "AUTH_FAILED"

    @pytest.mark.asyncio
    async def test_list_videos_forbidden_error(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
    ) -> None:
        """Test forbidden error handling."""
        mock_httpx_client.get("https://api.loom.com/v1/videos").mock(
            return_value=httpx.Response(403, json={"error": "Forbidden"})
        )

        result = await list_recorded_videos({})
        content = json.loads(result[0].text)

        assert content["error"] is True
        assert content["code"] == "FORBIDDEN"

    @pytest.mark.asyncio
    async def test_list_videos_rate_limit_error(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
    ) -> None:
        """Test rate limit error handling."""
        mock_httpx_client.get("https://api.loom.com/v1/videos").mock(
            return_value=httpx.Response(429, json={"error": "Rate limited"})
        )

        result = await list_recorded_videos({})
        content = json.loads(result[0].text)

        assert content["error"] is True
        assert content["code"] == "RATE_LIMITED"


class TestGetVideoTool:
    """Tests for get_video tool."""

    @pytest.mark.asyncio
    async def test_get_video_success(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
        sample_video_detail_response: dict,
    ) -> None:
        """Test successful video retrieval."""
        mock_httpx_client.get("https://api.loom.com/v1/videos/video-123").mock(
            return_value=httpx.Response(200, json=sample_video_detail_response)
        )

        result = await get_video({"video_id": "video-123"})
        content = json.loads(result[0].text)

        assert content["success"] is True
        assert content["video"]["id"] == "video-123"
        assert content["video"]["title"] == "Product Demo"

    @pytest.mark.asyncio
    async def test_get_video_not_found(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
    ) -> None:
        """Test video not found error."""
        mock_httpx_client.get("https://api.loom.com/v1/videos/nonexistent").mock(
            return_value=httpx.Response(404, json={"error": "Not found"})
        )

        result = await get_video({"video_id": "nonexistent"})
        content = json.loads(result[0].text)

        assert content["error"] is True
        assert content["code"] == "NOT_FOUND"

    @pytest.mark.asyncio
    async def test_get_video_auth_error(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
    ) -> None:
        """Test authentication error."""
        mock_httpx_client.get("https://api.loom.com/v1/videos/video-123").mock(
            return_value=httpx.Response(401, json={"error": "Unauthorized"})
        )

        result = await get_video({"video_id": "video-123"})
        content = json.loads(result[0].text)

        assert content["error"] is True
        assert content["code"] == "AUTH_FAILED"

    @pytest.mark.asyncio
    async def test_get_video_missing_id(
        self,
        mock_env: None,
    ) -> None:
        """Test error when video_id is missing."""
        result = await get_video({})
        content = json.loads(result[0].text)

        assert content["error"] is True


class TestEditVideoTool:
    """Tests for edit_video tool."""

    @pytest.mark.asyncio
    async def test_edit_video_trim_success(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
        sample_edit_response: dict,
    ) -> None:
        """Test successful video trimming."""
        mock_httpx_client.post("https://api.loom.com/v1/videos/video-123/edit").mock(
            return_value=httpx.Response(200, json=sample_edit_response)
        )

        result = await edit_video({
            "video_id": "video-123",
            "editing_details": {"trim_start": 5, "trim_end": 100},
        })
        content = json.loads(result[0].text)

        assert content["success"] is True
        assert content["video_id"] == "video-123"

    @pytest.mark.asyncio
    async def test_edit_video_with_clips(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
        sample_edit_response: dict,
    ) -> None:
        """Test video editing with clips."""
        mock_httpx_client.post("https://api.loom.com/v1/videos/video-123/edit").mock(
            return_value=httpx.Response(200, json=sample_edit_response)
        )

        result = await edit_video({
            "video_id": "video-123",
            "editing_details": {
                "clips": [
                    {"start": 0, "end": 30},
                    {"start": 60, "end": 90},
                ],
            },
        })
        content = json.loads(result[0].text)

        assert content["success"] is True

    @pytest.mark.asyncio
    async def test_edit_video_invalid_parameter(
        self,
        mock_env: None,
    ) -> None:
        """Test error for invalid editing parameter."""
        result = await edit_video({
            "video_id": "video-123",
            "editing_details": {"invalid_param": "value"},
        })
        content = json.loads(result[0].text)

        assert content["error"] is True
        assert content["code"] == "INVALID_PARAMETERS"

    @pytest.mark.asyncio
    async def test_edit_video_invalid_clips_format(
        self,
        mock_env: None,
    ) -> None:
        """Test error for invalid clips format."""
        result = await edit_video({
            "video_id": "video-123",
            "editing_details": {"clips": "not-a-list"},
        })
        content = json.loads(result[0].text)

        assert content["error"] is True
        assert content["code"] == "INVALID_PARAMETERS"

    @pytest.mark.asyncio
    async def test_edit_video_clips_missing_times(
        self,
        mock_env: None,
    ) -> None:
        """Test error for clips missing start/end times."""
        result = await edit_video({
            "video_id": "video-123",
            "editing_details": {"clips": [{"start": 0}]},
        })
        content = json.loads(result[0].text)

        assert content["error"] is True
        assert content["code"] == "INVALID_PARAMETERS"

    @pytest.mark.asyncio
    async def test_edit_video_not_found(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
    ) -> None:
        """Test video not found error."""
        mock_httpx_client.post("https://api.loom.com/v1/videos/nonexistent/edit").mock(
            return_value=httpx.Response(404, json={"error": "Not found"})
        )

        result = await edit_video({
            "video_id": "nonexistent",
            "editing_details": {"trim_start": 5},
        })
        content = json.loads(result[0].text)

        assert content["error"] is True
        assert content["code"] == "NOT_FOUND"


class TestMergeVideosTool:
    """Tests for merge_videos tool."""

    @pytest.mark.asyncio
    async def test_merge_videos_success(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
        sample_merge_response: dict,
    ) -> None:
        """Test successful video merge."""
        mock_httpx_client.post("https://api.loom.com/v1/videos/merge").mock(
            return_value=httpx.Response(200, json=sample_merge_response)
        )

        result = await merge_videos({
            "video_ids": ["video-123", "video-456"],
            "title": "Merged Video",
        })
        content = json.loads(result[0].text)

        assert content["success"] is True
        assert content["source_videos"] == ["video-123", "video-456"]

    @pytest.mark.asyncio
    async def test_merge_videos_without_title(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
        sample_merge_response: dict,
    ) -> None:
        """Test video merge without custom title."""
        mock_httpx_client.post("https://api.loom.com/v1/videos/merge").mock(
            return_value=httpx.Response(200, json=sample_merge_response)
        )

        result = await merge_videos({
            "video_ids": ["video-123", "video-456"],
        })
        content = json.loads(result[0].text)

        assert content["success"] is True

    @pytest.mark.asyncio
    async def test_merge_videos_insufficient_videos(
        self,
        mock_env: None,
    ) -> None:
        """Test error when less than 2 videos provided."""
        result = await merge_videos({
            "video_ids": ["video-123"],
        })
        content = json.loads(result[0].text)

        assert content["error"] is True

    @pytest.mark.asyncio
    async def test_merge_videos_empty_video_id(
        self,
        mock_env: None,
    ) -> None:
        """Test error when video ID is empty."""
        result = await merge_videos({
            "video_ids": ["video-123", ""],
        })
        content = json.loads(result[0].text)

        assert content["error"] is True
        assert content["code"] == "INVALID_PARAMETERS"

    @pytest.mark.asyncio
    async def test_merge_videos_duplicate_ids(
        self,
        mock_env: None,
    ) -> None:
        """Test error when duplicate video IDs provided."""
        result = await merge_videos({
            "video_ids": ["video-123", "video-456", "video-123"],
        })
        content = json.loads(result[0].text)

        assert content["error"] is True
        assert content["code"] == "INVALID_PARAMETERS"

    @pytest.mark.asyncio
    async def test_merge_videos_not_found(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
    ) -> None:
        """Test video not found error."""
        mock_httpx_client.post("https://api.loom.com/v1/videos/merge").mock(
            return_value=httpx.Response(404, json={"error": "Video not found"})
        )

        result = await merge_videos({
            "video_ids": ["video-123", "nonexistent"],
        })
        content = json.loads(result[0].text)

        assert content["error"] is True
        assert content["code"] == "NOT_FOUND"

    @pytest.mark.asyncio
    async def test_merge_videos_auth_error(
        self,
        mock_env: None,
        mock_httpx_client: respx.MockRouter,
    ) -> None:
        """Test authentication error."""
        mock_httpx_client.post("https://api.loom.com/v1/videos/merge").mock(
            return_value=httpx.Response(401, json={"error": "Unauthorized"})
        )

        result = await merge_videos({
            "video_ids": ["video-123", "video-456"],
        })
        content = json.loads(result[0].text)

        assert content["error"] is True
        assert content["code"] == "AUTH_FAILED"
