#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import base64
import hashlib
import hmac
import json
import logging
import random
import string
import time
import requests
from collections import OrderedDict
from datetime import datetime, timedelta


class UVerifyObject:

    '''
    【友盟+】智能认证 U-Verify（一键登录）
    开发文档:
    https://developer.umeng.com/docs/143070/detail/144785
    https://developer.umeng.com/docs/143070/detail/144783
    '''

    def __init__(self, token):
        # aliyun config
        self.ali_appkey = '204024884'
        self.ali_app_secret = 'lD7AXxc0ji0HzrNXZmfJaz3AecAboItD'

        # umeng config
        self.host_url = 'https://verify5.market.alicloudapi.com'
        self.path_url = '/api/v1/mobile/info'
        self.umeng_app_key = '5d8da0670cafb2a6b5000bc3'

        self.token = token
        self.phone = ''

        self.body_data_str = json.dumps({'token': self.token})
        content_md5_str = base64.b64encode(hashlib.md5(self.body_data_str.encode("UTF-8")).digest()).decode("UTF-8")

        now_date_time = datetime.utcnow() + timedelta(hours=8)
        timestamp = str(int(time.mktime(now_date_time.timetuple()) * 1000))

        sign_headers_dict = {
            'X-Ca-Key': self.ali_appkey,
            'X-Ca-Stage': 'RELEASE',
            'X-Ca-Timestamp': timestamp,
            'X-Ca-Version': '1'
        }

        sign_headers_str = ''
        for key in sorted(sign_headers_dict.keys()):
            value = sign_headers_dict[key]
            sign_headers_str = sign_headers_str + key + ':' + value + '\n'

        # 需要使用有序字典,否则StringToSign错误
        sign_dict = OrderedDict(
            [('HTTPMethod', 'POST'),
            ('Accept', 'application/json'),
            ('Content-MD5', content_md5_str),
            ('Content-Type', 'application/json; charset=UTF-8'),
            ('Date', None,),
            ('Headers', sign_headers_str),
            ('Url', self.path_url + '?' + 'appkey=' + self.umeng_app_key)]
        )

        string_to_sign = ""
        for key in sign_dict.keys():
            value = sign_dict[key]
            if key not in ['Headers', 'Url']:
                if value:
                    string_to_sign = string_to_sign + value + "\n"
                else:
                    string_to_sign = string_to_sign + "\n"
            else:
                string_to_sign = string_to_sign + value

        logger = logging.getLogger('info')
        logger.info('string_to_sign: {}'.format(string_to_sign))

        key_bytes = self.ali_app_secret.encode('utf-8')
        text_bytes = string_to_sign.encode('utf-8')
        hash_bytes = hmac.new(key_bytes, text_bytes, hashlib.sha256).digest()
        signature_str = base64.b64encode(hash_bytes).decode('utf-8')

        nonce_str = self.generate_code(8) + '-' + self.generate_code(4) + '-' + self.generate_code(4) + '-' + \
                    self.generate_code(4) + '-' + self.generate_code(12)

        self.headers_dict = {
            'Content-Type': 'application/json; charset=UTF-8',
            'Accept': 'application/json',
            'X-Ca-Version': '1',
            'X-Ca-Signature-Headers': 'X-Ca-Version,X-Ca-Stage,X-Ca-Key,X-Ca-Timestamp',
            'X-Ca-Stage': 'RELEASE',
            'X-Ca-Key': self.ali_appkey,
            'X-Ca-Timestamp': timestamp,
            'X-Ca-Nonce': nonce_str,
            'Content-MD5': content_md5_str,
            'X-Ca-Signature': signature_str
        }

        self.request_url = self.host_url + self.path_url + '?' + 'appkey=' + self.umeng_app_key


    def generate_code(self, length):
        key = string.digits + 'abcdef'
        str_list = random.sample(key + key, length)  # length >= len(key+key)
        result_str = ''.join(str_list)
        return result_str

    def verify_request(self):
        logger = logging.getLogger('info')
        logger.info('request_url: {}, data: {}, headers: {}'.format(self.request_url, self.body_data_str, self.headers_dict))
        response = requests.post(url=self.request_url, data=self.body_data_str.encode("UTF-8"), headers=self.headers_dict)
        logger.info('response: {}, headers: {}, text: {}'.format(response, response.headers, response.text))
        if response.status_code != 200:
            return False
        # 替换字符串,防止将字符串转为字典时报错
        res_text = response.text.replace('true', '"true"').replace('false', '"false"').replace('null', '"null"')
        logger.info('res_text: {}'.format(res_text))
        res = eval(res_text)
        print(res['success'])
        if res['success'] == 'false':
            return False
        self.phone = res['data']['mobile']  # 获取手机号
        return True
