# -*- coding:utf-8 -*-

import datetime

import jwt
import six
from flask import abort
from flask import current_app
from flask import request
from flask_login import login_user
from flask_login import logout_user

from api.lib.decorator import args_required
from api.lib.perm.acl.cache import User
from api.lib.perm.auth import auth_abandoned
from api.resource import APIView


class LoginView(APIView):
    url_prefix = "/login"

    @args_required("username")
    @args_required("password")
    @auth_abandoned
    def post(self):
        username = request.values.get("username") or request.values.get("email")
        password = request.values.get("password")
        user, authenticated = User.query.authenticate(username, password)
        if not authenticated:
            return abort(401, "invalid username or password")

        login_user(user)

        token = jwt.encode({
            'sub': user.email,
            'iat': datetime.datetime.now(),
            'exp': datetime.datetime.now() + datetime.timedelta(minutes=24 * 60 * 7)},
            current_app.config['SECRET_KEY'])

        return self.jsonify(token=token.decode() if six.PY2 else token, username=username)


class AuthWithKeyView(APIView):
    url_prefix = "/auth_with_key"

    @args_required("key")
    @args_required("secret")
    @args_required("path")
    @auth_abandoned
    def post(self):
        key = request.values.get('key')
        secret = request.values.get('secret')
        path = six.moves.urllib.parse.urlparse(request.values.get('path')).path
        payload = request.values.get('payload') or {}

        payload.pop('_key', None)
        payload.pop('_secret', None)

        req_args = [str(payload[k]) for k in sorted(payload.keys())]
        user, authenticated = User.query.authenticate_with_key(key, secret, req_args, path)

        return self.jsonify(user=user.to_dict() if user else {},
                            authenticated=authenticated)


class LogoutView(APIView):
    url_prefix = "/logout"

    @auth_abandoned
    def post(self):
        logout_user()
        self.jsonify(code=200)
