import jwt
from datetime import datetime, timedelta
from werkzeug.exceptions import Unauthorized
from ..db.models import User
from ..config import get_config


SECRET = get_config().JWT_SECRET
JWT_ALG = 'HS256'


def auth(admin=False):
    """Decorator that unwraps JWT token into an auth_user object"""

    def _auth(func):
        def wrapper(*args, **kwargs):
            if 'user' not in kwargs:
                return func(*args, **kwargs)

            auth_user = User.query.filter_by(id=kwargs['user']).first()

            if auth_user is None:
                raise Unauthorized('Could not load user %s for auth' % kwargs['user'])

            if admin and auth_user.is_admin is False:
                raise Unauthorized('Only an admin can perform that action')

            del kwargs['user']
            del kwargs['token_info']
            kwargs['auth_user'] = auth_user
            return func(*args, **kwargs)
        return wrapper
    return _auth


def login(body):
    user = User.query.filter_by(username=body.get('username')).first()
    if user is None or user.check_password(body.get('password')) is False:
        return dict(
            error='Could not authenticate you with that username and password'
        ), 401

    token = jwt.encode({
        'iat': datetime.utcnow(),
        'exp': datetime.utcnow() + timedelta(days=7),
        'sub': user.id,
    }, SECRET, algorithm=JWT_ALG)

    return {'token': token.decode('utf-8'), 'user_id': user.id}


def check_token(token):
    try:
        return jwt.decode(token, SECRET, algorithms=[JWT_ALG])
    except Exception:
        raise Unauthorized()
