"""
Token → identity resolution, shared by every adapter.

`authenticate(headers, config)` reads `X-Mizan-Token` (MWT) first, then
`Authorization: Bearer` (JWT), and returns an `Identity`, `None`, or the
`INVALID` sentinel.

The `INVALID` sentinel is load-bearing: when a token is PRESENT but bad, the
adapter must REJECT — never silently fall back to session auth (that would let
a forged/expired token degrade into anonymous-or-session access). `None` means
"no token offered" → the adapter may fall back to its own session identity.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Mapping

from mizan_core.auth.jwt import JWTConfig, JWTUser, decode_token
from mizan_core.identity import Identity
from mizan_core.mwt import MWTUser, decode_mwt


class _Invalid:
    """Sentinel: a token was presented but failed validation."""

    def __repr__(self) -> str:
        return "INVALID"


INVALID = _Invalid()


@dataclass(frozen=True)
class AuthConfig:
    jwt: JWTConfig | None = None
    mwt_secret: str | None = None
    mwt_audience: str = "mizan"


def authenticate(headers: Mapping[str, str], config: AuthConfig) -> Identity | _Invalid | None:
    """Resolve identity from request headers. Returns Identity | INVALID | None."""
    mwt = headers.get("X-Mizan-Token") or headers.get("x-mizan-token")
    if mwt and config.mwt_secret:
        payload = decode_mwt(mwt, config.mwt_secret, audience=config.mwt_audience)
        return MWTUser(payload) if payload else INVALID

    bearer = headers.get("Authorization") or headers.get("authorization") or ""
    if bearer.startswith("Bearer ") and config.jwt:
        payload = decode_token(bearer[7:], config.jwt, expected_type="access")
        return JWTUser(payload) if payload else INVALID

    return None
