"""
Authentication API contracts.

Pydantic schemas for authentication endpoints used by:
- Phoenix WebSocket authentication (token verification)
- Service-to-service authentication
- Frontend session state (TanStack Start)

SST Reference: definitions/communication/websockets/config.yaml

Session API (GET /v1/auth/session/):
    Returns current authentication state for frontend header/nav display.
    Uses camelCase field names to match TypeScript types.
"""

from pydantic import BaseModel, ConfigDict, Field

# =============================================================================
# Session API Schemas (camelCase for TypeScript frontend)
# =============================================================================


class LinkedAccountSchema(BaseModel):
    """Social account link info for OAuth providers."""

    model_config = ConfigDict(
        strict=True,
        extra="forbid",
        populate_by_name=True,
    )

    provider: str = Field(..., description="OAuth provider name (google, github, etc.)")
    providerAccountId: str = Field(..., description="Provider-specific account ID")
    email: str | None = Field(default=None, description="Email from provider")


class AuthUserSchema(BaseModel):
    """
    User info for session response.

    Uses camelCase to match TypeScript AuthUser interface.
    All fields optional except id and email for flexibility.
    """

    model_config = ConfigDict(
        strict=True,
        extra="forbid",
        populate_by_name=True,
    )

    id: str = Field(..., description="User UUID as string")
    email: str = Field(..., description="User's email address")
    username: str | None = Field(default=None, description="Username if different from email")
    firstName: str | None = Field(default=None, description="First name")
    lastName: str | None = Field(default=None, description="Last name")
    displayName: str | None = Field(default=None, description="Display name for UI")
    avatarUrl: str | None = Field(default=None, description="Avatar image URL")
    initials: str | None = Field(default=None, description="Initials for avatar fallback")
    isAdmin: bool = Field(default=False, description="Is superuser")
    isStaff: bool = Field(default=False, description="Is staff member")
    emailVerified: bool = Field(default=False, description="Email verification status")
    provider: str | None = Field(default=None, description="Primary OAuth provider if any")
    linkedAccounts: list[LinkedAccountSchema] = Field(default_factory=list, description="Linked OAuth accounts")
    createdAt: str | None = Field(default=None, description="Account creation timestamp (ISO 8601)")
    lastLogin: str | None = Field(default=None, description="Last login timestamp (ISO 8601)")


class AuthSessionSchema(BaseModel):
    """
    Session state response for GET /v1/auth/session/.

    Uses camelCase to match TypeScript AuthSession interface.
    Always returns 200 - isAuthenticated indicates auth status.

    Anonymous response: { isAuthenticated: false, user: null }
    Authenticated: { isAuthenticated: true, user: {...} }
    """

    model_config = ConfigDict(
        strict=True,
        extra="forbid",
        populate_by_name=True,
    )

    isAuthenticated: bool = Field(..., description="Whether user is logged in")
    user: AuthUserSchema | None = Field(default=None, description="User info if authenticated")
    accessToken: str | None = Field(default=None, description="JWT access token (optional)")
    refreshToken: str | None = Field(default=None, description="JWT refresh token (optional)")
    expiresAt: str | None = Field(default=None, description="Token expiration (ISO 8601)")


# =============================================================================
# Token Verification Schemas (snake_case for internal APIs)
# =============================================================================


class TokenVerifyResponse(BaseModel):
    """
    Response schema for /api/v2/auth/verify endpoint.

    Used by the Elixir orchestrator to verify JWT tokens and retrieve
    user context for WebSocket authentication.

    Example response:
        {
            "user_id": "550e8400-e29b-41d4-a716-446655440000",
            "tenant_id": "cineos",
            "email": "user@example.com",
            "roles": ["team_member", "subscriber"],
            "permissions": ["app.view_data", "app.edit_own"]
        }
    """

    model_config = ConfigDict(
        strict=True,
        extra="forbid",
    )

    user_id: str = Field(
        ...,
        description="UUID of the authenticated user",
    )
    tenant_id: str | None = Field(
        default=None,
        description="PostgreSQL schema name for multi-tenancy (None for platform admins)",
    )
    email: str = Field(
        ...,
        description="User's email address",
    )
    roles: list[str] = Field(
        default_factory=list,
        description="User's group/role names (e.g., ['team_admin', 'subscriber'])",
    )
    permissions: list[str] = Field(
        default_factory=list,
        description="User's permission codenames (e.g., ['app.view_data', 'app.edit_own'])",
    )


class TokenVerifyError(BaseModel):
    """Error response for token verification failures."""

    model_config = ConfigDict(
        strict=True,
        extra="forbid",
    )

    error: str = Field(
        ...,
        description="Error code (e.g., 'unauthorized', 'token_expired')",
    )
    message: str = Field(
        ...,
        description="Human-readable error message",
    )
