import aredis
from jwt import ExpiredSignatureError
from sanic import Sanic
from sanic_jwt import exceptions, Authentication
from sanic_jwt import initialize
from sanic_jwt import Initialize
from pot_libs.aredis_util.aredis_utils import RedisUtils
from sanic_jwt import Responses


class User:

    def __init__(self, id, username, password):
        self.user_id = id
        self.username = username
        self.password = password

    def __repr__(self):
        return "User(id='{}')".format(self.user_id)

    def to_dict(self):
        return {"user_id": self.user_id, "username": self.username}


users = [User(1, "user1", "abcxyz"), User(2, "user2", "abcxyz")]

username_table = {u.username: u for u in
                  users}  # {'user1': User(id='1'), 'user2': User(id='2')}
userid_table = {u.user_id: u for u in
                users}  # {1: User(id='1'), 2: User(id='2')}


async def authenticate(request, *args, **kwargs):
    username = request.json.get("username", None)
    password = request.json.get("password", None)

    if not username or not password:
        raise exceptions.AuthenticationFailed("Missing username or password.")

    user = username_table.get(username, None)
    if user is None:
        raise exceptions.AuthenticationFailed("User not found.")

    if password != user.password:
        raise exceptions.AuthenticationFailed("Password is incorrect.")
    # print(user)
    user = {"user_id": 10000, "name": "zhangsan", "age": 18}
    return user


async def store_refresh_token(user_id, refresh_token, *args, **kwargs):
    key = f'refresh_token_{user_id}'
    # await aredis.set(key, refresh_token)
    return await RedisUtils().set(key, refresh_token)


async def retrieve_refresh_token(request, user_id, *args, **kwargs):
    key = f'refresh_token_{user_id}'
    # return await aredis.get(key)
    return await RedisUtils().get(key)


def black_list_verify():
    res = RedisUtils().hset("myhash", "name1", "lisi")
    if not res:
        return 0
    else:
        return 1


class MyResponses(Responses):
    @staticmethod
    def extend_authenticate(request,
                            user=None,
                            access_token=None,
                            refresh_token=None):
        return {}

    @staticmethod
    def extend_retrieve_user(request, user=None, payload=None):
        return {}

    @staticmethod
    def extend_verify(request, user=None, payload=None):
        res = black_list_verify()
        # res = await RedisUtils().hset("myhash", "name1", "lisi")
        # 判断黑名单
        # return {"name": 111}

    @staticmethod
    def extend_refresh(request,
                       user=None,
                       access_token=None,
                       refresh_token=None,
                       purported_token=None,
                       payload=None):
        return {}


app = Sanic(__name__)

Initialize(
    app,
    authenticate=authenticate,
    # url_prefix='/api',  # URL前缀
    # path_to_authenticate='/my_auth',  # auth路由, 如果authenticate通过, 生成token
    # path_to_verify='/my_verify',  # 验证access_token
    # path_to_refresh='/my_refresh',  # 刷新token(包括access_token, refresh_token)
    # curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer <JWT>" -d '{"refresh_token": "<REFRESH
    # TOKEN>"}' http://localhost:8000/auth/refresh
    # path_to_retrieve_user='/my_retrieve_user',  # 获取当前用户的信息
    # curl -X GET -H "Authorization: Bearer <JWT>" http://localhost:8000/auth/me
    # 200 Response
    # {
    #     "me": {
    #         user_id": 123456
    #     }
    # }
    # refresh_token_enabled=True,
    # store_refresh_token=store_refresh_token,
    # retrieve_refresh_token=retrieve_refresh_token,
    # # secret=10000
    # # class_views=my_views
    # responses_class=MyResponses
)

@app.route("/auth/check_black_list")
def check_black_list(request):
    token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxMDAwMCwiZXhwIjoxNTkzNzc2MDU2fQ.78DaVkdbNFCy7FW9i73-O_-WjZRz_7qg-X4NH1zjzoQ"
    is_verified = False
    try:
        is_verified = app.auth.verify_token(token)
    except ExpiredSignatureError as exp:
        is_verified = False
        reason = exp.args[0]  # 'Signature has expired'
    except exceptions.InvalidCustomClaimError:
        is_verified = False
    finally:
        print("is_verified:%s" % (is_verified))

    return {"is_verified": is_verified, "reason": reason}



if __name__ == "__main__":
    app.run(host="127.0.0.1", port=8888)
