# -*- coding:utf-8 -*-
"""
    用户登录注册
"""

from django.conf import settings

import gm_upload
from gm_types.error import ERROR as ERROR_CODES
from gm_types.gaia import VERIFY_CODE_TYPE as VFC_TYPE
from gm_types.gaia import LOGIN_AUTH_TYPE, USER_ACCOUNT_TYPE
from helios import create_default_invoker

from rpc.decorators import bind_context
from rpc.tool.error_code import gen
from rpc.tool.log_tool import user_logger, info_logger, logging_exception
from utils.phone import format_phone
from api.tool.verification_code import anti_brute, VerifiedCode
from api.util.user_util import get_user_by_authtype_id, _user_register, _do_login
from api.trigger.user_trigger import login_trigger, user_change_trigger
from api.manager.user_manager import valid_nick_name


@bind_context('account/user/regin_vfc')
def vfc_login(ctx, vfc_code=None, phone_num=None, vfc_type=None, extra_info=None, reg_default=True, need_vfc=True, **kwargs):
    """
    手机验证码登录/ 如果用户不存在, 则先注册

    param code: 验证码
    param account_id: 手机号
    param reg_default:True, 没有账号时是否创建账号, 默认创建
    param need_vfc: 是否需要验证码, 如果没有验证码, 则默认验证通过
    """
    phone = format_phone(phone_num)
    if phone in ('18810225027', '12345678912', '12345678888') and vfc_code == "1234":
        _user = get_user_by_authtype_id(LOGIN_AUTH_TYPE.phone, phone)
        user_change_trigger(_user.id)  # 测试账号
        data =  _do_login(ctx, _user)
        data['new_reg'] = False
        return data

    vfc_type = vfc_type or VFC_TYPE.REGIN
    user_logger.info('[LOGIN] phone(%s) login...' % (phone))

    # vfc_auth
    if need_vfc:
        ver_res, _err = _verify_vfc_code(phone, vfc_type, vfc_code)
        if not ver_res:
            return gen(_err)

    _reg = False
    _user = get_user_by_authtype_id(LOGIN_AUTH_TYPE.phone, phone)
    if not _user:
        if not reg_default:
            gen(ERROR_CODES.USER_NOT_FOUND)

        if str(vfc_type) == str(VFC_TYPE.REGIN):
            _user_register(phone, account_type=LOGIN_AUTH_TYPE.phone, extra_info=extra_info)
            _reg = True
            _user = get_user_by_authtype_id(LOGIN_AUTH_TYPE.phone, phone)
            # 添加用户风险评估
            user_ip = kwargs.get('user_ip', '')
            u_type = '10004'
            _user_check(user_ip, phone, _user.id, phone, u_type)

    if not _user:
        user_logger.info('[LOGIN]{ERROR} phone(%s) login failed for reason: user not exist ' % (phone))
        return gen(ERROR_CODES.LOGIN_FAIL)

    login_trigger(_user.id, extra_info)
    user_change_trigger(_user.id)
    user_logger.info('[LOGIN] phone(%s) login at user_id(%s)' % (phone, _user.id))
    data = _do_login(ctx, _user)
    data['new_reg'] = _reg
    return data


def _verify_vfc_code(phone, vfc_type, vfc_code):
    '''
    验证手机验证码
    '''
    if anti_brute(phone + ':' + str(vfc_type)):
        user_logger.info('[LOGIN]{ERROR} phone(%s) regin too frequently' % (phone))
        return False, ERROR_CODES.ACCESS_LIMIT

    ver_res = VerifiedCode.verify(vfc_code, phone, vfc_type)
    if not ver_res:
        user_logger.info('{ERROR} phone(%s) login failed for invalid_vfc' % (phone))
        return False, ERROR_CODES.INVALID_VFC
    return True, None


def _convert_third_info(third_info):
    '''
    转换第三方头像, 验证第三方昵称合法性
    '''
    if third_info:
        if third_info.get('third_portrait'):
            third_info['converted_third_portrait'] = gm_upload.fetch_picture_and_save_to_qiniu(third_info['third_portrait'])
        info_logger.info('third_nick_name={}'.format(third_info.get('third_nick_name')))
        if third_info.get('third_nick_name'):
            try:
                res = valid_nick_name(third_info['third_nick_name'])
                if res['error'] == 0:
                    third_info['converted_third_nick_name'] = third_info.get('third_nick_name')
                else:
                    info_logger.info(u'third_nick_name={},valid_error={},valid_message={}'.format(
                        third_info['third_nick_name'], res['error'], res['message'],
                    ))
            except:
                pass
        else:
            info_logger.info('third_nick_name=None,valid_error=-1')


