import os
from typing import Annotated
from functools import wraps

from fastapi import Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from jose import jwt, JWTError
from starlette import status

from utils.exceptions import UnauthorizedException, AuthenticationError

oauth2_bearer = OAuth2PasswordBearer(tokenUrl='/api/auth/login')



async def get_current_user(token: Annotated[str, Depends(oauth2_bearer)]):
    try:
        secret_key = os.getenv('SECRET_KEY')
        algorithm = os.getenv('ALGORITHM')
        payload = jwt.decode(token, secret_key, algorithms=[algorithm])
        name: str = payload.get('sub')
        user_id: int = payload.get('id')
        email: str = payload.get('email')
        if name is None or user_id is None:
            raise AuthenticationError
        return {'name': name, 'id': user_id, 'email': email}
    except JWTError:
        raise AuthenticationError

user_dependency = Annotated[dict, Depends(get_current_user)]

def handles_authentication(handler):
    @wraps(handler)
    async def wrapper(user: user_dependency, *args, **kwargs):
        if user is None:
            raise AuthenticationError
        return await handler(user, *args, **kwargs)

    return wrapper
