import base64
import binascii

from starlette.authentication import (
    AuthCredentials,
    AuthenticationBackend,
    AuthenticationError,
    BaseUser,
)
from starlette.middleware import Middleware
from starlette.middleware.authentication import AuthenticationMiddleware
from starlette.requests import HTTPConnection


class User(BaseUser):
    def __init__(self, user_id: str) -> None:
        self.user_id = user_id

    @property
    def is_authenticated(self) -> bool:
        return True


class BasicAuthBackend(AuthenticationBackend):
    async def authenticate(self, conn: HTTPConnection) -> tuple[AuthCredentials, User] | None:
        if "Authorization" not in conn.headers:
            return None

        auth = conn.headers["Authorization"]
        try:
            scheme, credentials = auth.split()
            if scheme.lower() != "basic":
                return None
            decoded = base64.b64decode(credentials).decode("ascii")
        except (ValueError, UnicodeDecodeError, binascii.Error):
            raise AuthenticationError("Invalid basic auth credentials")

        user_id, _, _ = decoded.partition(":")
        return AuthCredentials(["authenticated"]), User(user_id)


def create_auth_middleware() -> list[Middleware]:
    return [Middleware(AuthenticationMiddleware, backend=BasicAuthBackend())]