def _verify_phone_vfc_thirdlogin(phone_num, vfc_code, account_type, account_id):
    '''
    三方登录, 验证手机验证码
    '''
    phone = format_phone(phone_num)
    if phone:
        vfc_type = VFC_TYPE.REGIN
        if anti_brute(phone + ':' + str(vfc_type)):
            user_logger.info('[THR_LOGIN]{ERROR} account(%s_%s) login failed for phone(%s) act too frequently' % (account_type, account_id, phone))
            gen(ERROR_CODES.ACCESS_LIMIT)
        ver_res = VerifiedCode.verify(vfc_code, phone, vfc_type)
        if not ver_res:
            user_logger.info('[THR_LOGIN]{ERROR} account(%s_%s) login failed for invalid vfc' % (account_type, account_id))
            gen(ERROR_CODES.INVALID_VFC)

    elif settings.PHONE_MUST_FOR_THIRD_REG:
        user_logger.info('[THR_LOGIN]{ERROR} account(%s_%s) login failed for phone lost' % (account_type, account_id))
        gen(ERROR_CODES.PHONE_NEEDED_FOR_THIRD_REG)     # 提示注册需要绑定手机号


def _user_check(user_ip, uid, user_id, phone, account_type):
    # 添加用户风险评估
    rpc_client = create_default_invoker(debug=True)
    try:
        res = rpc_client['antispam/user/check'](
            uid=uid,
            user_ip=user_ip,
            user_id=user_id,
            account_type=account_type,
        ).unwrap()
        if res.get('black'):
            rpc_client['api/user/add_blacklist'](
                phone=phone,
                user_id=user_id,
            ).unwrap()
    except:
        logging_exception()


@bind_context('account/user/third_login')
def third_login(ctx, account_type, account_id, phone_num=None, vfc_code=None, extra_info=None, third_info=None, **kwargs):
    """
    第三方登录

    param account_type: 第三方类型, 客户端参数为LOGIN_AUTH_TYPE, 入库映射为ACCOUNT_TYPE
    param account_id: 第三方id
    param phone_num: 手机号, eg: +86123456789
    param vfc_code: 验证码
    param extra_info: 包含基本信息参数
    param third_info: 第三方信息, 可包含第三方昵称, 头像信息等
    """
    _user = get_user_by_authtype_id(account_type, account_id)
    user_logger.info('[THR_LOGIN] account(%s_%s) login...' % (account_type, account_id))
    new_reg = False
    if not _user:
        _verify_phone_vfc_thirdlogin(phone_num, vfc_code, account_type, account_id)

        _convert_third_info(third_info)
        phone = format_phone(phone_num)
        _user_id = _user_register(account_id=account_id, account_type=account_type, phone=phone, extra_info=extra_info, third_info=third_info)
        if account_type in [USER_ACCOUNT_TYPE.QQ, USER_ACCOUNT_TYPE.WECHAT]:
            # 添加用户风险评估
            user_ip = kwargs.get('user_ip', '')
            uid = phone
            u_type = '1' if account_type == USER_ACCOUNT_TYPE.QQ else '2'
            _user_check(user_ip, uid, _user_id, phone, u_type)
        _user = get_user_by_authtype_id(account_type, account_id)
        new_reg = _user_id and _user_id is not True
    if not _user:
        user_logger.info('[THR_LOGIN]{ERROR} account(%s_%s) login failed for user_not_existing' % (account_type, account_id))
        gen(ERROR_CODES.LOGIN_FAIL)

    login_trigger(_user.id, extra_info)
    user_change_trigger(_user.id)
    user_logger.info('[THR_LOGIN] account(%s_%s) login at user_id(%s)!!!' % (account_type, account_id, _user.id))
    data = _do_login(ctx, _user)
    data['new_reg'] = new_reg
    return data
