"""Tests for GMeetClient."""

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

from gmeet_mcp_server.client import GMeetClient, CalendarClient, CalendarAPIError, CalendarAuthError


class TestGMeetClientInit:
    """Tests for GMeetClient initialization."""

    def test_requires_client_id(self):
        with pytest.raises(CalendarAuthError, match="client_id is required"):
            GMeetClient(client_id="", client_secret="secret", refresh_token="token")

    def test_requires_client_secret(self):
        with pytest.raises(CalendarAuthError, match="client_secret is required"):
            GMeetClient(client_id="id", client_secret="", refresh_token="token")

    def test_requires_refresh_token(self):
        with pytest.raises(CalendarAuthError, match="refresh_token is required"):
            GMeetClient(client_id="id", client_secret="secret", refresh_token="")

    @patch("gmeet_mcp_server.client.build")
    def test_valid_init(self, mock_build):
        client = GMeetClient(
            client_id="fake-id",
            client_secret="fake-secret",
            refresh_token="fake-token",
        )
        assert client._calendar_service is None
        assert client._meet_service is None
        assert client._drive_service is None

    def test_backward_compat_alias(self):
        assert CalendarClient is GMeetClient


class TestFormatEvent:
    """Tests for GMeetClient._format_event static method."""

    def test_format_event_with_meet(self, sample_event):
        result = GMeetClient._format_event(sample_event)
        assert result["event_id"] == "test_event_123"
        assert result["title"] == "Team Standup"
        assert result["meet_url"] == "https://meet.google.com/abc-defg-hij"
        assert result["start"] == "2025-06-20T10:00:00-07:00"
        assert result["end"] == "2025-06-20T10:30:00-07:00"
        assert len(result["attendees"]) == 2
        assert result["attendees"][0]["email"] == "alice@example.com"
        assert result["organizer"] == "alice@example.com"

    def test_format_event_without_meet(self, sample_event_no_meet):
        result = GMeetClient._format_event(sample_event_no_meet)
        assert result["event_id"] == "test_event_456"
        assert result["meet_url"] == ""
        assert result["title"] == "Lunch Break"

    def test_format_event_minimal(self):
        minimal = {"id": "min1", "start": {}, "end": {}}
        result = GMeetClient._format_event(minimal)
        assert result["event_id"] == "min1"
        assert result["title"] == ""
        assert result["meet_url"] == ""
        assert result["attendees"] == []


class TestExtractMeetUrl:
    """Tests for GMeetClient._extract_meet_url static method."""

    def test_extracts_video_url(self):
        event = {
            "conferenceData": {
                "entryPoints": [
                    {"entryPointType": "phone", "uri": "tel:+1234567890"},
                    {"entryPointType": "video", "uri": "https://meet.google.com/xyz"},
                ]
            }
        }
        assert GMeetClient._extract_meet_url(event) == "https://meet.google.com/xyz"

    def test_no_conference_data(self):
        assert GMeetClient._extract_meet_url({}) == ""

    def test_no_video_entry_point(self):
        event = {
            "conferenceData": {
                "entryPoints": [
                    {"entryPointType": "phone", "uri": "tel:+1234567890"},
                ]
            }
        }
        assert GMeetClient._extract_meet_url(event) == ""


class TestGMeetClientMethods:
    """Tests for GMeetClient API methods using mocked service."""

    @patch("gmeet_mcp_server.client.build")
    def test_list_events(self, mock_build, sample_event):
        mock_service = MagicMock()
        mock_build.return_value = mock_service
        mock_service.events().list().execute.return_value = {
            "items": [sample_event]
        }

        client = GMeetClient(
            client_id="fake-id",
            client_secret="fake-secret",
            refresh_token="fake-token",
        )
        events = client.list_events(max_results=5)
        assert len(events) == 1
        assert events[0]["event_id"] == "test_event_123"

    @patch("gmeet_mcp_server.client.build")
    def test_get_event(self, mock_build, sample_event):
        mock_service = MagicMock()
        mock_build.return_value = mock_service
        mock_service.events().get().execute.return_value = sample_event

        client = GMeetClient(
            client_id="fake-id",
            client_secret="fake-secret",
            refresh_token="fake-token",
        )
        result = client.get_event("test_event_123")
        assert result["event_id"] == "test_event_123"
        assert result["meet_url"] == "https://meet.google.com/abc-defg-hij"

    @patch("gmeet_mcp_server.client.build")
    def test_delete_event(self, mock_build):
        mock_service = MagicMock()
        mock_build.return_value = mock_service
        mock_service.events().delete().execute.return_value = None

        client = GMeetClient(
            client_id="fake-id",
            client_secret="fake-secret",
            refresh_token="fake-token",
        )
        result = client.delete_event("test_event_123")
        assert result["event_id"] == "test_event_123"
        assert result["status"] == "deleted"

    @patch("gmeet_mcp_server.client.build")
    def test_list_calendars(self, mock_build):
        mock_service = MagicMock()
        mock_build.return_value = mock_service
        mock_service.calendarList().list().execute.return_value = {
            "items": [
                {
                    "id": "primary",
                    "summary": "My Calendar",
                    "description": "",
                    "primary": True,
                    "accessRole": "owner",
                    "timeZone": "America/Los_Angeles",
                }
            ]
        }

        client = GMeetClient(
            client_id="fake-id",
            client_secret="fake-secret",
            refresh_token="fake-token",
        )
        calendars = client.list_calendars()
        assert len(calendars) == 1
        assert calendars[0]["calendar_id"] == "primary"
        assert calendars[0]["primary"] is True
