from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from sqlmodel import Session, select
from jose import JWTError
from app.utils.tokens import decode_token
from app.core.config import get_settings
from app.db.session import get_session
from app.models import User, Role
from app.core.constants import (
    ERR_INVALID_TOKEN,
    ERR_NOT_VALID_CRED,
    ERR_USER_NOT_FOUND,
    ERR_INACTIVE_USER,
    ERR_USER_DELETED,
    ERR_FORBIDDEN,
    ERR_NO_SUB
)

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/auth/login")
settings = get_settings()

def get_current_user(token: str = Depends(oauth2_scheme), session: Session = Depends(get_session)) -> User:
    try:
        payload = decode_token(token)
        if payload.get("type") != "access":
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=ERR_INVALID_TOKEN)
        sub = payload.get("sub")
        if not sub:
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=ERR_NO_SUB)
    except JWTError as e:
        print("JWTError:", e)
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=ERR_NOT_VALID_CRED)

    q = select(User).where(User.email == sub)
    user = session.exec(q).first()
    if not user:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=ERR_USER_NOT_FOUND)
    if not user.is_active:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERR_INACTIVE_USER)
    if user.is_deleted:
        raise HTTPException(status_code=status.HTTP_410_GONE, detail=ERR_USER_DELETED)
    return user

# role-checker factory -> usage: Depends(require_roles(Role.SUPERADMIN))
def require_roles(*allowed_roles: Role):
    """
    Correct FastAPI-compatible role checker.
    Must return a callable, NOT Depends().
    """
    async def role_checker(current_user: User = Depends(get_current_user)):
        if current_user.role not in allowed_roles:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail=ERR_FORBIDDEN
            )
        return current_user
    
    return role_checker
