"""Calendar integration port interfaces.

Defines protocols for OAuth operations and calendar event fetching.
Implementations live in infrastructure/calendar/.
"""

from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime
from typing import TYPE_CHECKING, Protocol

if TYPE_CHECKING:
    from noteflow.domain.value_objects import OAuthProvider, OAuthTokens


@dataclass(frozen=True, slots=True)
class CalendarEventInfo:
    """Calendar event information from provider API.

    Richer than trigger-layer CalendarEvent, used for API responses
    and caching in CalendarEventModel.
    """

    id: str
    title: str
    start_time: datetime
    end_time: datetime
    attendees: tuple[str, ...]
    location: str | None = None
    description: str | None = None
    meeting_url: str | None = None
    is_recurring: bool = False
    is_all_day: bool = False
    provider: str = ""
    raw: dict[str, object] | None = None


@dataclass(frozen=True, slots=True)
class OAuthConnectionInfo:
    """OAuth connection status for a provider."""

    provider: str
    status: str  # "connected", "disconnected", "error", "expired"
    email: str | None = None
    expires_at: datetime | None = None
    error_message: str | None = None


class OAuthPort(Protocol):
    """Port for OAuth operations.

    Handles PKCE flow for Google and Outlook calendar providers.
    """

    def initiate_auth(
        self,
        provider: OAuthProvider,
        redirect_uri: str,
    ) -> tuple[str, str]:
        """Generate OAuth authorization URL with PKCE.

        Args:
            provider: OAuth provider (google or outlook).
            redirect_uri: Callback URL after authorization.

        Returns:
            Tuple of (authorization_url, state_token).
        """
        ...

    async def complete_auth(
        self,
        provider: OAuthProvider,
        code: str,
        state: str,
    ) -> OAuthTokens:
        """Exchange authorization code for tokens.

        Args:
            provider: OAuth provider.
            code: Authorization code from callback.
            state: State parameter from callback.

        Returns:
            OAuth tokens.

        Raises:
            ValueError: If state doesn't match or code exchange fails.
        """
        ...

    async def refresh_tokens(
        self,
        provider: OAuthProvider,
        refresh_token: str,
    ) -> OAuthTokens:
        """Refresh expired access token.

        Args:
            provider: OAuth provider.
            refresh_token: Refresh token from previous exchange.

        Returns:
            New OAuth tokens.

        Raises:
            ValueError: If refresh fails.
        """
        ...

    async def revoke_tokens(
        self,
        provider: OAuthProvider,
        access_token: str,
    ) -> bool:
        """Revoke OAuth tokens with provider.

        Args:
            provider: OAuth provider.
            access_token: Access token to revoke.

        Returns:
            True if revoked successfully.
        """
        ...


class CalendarPort(Protocol):
    """Port for calendar event operations.

    Each provider (Google, Outlook) implements this protocol.
    """

    async def list_events(
        self,
        access_token: str,
        hours_ahead: int = 24,
        limit: int = 20,
    ) -> list[CalendarEventInfo]:
        """Fetch upcoming calendar events.

        Args:
            access_token: Provider OAuth access token.
            hours_ahead: Hours to look ahead.
            limit: Maximum number of events.

        Returns:
            Calendar events sorted chronologically.

        Raises:
            ValueError: If token is invalid or API call fails.
        """
        ...

    async def get_user_email(self, access_token: str) -> str:
        """Get authenticated user's email address.

        Args:
            access_token: Valid OAuth access token.

        Returns:
            User's email address.

        Raises:
            ValueError: If token is invalid or API call fails.
        """
        ...
