from collections.abc import Generator

from fastapi import Depends, Header, HTTPException, Query, status
from sqlalchemy.orm import Session

from app.core.database import open_db_session
from app.core.tenancy import AuthContext, resolve_token


def _normalize_token(raw_value: str | None) -> str:
    if raw_value is None:
        return ""
    value = raw_value.strip()
    if value.lower().startswith("bearer "):
        return value.split(" ", 1)[1].strip()
    return value


def validate_token(raw_value: str | None) -> AuthContext:
    token = _normalize_token(raw_value)
    context = resolve_token(token)
    if context is None:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Token o sessione non validi")
    return context


def require_token(authorization: str | None = Header(default=None)) -> AuthContext:
    return validate_token(authorization)


def require_query_token(token: str | None = Query(default=None)) -> AuthContext:
    return validate_token(token)


def require_management_token(authorization: str | None = Header(default=None)) -> AuthContext:
    context = validate_token(authorization)
    if context.role == "staff" and "ordini" not in context.permissions:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Questo account non puo accedere a Ordini")
    return context


def require_management_query_token(token: str | None = Query(default=None)) -> AuthContext:
    context = validate_token(token)
    if context.role == "staff" and "ordini" not in context.permissions:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Questo account non puo accedere a Ordini")
    return context


def get_db(auth: AuthContext = Depends(require_management_token)) -> Generator[Session, None, None]:
    yield from open_db_session(auth.database_url)


def get_db_from_query_token(auth: AuthContext = Depends(require_management_query_token)) -> Generator[Session, None, None]:
    yield from open_db_session(auth.database_url)


__all__ = [
    "get_db",
    "get_db_from_query_token",
    "require_management_query_token",
    "require_management_token",
    "require_query_token",
    "require_token",
    "validate_token",
]
