import asyncio
from _typeshed import Incomplete
from dataclasses import dataclass, field
from typing import Any

REFRESH_MARGIN_SECONDS: float
console: Incomplete

class GatewayError(Exception):
    """Expected gateway failure rendered to the user without a traceback."""

@dataclass(frozen=True)
class OAuthMetadata:
    authorization_endpoint: str
    token_endpoint: str
    device_authorization_endpoint: str

async def discover_oauth_metadata(http: Any, backend: str) -> OAuthMetadata:
    """Fetch the backend's OAuth authorization server metadata."""

GATEWAY_CIMD_PATH: str

class CimdOAuthClient:
    """Public OAuth client identified by a CIMD URL."""
    client_id: Incomplete
    def __init__(self, http: Any, metadata: OAuthMetadata, *, client_id: str) -> None: ...
    async def start_device_authorization(self, data: dict[str, str]) -> Any: ...
    async def post_token(self, data: dict[str, str]) -> Any: ...

@dataclass
class AuthBootstrap:
    redirect_uri: str
    expected_state: str = ...
    code_verifier: str = ...
    received_code: str | None = ...
    error: str | None = ...
    event: asyncio.Event = field(default_factory=asyncio.Event)

@dataclass(frozen=True)
class OAuthCallbackResult:
    title: str
    body: str
    status_code: int = ...

class OAuthSession:
    """In-memory OAuth token state for the local gateway proxy."""
    def __init__(self, client: CimdOAuthClient, metadata: OAuthMetadata, *, resource: str, scope: str) -> None: ...
    async def auth_code_flow(self, bootstrap: AuthBootstrap) -> None: ...
    async def device_flow(self) -> None: ...
    async def refresh(self) -> None: ...
    async def current_access_token(self) -> str: ...
    async def force_refresh(self) -> str: ...

class GatewayAuth:
    """OAuth control-plane for an authorized local gateway proxy session."""
    def __init__(self, session: OAuthSession, *, redirect_uri: str, flow: str) -> None: ...
    async def authorize(self) -> None: ...
    async def current_access_token(self) -> str: ...
    async def recover_after_rejection(self, *, use_reauth: bool) -> bool: ...
    async def reauthorize(self) -> None: ...
    def complete_browser_callback(self, *, error: str | None, error_description: str | None, code: str | None, state: str | None) -> OAuthCallbackResult: ...
