"""Token extraction from HTTP request headers."""

from collections.abc import Mapping
from typing import Protocol, runtime_checkable


@runtime_checkable
class HasHeaders(Protocol):
    """Any object that exposes a ``headers`` mapping (e.g. Starlette Request)."""

    @property
    def headers(self) -> Mapping[str, str]: ...


def _get_header(headers: Mapping[str, str], *names: str) -> str:
    """Return the first truthy header value found, or empty string."""
    for name in names:
        value = headers.get(name)
        if value:
            return value
    return ""


def extract_token(request: HasHeaders) -> str | None:
    """Extract a bearer token from request headers.

    Checks ``Authorization: Bearer <token>`` first, then falls back to
    the ``api-key`` header.  Returns *None* if neither is present.

    Both lower-case and title-case header names are tried so that plain
    ``dict`` callers (outside Starlette's case-insensitive Headers) work.
    """
    headers = request.headers

    auth_header = _get_header(headers, "authorization", "Authorization")
    if auth_header.lower().startswith("bearer "):
        return auth_header[7:].strip()

    api_key = _get_header(headers, "api-key", "Api-Key")
    if api_key:
        return api_key.strip()

    return None
