"""Runtime-checkable protocols for backends, strategies, and transports."""

from __future__ import annotations

from typing import Any, Protocol, runtime_checkable

from .types import ID


@runtime_checkable
class UserProtocol(Protocol[ID]):
    """Any user model must satisfy this shape."""

    id: ID
    email: str
    hashed_password: str | None
    is_active: bool
    is_verified: bool


@runtime_checkable
class BackendProtocol(Protocol[ID]):
    """Database backend for user CRUD."""

    async def get_by_id(self, user_id: ID) -> UserProtocol[ID] | None: ...

    async def get_by_email(self, email: str) -> UserProtocol[ID] | None: ...

    async def create(self, data: dict[str, Any]) -> UserProtocol[ID]: ...

    async def update(self, user: UserProtocol[ID], data: dict[str, Any]) -> UserProtocol[ID]: ...

    async def delete(self, user: UserProtocol[ID]) -> None: ...


@runtime_checkable
class StrategyProtocol(Protocol[ID]):
    """Authentication strategy contract."""

    async def authenticate(
        self, credentials: dict[str, Any], backend: BackendProtocol[ID]
    ) -> UserProtocol[ID] | None: ...

    async def on_after_register(self, user: UserProtocol[ID]) -> None: ...

    async def on_after_login(self, user: UserProtocol[ID]) -> None: ...


@runtime_checkable
class TransportProtocol(Protocol):
    """How auth tokens travel (bearer header, cookie, etc.)."""

    async def get_token(self, request: Any) -> str | None: ...

    def set_token(self, response: Any, token: str) -> None: ...

    def remove_token(self, response: Any) -> None: ...
