import logging
import jwt
import time
import requests
import datetime

from Object.RedisObject import RedisObject
from Ansjer.config import OAUTH_ACCESS_TOKEN_SECRET, OAUTH_REFRESH_TOKEN_SECRET, OAUTH_ACCESS_TOKEN_TIME, \
    OAUTH_REFRESH_TOKEN_TIME, DETECT_PUSH_DOMAINS, LOGGER
from Model.models import StsFrequency

logger = logging.getLogger('token')


class TokenObject:

    def __init__(self, token=None, returntpye='currency'):
        if token == 'local':
            token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiIxNTg0MzUxODk2MjgyMTM4MDAxMzgwMDAiLCJsYW5nIjoiZW4iLCJ1c2VyIjoiMTM2ODAzMTc1OTYiLCJtX2NvZGUiOiIxMjM0MTMyNDMyMTQiLCJleHAiOjE1ODcyNzcwNjB9.c0LV_XyxwbzUlYqMJqx7vw9f19Jv-0kGnUHuu_go-mo'
        if token == 'test':
            token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiMTM4MDAxMzgwMDEiLCJleHAiOjE1Njk5OTg4OTYsInVzZXJJRCI6IjE1MTU2NDI2MjMzNzkzOTUxMzgwMDEzODAwMSIsImxhbmciOiJlbiIsIm1fY29kZSI6IjEyMzQxMzI0MzIxNCJ9.VAQtT9AbCCfXcrNj9DL5cvVasMDoI7AP8ptgU1GoMu8'
        today = datetime.datetime.today()
        today_date = datetime.datetime(today.year, today.month, today.day)
        self.today_timestamp = int(today_date.timestamp())
        self.token = token
        self.lang = None
        self.userID = None
        self.user = ''
        self.code = 0
        self.valid()
        self.returntpye = returntpye

    def valid(self):
        if self.token is None:
            logger.info("token is None")
            self.code = 309
            return
        try:
            self.token = self.token.replace("Bearer ", "")

            res = jwt.decode(self.token, OAUTH_ACCESS_TOKEN_SECRET, algorithms='HS256')
            self.userID = res.get('userID', None)
            self.lang = res.get('lang', None)
            self.user = res.get('user', '')
            app_bundle_id = res.get('appBundleId', None)
            token_version = res.get('tokenVersion', None)
            # 刷新登录时间
            # if self.userID:
            #     print(self.user)
            #     redisObj = RedisObject(db=3)
            #     redisObj.set_data(key=self.userID, val=self.user, expire=300)

        except jwt.ExpiredSignatureError as e:
            self.code = 309
            self.add_or_update_qs()
            logger.info('errLine:{}, errMsg:{}, token:{}'.format(e.__traceback__.tb_lineno, repr(e), self.token))
            return
        except Exception as e:
            self.code = 309
            self.add_or_update_qs()
            logger.info('errLine:{}, errMsg:{}, token:{}'.format(e.__traceback__.tb_lineno, repr(e), self.token))
            return
        else:
            if not self.userID:
                self.code = 309
                self.add_or_update_qs()
                logger.info('errMsg:{}, token:{}'.format('缺少用户ID', self.token))
                return
            else:
                if self.userID:
                    if app_bundle_id and token_version == 'V2':
                        redis_obj = RedisObject()
                        key = 'token_user_{}_{}'.format(self.userID, app_bundle_id)
                        redis_token = redis_obj.get_data(key)
                        if not redis_token:
                            redis_obj.set_data(key, self.token)
                            self.code = 0
                            return res
                        if self.token != redis_token:
                            self.code = 310
                            logger.info(
                                'errMsg:{}, token:{}, redis_token:{}'.format('多点登录', self.token, redis_token))
                            return
                    self.code = 0
                    return res
                else:
                    self.code = 309
                    return

    def generate(self, data=None):
        if data is None:
            data = {}
        try:
            access_expire = int(OAUTH_ACCESS_TOKEN_TIME.total_seconds())
            refresh_expire = int(OAUTH_REFRESH_TOKEN_TIME.total_seconds())
            now_stamp = int(time.time())
            access_data = data
            refresh_data = data
            access_data['exp'] = access_expire + now_stamp
            refresh_data['exp'] = refresh_expire + now_stamp
            access_token = jwt.encode(access_data,
                                      OAUTH_ACCESS_TOKEN_SECRET,
                                      algorithm='HS256')
            refresh_token = jwt.encode(
                refresh_data,
                OAUTH_REFRESH_TOKEN_SECRET,
                algorithm='HS256')

            res = {
                'access_token': access_token,
                'access_expire': access_expire,
                'refresh_expire': refresh_expire,
                'refresh_token': refresh_token,
            }

            if self.returntpye == 'pc':
                res = {
                    'token': access_token,
                    'access_expire': access_expire,
                    'refresh_expire': refresh_expire,
                    'refresh_token': refresh_token,
                }
            app_bundle_id = data.get('appBundleId', None)
            token_version = data.get('tokenVersion', None)
            LOGGER.info('{}生成新token，参数:{}'.format(data.get('userID', 'pctest'), data))
            if app_bundle_id and token_version == 'V2':
                redis_obj = RedisObject()
                key = 'token_user_{}_{}'.format(data['userID'], app_bundle_id)
                LOGGER.info('{}写入新token：{}'.format(data['userID'], access_token))
                redis_obj.set_data(key, access_token)
                if data['tokenVal']:
                    # 请求推送
                    push_url = '{}transparent-transmission/logout-push'.format(DETECT_PUSH_DOMAINS)
                    result = requests.post(push_url, data={'push_token': data['tokenVal'], 'user_id': data['userID'],
                                                           'app_bundle_id': app_bundle_id})
                    LOGGER.info('{}登出推送结果:{}'.format(data['userID'], result.json()))
            logger.info(
                '用户登录信息, data:{}, access_token:{}, refresh_token:{}'.format(data, access_token, refresh_token))
        except Exception as e:
            self.code = 309
            self.add_or_update_qs()
            logger.info('errLine:{}, errMsg:{}, token:{}'.format(e.__traceback__.tb_lineno, repr(e), self.token))
            print(repr(e))
        else:
            self.code = 0
            return res

    def encryption(self, data=None):
        if data is None:
            data = {}
        try:
            access_expire = int(OAUTH_ACCESS_TOKEN_TIME.total_seconds())
            refresh_expire = int(OAUTH_REFRESH_TOKEN_TIME.total_seconds())
            now_stamp = int(time.time())
            access_data = data
            refresh_data = data
            access_data['exp'] = access_expire + now_stamp
            refresh_data['exp'] = refresh_expire + now_stamp
            access_token = jwt.encode(access_data,
                                      OAUTH_ACCESS_TOKEN_SECRET,
                                      algorithm='HS256')
            return access_token
        except Exception as e:
            self.code = 309
            print(repr(e))

    def refresh(self):
        if not self.token:
            self.code = 309
            return
        try:
            res = jwt.decode(self.token, OAUTH_REFRESH_TOKEN_SECRET, algorithms='HS256')
        except jwt.ExpiredSignatureError as e:
            print('过期')
            print(repr(e))
            self.code = 309
            self.add_or_update_qs()
            logger.info('errLine:{}, errMsg:{}, token:{}'.format(e.__traceback__.tb_lineno, repr(e), self.token))
        except Exception as e:
            self.code = 309
            self.add_or_update_qs()
            logger.info('errLine:{}, errMsg:{}, token:{}'.format(e.__traceback__.tb_lineno, repr(e), self.token))
            print(repr(e))
        else:
            self.userID = res.get('userID', None)
            self.user = res.get('user', '')
            self.lang = res.get('lang', None)
            refreshRes = self.generate(data=res)
            return refreshRes

    def add_or_update_qs(self):
        qs = StsFrequency.objects.filter(type=2, addTime=self.today_timestamp, uid='token')
        if qs.exists():
            token_qs = qs[0]
            token_qs.frequency += 1
            token_qs.updateTime = int(time.time())
            token_qs.save()
        else:
            StsFrequency.objects.create(uid='token', frequency=1, type=2, addTime=self.today_timestamp,
                                        updateTime=int(time.time()))
