"""Tests for event tools."""

import pytest
from unittest.mock import MagicMock, patch, AsyncMock

from gmeet_mcp_server.tools.events import register_event_tools
from gmeet_mcp_server.client import GMeetClient, CalendarAPIError, CalendarAuthError


class TestEventTools:
    """Tests for gmeet event tools."""

    @pytest.fixture
    def app_with_tools(self, mock_config):
        """Create a mock FastMCP app with event tools registered."""
        app = MagicMock()
        tools = {}

        def mock_tool():
            def decorator(func):
                tools[func.__name__] = func
                return func
            return decorator

        app.tool = mock_tool
        register_event_tools(app, mock_config)
        return tools

    @pytest.mark.asyncio
    async def test_gmeet_list_events_success(self, app_with_tools, sample_event):
        with patch.object(GMeetClient, "__init__", return_value=None), \
             patch.object(GMeetClient, "list_events", return_value=[
                 GMeetClient._format_event(sample_event)
             ]):
            result = await app_with_tools["gmeet_list_events"](max_results=5)
            assert result["success"] is True
            assert result["count"] == 1

    @pytest.mark.asyncio
    async def test_gmeet_list_events_auth_error(self, app_with_tools):
        with patch.object(GMeetClient, "__init__", return_value=None), \
             patch.object(GMeetClient, "list_events", side_effect=CalendarAuthError("Token expired")):
            result = await app_with_tools["gmeet_list_events"]()
            assert "error" in result
            assert "Authentication failed" in result["error"]

    @pytest.mark.asyncio
    async def test_gmeet_get_event_success(self, app_with_tools, sample_event):
        formatted = GMeetClient._format_event(sample_event)
        with patch.object(GMeetClient, "__init__", return_value=None), \
             patch.object(GMeetClient, "get_event", return_value=formatted):
            result = await app_with_tools["gmeet_get_event"](event_id="test_event_123")
            assert result["success"] is True
            assert result["event_id"] == "test_event_123"

    @pytest.mark.asyncio
    async def test_gmeet_delete_event_success(self, app_with_tools):
        with patch.object(GMeetClient, "__init__", return_value=None), \
             patch.object(GMeetClient, "delete_event", return_value={
                 "event_id": "test_event_123", "status": "deleted"
             }):
            result = await app_with_tools["gmeet_delete_event"](event_id="test_event_123")
            assert result["success"] is True
            assert result["action"] == "deleted"

    @pytest.mark.asyncio
    async def test_gmeet_update_event_success(self, app_with_tools, sample_event):
        formatted = GMeetClient._format_event(sample_event)
        with patch.object(GMeetClient, "__init__", return_value=None), \
             patch.object(GMeetClient, "update_event", return_value=formatted):
            result = await app_with_tools["gmeet_update_event"](
                event_id="test_event_123",
                updates_json='{"title": "Updated Title"}',
            )
            assert result["success"] is True
            assert result["action"] == "updated"

    @pytest.mark.asyncio
    async def test_gmeet_update_event_invalid_json(self, app_with_tools):
        result = await app_with_tools["gmeet_update_event"](
            event_id="test_event_123",
            updates_json="not valid json",
        )
        assert "error" in result
        assert "Invalid JSON" in result["error"]

    @pytest.mark.asyncio
    async def test_gmeet_update_event_empty_updates(self, app_with_tools):
        result = await app_with_tools["gmeet_update_event"](
            event_id="test_event_123",
            updates_json="",
        )
        assert "error" in result
        assert "No updates provided" in result["error"]

    @pytest.mark.asyncio
    async def test_gmeet_create_event_success(self, app_with_tools, sample_event_no_meet):
        formatted = GMeetClient._format_event(sample_event_no_meet)
        with patch.object(GMeetClient, "__init__", return_value=None), \
             patch.object(GMeetClient, "create_event", return_value=formatted):
            result = await app_with_tools["gmeet_create_event"](
                title="Lunch",
                start_time="2025-06-20T12:00:00-07:00",
            )
            assert result["success"] is True

    @pytest.mark.asyncio
    async def test_gmeet_list_events_api_error(self, app_with_tools):
        with patch.object(GMeetClient, "__init__", return_value=None), \
             patch.object(GMeetClient, "list_events", side_effect=CalendarAPIError("API down", 500)):
            result = await app_with_tools["gmeet_list_events"]()
            assert "error" in result
            assert "Calendar API error" in result["error"]
