#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from django.conf import settings as config
from django.contrib.auth import get_user_model
from django.core.cache import cache
from jwt import decode as jwt_decode
from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication

from django_base_ai import dispatch

User = get_user_model()


class UserAuthentication(BaseAuthentication):
    def authenticate(self, request):
        if isinstance(request.data, dict):
            request.data.update(request.query_params.dict())
        token = ""
        access_token = request.META.get("HTTP_AUTHORIZATION", None)
        # 用于处理下载/导出功能 a标签无法获取header 配置的AUTHORIZATION
        access_token_cookie = request.COOKIES.get("access_token", None)
        # header 方式上送token
        if access_token is not None:
            token = access_token
        # COOKIE 方式上送token
        if not token and access_token_cookie:
            token = access_token_cookie
        if not token:
            raise exceptions.AuthenticationFailed(detail={"code": 402, "msg": "缺少access_token"})
        try:
            new_token = token[4:] if "JWT " in token else token
            decoded_data = jwt_decode(new_token.strip(), config.SECRET_KEY, algorithms=["HS256"])
            userid = decoded_data["user_id"]
            current_user = User.objects.get(id=int(userid))
            # 开启点单登录 判断Token 是否唯一
            if (
                dispatch.get_system_config_values("base.single_login")
                and current_user
                and current_user.last_token != new_token
            ):
                print("access_token单点登录认证失效")
                raise exceptions.AuthenticationFailed(detail={"code": 402, "msg": "access_token单点登录"})
            # 判断 token 是否注销
            if cache.has_key(token):
                print("access_token已注销")
                raise exceptions.AuthenticationFailed(detail={"code": 402, "msg": "access_token已注销"})
            return (current_user, token)
        except Exception:
            raise exceptions.AuthenticationFailed(detail={"code": 402, "msg": "access_token已过期"})

    def authenticate_header(self, request):
        pass
