# coding=utf-8
__author__ = 'leaf'

import datetime
import random
from hashlib import sha1

from django.conf import settings

from rpc.cache import code_cache, user_cache
from rpc.tool.random_tool import random_str


salt = lambda: sha1(u"jFcSFdQvbDkN9fsc" + str(datetime.date.today())).hexdigest()[:5]


def calc_verification_code(phone):
    # 生成验证码
    if isinstance(phone, unicode):
        phone = phone.encode()
    verification_code = int(sha1(salt() + phone).hexdigest(), 16) % 10000
    return verification_code


def get_verification_message(verification_code):
    # 生成验证码(4位)
    return u"%04d" % verification_code


def get_verification_message_v1(verification_code):
    # 生成验证码(6位)
    return u"%06d" % verification_code


def generate_referral_code(id_length):
    # 生成邀请码
    return str(random.randint(10**(id_length-1), 10**id_length-1))


def anti_brute(phone):
    anti_brute_force_key = "anti:{}:login:{}".format(
                            phone, datetime.datetime.today().strftime('%y%m%d%H'))
    login_attempts = user_cache.get(anti_brute_force_key)
    # 防暴力破解
    if login_attempts is None:
        login_attempts = 0
        user_cache.setex(anti_brute_force_key, 3600, login_attempts)
    else:
        login_attempts = int(login_attempts)

    if login_attempts >= settings.MAX_LOGIN_ATTEMPTES:
        return True
    else:
        user_cache.incr(anti_brute_force_key)
        return False


def generate_login_code(phone):
    from api.models import VERIFY_CODE_TYPE
    key = 'phone:%d:%s' % (VERIFY_CODE_TYPE.LOGIN, phone)
    code = code_cache.get(key)
    if code is None:
        code = random_str(4, digit=True)
        code_cache.setex(key, 15*60, code)
    return code


class CodeBase(object):
    timeout = 900  # 15 minutes
    _cache = code_cache

    @classmethod
    def generate(cls, *args, **kwargs):

        key = cls.gen_key(*args, **kwargs)
        code = cls._cache.get(key)
        if code is None:
            code = cls.gen_code(key, *args, **kwargs)
            cls._cache.setex(key, cls.timeout, code)
        return code

    @classmethod
    def verify(cls, code, *args, **kwargs):

        key = cls.gen_key(*args, **kwargs)
        if code == cls._cache.get(key):
            return True
        return False

    @classmethod
    def gen_code(cls, key, *args, **kwargs):
        raise NotImplementedError

    @classmethod
    def gen_key(cls, *args, **kwargs):
        raise NotImplementedError


class DocRegCode(CodeBase):
    @classmethod
    def gen_code(cls, key, *args, **kwargs):
        return random_str(4, digit=True)

    @classmethod
    def gen_key(cls, phone, *args, **kwargs):
        from api.models import VERIFY_CODE_TYPE
        key = 'phone:%d:%s' % (VERIFY_CODE_TYPE.DOCREG, phone)
        return key


def verify_phone_code(phone, code, code_type):
    key = "phone:%d:%s" % (code_type, phone)
    _code = code_cache.get(key)
    if _code is None or code != _code:
        return False
    elif _code == code:
        return True
    else:
        return False


class VerifiedCode(CodeBase):
    @classmethod
    def gen_code(cls, key, *args, **kwargs):
        return random_str(6, digit=True)

    @classmethod
    def gen_key(cls, phone, code_type, *args, **kwargs):
        key = 'phone:%d:%s' % (code_type, phone)
        return key
