"""Authentication models for token caching and status tracking."""

from datetime import datetime, timezone
from enum import Enum
from typing import Optional

from pydantic import BaseModel, ConfigDict


class AuthStatusType(str, Enum):
    """Authentication status states.

    Attributes:
        AUTHENTICATED: Successfully authenticated with valid token.
        UNAUTHENTICATED: No valid authentication (requires login).
        EXPIRED: Token has expired (requires refresh or re-authentication).
    """

    AUTHENTICATED = "authenticated"
    UNAUTHENTICATED = "unauthenticated"
    EXPIRED = "expired"


class CachedToken(BaseModel):
    """Cached authentication token for a tenant.

    Stores the access token and expiration timestamp for token caching.
    MSAL handles refresh tokens internally, so only access token is stored.

    Attributes:
        access_token: The OAuth 2.0 access token string.
        expires_at: UTC datetime when the token expires.
        tenant_id: The tenant ID this token is associated with.
        scopes: List of scopes granted to this token.
    """

    model_config = ConfigDict(extra="forbid")

    access_token: str
    expires_at: datetime
    tenant_id: str
    scopes: list[str]

    def is_expired(self) -> bool:
        """Check if the token has expired.

        Returns:
            True if current time is past expiration, False otherwise.
        """
        now = datetime.now(timezone.utc)
        expires = self.expires_at
        # Handle both naive and aware datetimes for comparison
        if expires.tzinfo is None:
            expires = expires.replace(tzinfo=timezone.utc)
        return now >= expires


class AuthStatus(BaseModel):
    """Current authentication status for a tenant.

    Tracks the authentication state and provides context about
    the current session.

    Attributes:
        status: Current authentication state.
        tenant_name: Profile name of the authenticated tenant.
        tenant_id: Tenant ID if authenticated.
        expires_at: Token expiration time if authenticated.
        error_message: Error details if authentication failed.
    """

    model_config = ConfigDict(extra="forbid")

    status: AuthStatusType
    tenant_name: Optional[str] = None
    tenant_id: Optional[str] = None
    expires_at: Optional[datetime] = None
    error_message: Optional[str] = None


class ConnectionTestResult(BaseModel):
    """Result of a tenant connection test.

    Contains the outcome of testing connectivity to Microsoft Graph API
    for a given tenant, including latency measurement and permission info.

    Attributes:
        success: Whether the connection test succeeded.
        tenant_name: Name of the tenant that was tested.
        latency_ms: Round-trip latency in milliseconds (None if failed before API call).
        permissions: List of application permissions (scopes) available.
        error_message: Error details if the test failed.
    """

    model_config = ConfigDict(extra="forbid")

    success: bool
    tenant_name: str
    latency_ms: Optional[int] = None
    permissions: list[str] = []
    error_message: Optional[str] = None
