# coding=utf-8
from __future__ import absolute_import, unicode_literals, print_function

import hashlib
import time
import urllib
import urllib2
import datetime
import urlparse
from hashlib import md5
import json
import requests
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from django.conf import settings

from gm_types.gaia import (
    PROMOTION_CHANNEL_NAME,
    CHANNEL_CALLBACK_TYPE,
    CLIENT_TYPE,
    CHANNEL_STATUS,
    PLATFORM_CHANNEL
)

from api.util import auth_util
from statistic.utils.url import get_url_info
from statistic.tasks import delayed_activate_callback
from rpc.decorators import bind
from rpc.tool.log_tool import channel_logger, logging_exception
from ..models import PromotionChannel, Device, SheQuDevice, LikePromotionInfo
from ..utils.guangdiantong import guangdiantong_active,get_token
from statistic.views.channels.xinyouxingkong import xinyouxingkong_active_record
from statistic.views.channels.in_mobi import inmobi_active_record

# 请求时校验ssl
_VERIFIED = False

def _form_google_user_agent(app_name, app_version, platform, os_version, device_model, build_number=''):
    if not all([app_name, app_version, platform, os_version, device_model]):
        return ''

    platform = 'Android' if platform.lower() == "android" else 'IOS'
    build = build_number if build_number else '13D15'
    name = app_name
    version = app_version
    os_and_version = '{} {}'.format(platform, os_version)
    device = device_model
    build = 'Build/{}'.format(build)
    result = '{}: {}/{} ({}; {}; {}; Proxy)'.format(platform, name, version, os_and_version, device, build)

    return result


def _google_channel_activate(idfa, app_name=None, app_version=None, platform=None, os_version=None,
                             device_model=None, uuid=None, client_ip=None, build_number=None):
    if not all([idfa, app_name, app_version, platform, os_version, device_model]):
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_INVALID_PARAMS}
    if platform.lower() == "android":
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    params_user_agent = {
        'app_name': app_name,
        'app_version': app_version,
        'platform': platform,
        'os_version': os_version,
        'device_model': device_model,
        'build_number': build_number,
    }
    user_agent = _form_google_user_agent(**params_user_agent)
    if not user_agent:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    params_request = {
        'dev_token': settings.DEV_TOKEN,
        'link_id': settings.LINK_ID,
        'app_event_type': 'first_open',
        'rdid': uuid,
        'id_type': 'idfa',
        'lat': 0,
        'app_version': app_version,
        'os_version': os_version,
        'sdk_version': app_version,
        'timestamp': time.time(),
    }
    params_header = {
        'User-Agent': user_agent,
        'X-Forwarded-For': client_ip,
        'Content-Length': 0,
    }

    res = requests.post(url=settings.GOOGLE_CHANNEL_URL, headers=params_header, params=params_request)
    if res.status_code != 200:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    res_json = res.json()
    if res_json and not res_json.get('attributed'):
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_NO_PROMOTION}

    time_now = datetime.datetime.now()
    params = {
        'idfa': idfa,
        'appid': PROMOTION_CHANNEL_NAME.GOOGLE,
        'update_time': time_now,
        'active_time': time_now,
        'callback_type': CHANNEL_CALLBACK_TYPE.POST_CALLBACK,
        'callback': res.url,
        'callback_response': res.text,
        'client_type': CLIENT_TYPE.USER,
        'platform_type': PLATFORM_CHANNEL.IOS
    }
    try:
        PromotionChannel.objects.create(**params)
        result = {'error': 0, 'msg': CHANNEL_STATUS.ACT_OK}
    except Exception as e:
        record_msg = 'google-activate-exception: %s, %s' % (e.message, params)
        channel_logger.error(record_msg)
        result = {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    return result


def _baidu_channel_activate(record):

    if not record.callback:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    callback = record.callback
    callback = callback.replace('{{ATYPE}}', 'activate')
    callback = callback.replace('{{AVALUE}}', '0')
    sign = md5(callback + settings.BAIDU_AKEY).hexdigest()

    res = requests.get(callback, params={'sign': sign})
    if res.status_code != 200:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    res_json = res.json()
    if res_json and res_json['error_code'] != 0:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_NO_PROMOTION}

    time_now = datetime.datetime.now()
    record.active_time = time_now
    record.update_time = time_now
    record.callback_response = res.text if res.text else ''
    record.save(update_fields=['active_time', 'update_time', 'callback_response'])

    return {'error': 0, 'msg': CHANNEL_STATUS.ACT_OK}


def _baidushouzhu_channel_activate(record):

    if not record.callback:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    packagename = "com.wanmeizhensuo.zhensuo"
    if not record.idfa and record.platform_type == PLATFORM_CHANNEL.UNKNOWN:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    app_type = 'android' if record.platform_type == PLATFORM_CHANNEL.ANDROID else 'ios'
    now_time = int(time.time())

    k_str = "activetime={activetime}apptype={app_type}clickid={clickid}packagename={packagename}".format(
        app_type=app_type, activetime=now_time, clickid=record.idfa, packagename=packagename
    )
    k = md5(k_str + settings.BAIDU_SHOUZHU).hexdigest()

    res = requests.get(record.callback, params={'activetime': now_time, 'apptype': app_type, 'clickid': record.idfa,
                                                 'k': k, 'packagename': packagename})
    if res.status_code != 0:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    res_json = res.json()
    if res_json and res_json['error_code'] != 0:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_NO_PROMOTION}

    time_now = datetime.datetime.now()
    record.active_time = time_now
    record.update_time = time_now
    record.callback_response = res.text if res.text else ''
    record.save(update_fields=['active_time', 'update_time', 'callback_response'])

    return {'error': 0, 'msg': CHANNEL_STATUS.ACT_OK}


def _mobilebaidu_channel_activate(record):
    if not record.callback:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    callback = record.callback
    callback = callback.replace('{{ATYPE}}', 'activate')
    callback = callback.replace('{{AVALUE}}', '0')

    sign = md5(callback + settings.MOBILE_BAIDU_KEY).hexdigest()

    res = requests.get(callback, params={'sign': sign})
    if res.status_code != 200:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    res_json = res.json()
    if res_json and res_json['error_code'] != 0:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_NO_PROMOTION}

    time_now = datetime.datetime.now()
    record.active_time = time_now
    record.update_time = time_now
    record.callback_response = res.text if res.text else ''
    record.save(update_fields=['active_time', 'update_time', 'callback_response'])

    return {'error': 0, 'msg': CHANNEL_STATUS.ACT_OK}


def _dianru_channel_activate(record, client_ip=None):

    params = {'drkey': record.active_key}
    if client_ip:
        params.update({'ip': client_ip})

    res = requests.get(settings.DIANRU_ACTIVATE_URL, params=params)
    if res.status_code != 200:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    res_json = res.json()
    if res_json['status'] != 1 or res_json['message'] != 'success':
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    time_now = datetime.datetime.now()
    record.active_time = time_now
    record.update_time = time_now
    record.callback_response = res.text if res.text else ''
    record.save(update_fields=['active_time', 'update_time', 'callback_response'])

    return {'error': 0, 'msg': CHANNEL_STATUS.ACT_OK}


def _general_channel_activate(record):

    time_now = datetime.datetime.now()
    record.active_time = time_now
    record.update_time = time_now
    update_fields = ['active_time', 'update_time', 'idfa', 'callback']
    error_status = 1
    msg = CHANNEL_STATUS.ACT_FAIL_GENERAL

    # 目前接入的渠道中钱咖无回调, 只要调用该接口就认为激活成功
    # make sure those callback required channels get called-back
    # some callback value as string '[callback]'
    channel_logger.info("通用回调函数---")

    headers={
        'Accept-Encoding': 'gzip',
        'Content-Type': 'application/x-www-form-urlencoded',
        'user-agent':"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36"
    }
    now_ts = time.time()
    placeholders = {
        '__TIMESTAMPMS__': str(int(now_ts * 1000)),
        '__TIMESTAMP__': str(int(now_ts)),
    }
    callback = record.callback or None
    if callback and callback.startswith(('http', 'HTTP','https','HTTPS')) and record.callback_type != CHANNEL_CALLBACK_TYPE.NO_CALLBACK:
        res = None

        url = urllib2.unquote(callback)
        for key, value in placeholders.items():
            url = url.replace(key, value)
        record.callback = url
        try:
            if record.callback_type == CHANNEL_CALLBACK_TYPE.GET_CALLBACK:
                channel_logger.info("{0} callback".format(record.appid))
                res = requests.get(url,timeout=60,headers=headers,verify=_VERIFIED)

            elif record.callback_type == CHANNEL_CALLBACK_TYPE.POST_CALLBACK:
                res = requests.post(url,timeout=60,headers=headers,verify=_VERIFIED)

            if res:
                if res.encoding == 'ISO-8859-1':
                    res.encoding = res.apparent_encoding

                channel_logger.info("{0}".format(res.text))

                record.callback_response = res.text or ''
                update_fields.append('callback_response')
                if res.status_code == 200:
                    error_status = 0
                    msg = CHANNEL_STATUS.ACT_OK
        except:
            # call back just let 3rd party know this, wont affect device ativate
            delayed_activate_callback.delay(url=url, callback_method=record.callback_type, idfa=record.idfa)
            logging_exception()
    else:
        channel_logger.info("无回调---")

    record.save(update_fields=update_fields)
    return {'error': error_status, 'msg': msg}


def _meiyou_channel_activate(record):
    '''
    美柚渠道激活回调
    '''
    # 更新数据库
    time_now = datetime.datetime.now()
    record.active_time = time_now
    record.update_time = time_now
    update_fields = ['active_time', 'update_time']
    error_status = 1
    msg = CHANNEL_STATUS.ACT_FAIL_GENERAL
    # 处理回调
    conv_time = time.time()
    conv_type = 3                # 激活type  3-激活; 4-激活并注册; 5-激活并付费
    request_params = json.loads(record.click_request)
    request_params.update(dict(conv_time=int(conv_time), conv_type=conv_type))
    query_string = urllib.urlencode(request_params)
    signature = auth_util.hash_hmac(settings.MEIYOU_AUTH_KEY, query_string)
    query_string = query_string + '&signature=' + signature
    callback_url = settings.MEIYOU_CALLBACK_URL + query_string

    res = requests.get(callback_url, verify=_VERIFIED)
    if res is not None:
        if res.encoding == 'ISO-8859-1':
            res.encoding = res.apparent_encoding
        record.callback_response = res.text or ''
        update_fields.append('callback_response')

        if res.status_code != 200:
            error_status = 0
            msg = CHANNEL_STATUS.ACT_OK

    record.save(update_fields=update_fields)
    return {'error': error_status, 'msg': msg}


def _youdao_channel_activate(conv_ext, record, conv_type=1):

    query_request = {
        'conv_ext': conv_ext.strip('__'),
        'conv_action': 'ios_activate'
    }

    time_now = datetime.datetime.now()
    record.active_time = time_now
    record.update_time = time_now
    record.save(update_fields=['active_time', 'update_time'])
    res = requests.get(url='http://conv.youdao.com/api/track', params=query_request)

    if res.status_code != 200:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    res_json = res.json()
    if res_json and res_json.get('code') and res_json['code'] == 'success':
        return {'error': 0, 'msg': CHANNEL_STATUS.ACT_OK}


def _xiaomi_channel_activate(record):
    '''小米回调激活'''
    secret_key="fmgyKWIhSTbjSAri"#通过小米广告平台获得
    callback_url="http://trail.e.mi.com/api/callback"


    channel_logger.info("xiaomi with......")

    click_request=json.loads(record.click_request)

    time_now = datetime.datetime.now()
    record.active_time = time_now
    record.update_time = time_now

    #转化时间,13位时间戳
    conv_time=int(round(time.time() * 1000))

    callback=click_request.get("callback")
    imei=click_request.get("imei")

    callback_url="{0}?&callback={1}&imei={2}&conv_time={3}".format(callback_url,callback,imei,conv_time)

    channel_logger.info(callback_url)
    #回调小米服务器
    try:
        response=requests.get(callback_url,timeout=60)

        channel_logger.info(response.text)
        if int(response.status_code)!=200:
            channel_logger.info("xiaomi callback fail")
            return JsonResponse({
                "code":1,#0为成功,其他为失败
                "failMsg":"回调服务器错误:{0}".format(response.status_code),#错误信息
            })
        elif int(response.json().get("code"))!=0:
            channel_logger.info("xiaomi callback fail")
            return JsonResponse(response.json())

    except ConnectionError as e:
        channel_logger.info(str(e))
        return JsonResponse({
            "code":1,#0为成功,其他为失败
            "failMsg":"连接小米服务器错误",#错误信息
        })
    channel_logger.info("xiaomi bottom..")
    record.save()


def _wangyi_youdao_channel_activate_new(record):
    """
    网易有道 新版回调
    :param record:
    :return:
    """
    _now = datetime.datetime.now()
    record.active_time = _now
    record.update_time = _now

    update_fields = ['active_time', 'update_time']
    error_status = 1
    msg = CHANNEL_STATUS.ACT_FAIL_GENERAL

    channel_logger.info("调用 网易有道 回调函数---")
    callback = record.callback or None

    if callback and callback.startswith(
            ('http', 'HTTP', 'https', 'HTTPS')
    ) and record.callback_type == CHANNEL_CALLBACK_TYPE.GET_CALLBACK:
        request_params = json.loads(record.click_request)
        platform = record.platform_type  # 设备

        if platform == PLATFORM_CHANNEL.IOS:
            _action = "ios_activate"

        elif platform == PLATFORM_CHANNEL.ANDROID:
            _action = "android_activate"

        else:
            _action = ""

        query_dic = {
            'conv_ext': request_params.get("conv", ""),
            'conv_action': _action,
        }

        callback_url = "{}?{}".format(callback, urllib.urlencode(query_dic))
        try:
            res = requests.get(callback_url)

            if res.encoding == 'ISO-8859-1':
                res.encoding = res.apparent_encoding

            _response_info_str = res.text
            _response_dic = res.json()

            if res.status_code == 200 and _response_dic.get("code", "") == "success":
                error_status = 0
                msg = CHANNEL_STATUS.ACT_OK

            channel_logger.info("网易有道回调! 回调地址:{0},回调结果:{1}".format(callback_url, _response_info_str))

            record.callback_response = _response_info_str or ''
            update_fields.append('callback_response')
        except:
            logging_exception()
            channel_logger.info("网易有道 回调失败。记录id:{}".format(record.id))
    else:
        channel_logger.info("无回调---")

    record.save(update_fields=update_fields)
    return {'error': error_status, 'msg': msg}


def _qutoutiao_channel_activate(record):
    """趣头条回调"""

    _now = datetime.datetime.now()
    record.active_time = record.update_time = _now

    update_fields = ['active_time', 'update_time']
    error_status = 1
    msg = CHANNEL_STATUS.ACT_FAIL_GENERAL

    channel_logger.info("调用 趣头条 回调函数---")
    callback = record.callback or None

    if callback and callback.startswith(
            ('http', 'HTTP', 'https', 'HTTPS')
    ) and record.callback_type == CHANNEL_CALLBACK_TYPE.GET_CALLBACK:

        url_info = get_url_info(urllib.unquote(callback))
        url_info["query"].append(("op2", 0))  # 安装app并首次打开

        callback_url = "{http}://{host}{path}?{query}".format(
            http=url_info["scheme"], host=url_info["host"], path=url_info["path"],
            query=urllib.urlencode(url_info["query"])
        )

        try:
            res = requests.get(callback_url)

            if res.encoding == 'ISO-8859-1':
                res.encoding = res.apparent_encoding

            if res.status_code == requests.codes.ok:
                error_status = 0
                msg = CHANNEL_STATUS.ACT_OK
                _response_info_str = res.text

                record.callback_response = _response_info_str or ''
                update_fields.append('callback_response')
            else:
                _response_info_str = ""

            channel_logger.info("趣头条 回调! 回调地址:{0}, 回调状态:{1},回调结果:{2}".format(
                callback_url, res.status_code, _response_info_str)
            )

        except:
            logging_exception()
            channel_logger.info("趣头条 回调失败。记录id:{}".format(record.id))
    else:
        channel_logger.info("无回调---")

    record.save(update_fields=update_fields)
    return {'error': error_status, 'msg': msg}


def _iqiyi_channel_activate(record):
    """ 爱奇艺激活"""
    callback_url = record.callback
    channel_logger.info('iqiyi channel callback url:{}'.format(callback_url))
    if not callback_url:
        return
    callback_url = urlparse.unquote(callback_url)
    params = {"event_type": 0}
    if record.callback_type == CHANNEL_CALLBACK_TYPE.GET_CALLBACK:
        res = requests.get(callback_url, params=params)
    else:
        headers = {'Content-Type': 'application/json'}
        res = requests.post(callback_url, headers=headers, data=params)

    channel_logger.info('iqiyi channel callback response:{}'.format(res.status_code))
    if res.status_code != 200:
        channel_logger.info('iqiyi channel http request fail idfa:{}'.format(record.idfa))
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    res_json = res.json()
    if res_json and res_json['status'] != 200:
        channel_logger.info('iqiyi channel activate fail idfa:{}'.format(record.idfa))
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_NO_PROMOTION}

    time_now = datetime.datetime.now()
    record.active_time = time_now
    record.update_time = time_now
    record.callback_response = res.text if res.text else ''
    record.save(update_fields=['active_time', 'update_time', 'callback_response'])

    return {'error': 0, 'msg': CHANNEL_STATUS.ACT_OK}


def _bilibili_channel_activate(record):
    """ B站激活"""
    callback_url = record.callback
    channel_logger.info('bilibili channel callback url:{}'.format(callback_url))
    if not callback_url:
        return
    callback_url = urlparse.unquote(callback_url)
    request_params = json.loads(record.click_request)
    params = {
        'conv_type': 'APP_FIRST_ACTIVE',
        'conv_time': int(time.time() * 1000),
        'client_ip': request_params.get('ip', ''),
        'track_id': request_params.get('trackid', ''),
    }

    if record.callback_type == CHANNEL_CALLBACK_TYPE.GET_CALLBACK:
        res = requests.get(callback_url, params=params)
    else:
        headers = {'Content-Type': 'application/json'}
        res = requests.post(callback_url, headers=headers, data=params)

    channel_logger.info('bilibili channel callback response:{}'.format(res.status_code))
    if res.status_code != 200:
        channel_logger.info('bilibili channel http request fail idfa:{}'.format(record.idfa))
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    try:
        res_json = res.json()
    except Exception:
        res_json = None
    if not res_json or res_json.get('code', -1) != 0:
        channel_logger.info('bilibili channel activate fail idfa:{}, res:{}'.format(record.idfa, res.content))
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_NO_PROMOTION}

    time_now = datetime.datetime.now()
    record.active_time = time_now
    record.update_time = time_now
    record.callback_response = res.text if res.text else ''
    record.save(update_fields=['active_time', 'update_time', 'callback_response'])

    return {'error': 0, 'msg': CHANNEL_STATUS.ACT_OK}


def _oppo_channel_activate(record):
    """oppo激活"""
    OPPO_AES_KEY = 'XGAXicVG5GMBsx5bueOe4w=='
    OPPO_SALT = 'e0u6fnlag06lc3pl'
    def aes_encrypt(text, key):
        key = key.decode('base64')
        obj = AES.new(key, AES.MODE_ECB)
        enc_s = obj.encrypt(pad(text.encode(), 16))
        return enc_s.encode('base64').strip()

    def signature_calc(data, timestamp, salt):
        _s = '%s%s%s' % (data, timestamp, salt)
        sign_str = hashlib.md5(_s).hexdigest()
        return sign_str

    callback_url = record.callback or 'https://api.ads.heytapmobi.com/api/uploadActiveData'
    channel_logger.info('oppo channel callback url:{}'.format(callback_url))
    if not callback_url:
        return
    now_t_ms = int(time.time() * 1000)
    callback_url = urlparse.unquote(callback_url)
    request_params = json.loads(record.click_request)
    params = {
        'dataType': 1,
        'timestamp': now_t_ms,
        'client_ip': request_params.get('ip', ''),
        'pkg': request_params.get('pkg', ''),
        'channel': 1,
    }
    if 'oaid' in request_params:
        params['ouId'] = aes_encrypt(request_params['oaid'], OPPO_AES_KEY)
    elif 'imei' in request_params:
        params['imei'] = aes_encrypt(request_params['imei'], OPPO_AES_KEY)
    else:
        return
    if 'ad_id' in request_params:
        params['adId'] = request_params['ad_id']

    if record.callback_type == CHANNEL_CALLBACK_TYPE.GET_CALLBACK:
        res = requests.get(callback_url, params=params)
    else:
        data_json_str = json.dumps(params, separators=(',', ':'))
        headers = {
            'Content-Type': 'application/json',
            'signature': signature_calc(data_json_str, now_t_ms, OPPO_SALT),
            'timestamp': now_t_ms,
        }
        import pdb; pdb.set_trace()
        res = requests.post(callback_url, headers=headers, data=data_json_str)

    channel_logger.info('oppo channel callback response:{}'.format(res.status_code))
    if res.status_code != 200:
        channel_logger.info('oppo channel http request fail idfa:{}'.format(record.idfa))
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_FAIL_GENERAL}

    try:
        res_json = res.json()
    except Exception:
        res_json = None
    if not res_json or res_json.get('ret', -1) != 0:
        channel_logger.info('oppo channel activate fail idfa:{}, res:{}'.format(record.idfa, res.content))
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_NO_PROMOTION}

    time_now = datetime.datetime.now()
    record.active_time = time_now
    record.update_time = time_now
    record.callback_response = res.text if res.text else ''
    record.save(update_fields=['active_time', 'update_time', 'callback_response'])

    return {'error': 0, 'msg': CHANNEL_STATUS.ACT_OK}


@bind('statistic/channel_promotion/add_record')
def add_channel_promotion_record(appid, idfa, client_type=CLIENT_TYPE.USER, callback_type=None, callback=None,
                                 click_request=None, active_key=None, platform_type=None, from_shequ=False):
    """
    渠道点击上传接口, hermes调用
    """
    if not all([appid, idfa]):
        return {'error': 1, 'msg': CHANNEL_STATUS.ADD_INVALID_PARAMS}

    if from_shequ:
        if SheQuDevice.objects.filter(device_id=idfa).exists():
            return {'error': 1, 'msg': CHANNEL_STATUS.ADD_ALREADY_ACTIVATED}

    else:
        if Device.objects.filter(device_id=idfa).exists():
            return {'error': 1, 'msg': CHANNEL_STATUS.ADD_ALREADY_ACTIVATED}

    result = {'error': 0, 'msg': CHANNEL_STATUS.ADD_OK}

    try:
        record, created = PromotionChannel.objects.get_or_create(appid=appid, idfa=idfa,
                                                                 defaults={'update_time': datetime.datetime.now()})

        record.callback_type = callback_type if callback_type in CHANNEL_CALLBACK_TYPE \
            else CHANNEL_CALLBACK_TYPE.NO_CALLBACK
        record.callback = callback if callback else ''
        record.click_request = click_request if click_request else ''
        record.client_type = client_type if client_type in CLIENT_TYPE else CLIENT_TYPE.USER
        record.active_key = active_key if active_key else ''
        record.update_time = datetime.datetime.now()
        record.record_from = ''
        record.platform_type = platform_type if platform_type else PLATFORM_CHANNEL.IOS

        record.save()
    except Exception as e:
        param_msg = '{appid},{idfa},{client_type},{callback_type},{callback},{click_request}'
        param_msg = param_msg.format(appid=appid, idfa=idfa, client_type=client_type, callback_type=callback_type,
                                     callback=callback, click_request=click_request)
        msg = 'add-channel-record-exception: %s, %s' % (e.message, param_msg)
        channel_logger.error(msg)
        result.update({'error': 1, 'msg': CHANNEL_STATUS.ADD_FAIL_GENERAL})

    return result


@bind('statistic/guangdiantong')
def guangdiantong_authorization(authorization_code):
    '''
        保存广点通的 authorization_code到redis
    '''
    get_token(authorization_code)
    return


@bind('statistic/channel_promotion/activate_record')
def activate_channel_promotion_record(
        idfa, app_name=None, app_version=None, platform=None, os_version=None,
        device_model=None, uuid=None, client_ip=None, build_number=None,
        client_type=CLIENT_TYPE.USER, oaid='',
):
    """
    渠道激活接口, backend调用
    """

    if not idfa:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_INVALID_PARAMS}
    channel_logger.info("*"*100)

    # ios的idfa默认为大写,android的idfa默认为小写
    if idfa.startswith('androidid_'):
        idfa = idfa.replace('androidid_', '')
    idfa_md5 = md5(idfa).hexdigest()

    channel_logger.info(idfa)
    channel_logger.info(idfa_md5)

    idfa_fvals = [idfa, idfa_md5]
    if oaid:
        idfa_fvals.append(oaid)

    exists = PromotionChannel.objects.filter(
        idfa__in=idfa_fvals, client_type=client_type, active_time__isnull=False
    ).exists()
    if exists:
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_ALREADY_ACTIVATED}

    record = PromotionChannel.objects.filter(
        idfa__in=idfa_fvals, client_type=client_type,
    ).order_by('-update_time').first()

    #如果已激活
    if record and record.active_time:
        channel_logger.info("already activate.")
        return {'error': 1, 'msg': CHANNEL_STATUS.ACT_ALREADY_ACTIVATED}

    # 谷歌推广, 无点击上传记录
    if not record:
        params = {
            'idfa': idfa,
            'app_name': app_name,
            'app_version': app_version,
            'platform': platform,
            'os_version': os_version,
            'device_model': device_model,
            'uuid': uuid,
            'client_ip': client_ip,
            'build_number': build_number
        }
        return _google_channel_activate(**params)

    #更新数据库的idfa
    record.idfa=idfa

    #手机百度推广 需要写在百度推广前面
    if record.appid.startswith(PROMOTION_CHANNEL_NAME.SHOUJIBAIDU):
        channel_logger.info("enter in baidu mobile.")
        func = _mobilebaidu_channel_activate
        params = {'record': record}

    # 百度推广, 回调需要独立的key
    elif record.appid.startswith(PROMOTION_CHANNEL_NAME.BAIDU):
        channel_logger.info("enter in baidu tuiguang")
        func = _baidu_channel_activate
        params = {'record': record}

    elif record.appid.startswith(PROMOTION_CHANNEL_NAME.BAIDUSHOUZHU):
        channel_logger.info("enter in baidu shouzhu")
        func = _baidushouzhu_channel_activate
        params = {'record': record}

    # 点入推广
    elif record.appid.startswith(PROMOTION_CHANNEL_NAME.DIANRU):
        channel_logger.info("enter in dianru!")
        func = _dianru_channel_activate
        params = {'record': record, 'client_ip': client_ip}

    # 网易有道
    elif record.appid.startswith(PROMOTION_CHANNEL_NAME.WANGYIYOUDAO):
        channel_logger.info("enter in wangyi youdao")
        temp = record.click_request
        func = _youdao_channel_activate
        obj = json.loads(temp)
        params = {'conv_ext': obj['conv'], 'record': record, 'conv_type': 1}

    # 网易有道 v2 add in 2019.10.18 不清楚为什么之前加的废弃了
    elif record.appid.startswith(PROMOTION_CHANNEL_NAME.WANGYIYOUDAO_V2):
        channel_logger.info("enter in wang yi you dao - wangyi!")
        params = {"record": record}
        func = _wangyi_youdao_channel_activate_new

    elif record.appid.startswith(PROMOTION_CHANNEL_NAME.MEIYOU):
        channel_logger.info("enter in meiyou")
        func = _meiyou_channel_activate
        params = {'record': record}

    # 趣头条
    elif record.appid.startswith(PROMOTION_CHANNEL_NAME.QUTOUTIAO):
        channel_logger.info("enter in qutoutiao")
        func = _qutoutiao_channel_activate
        params = {"record": record}

    #小米PROMOTION_CHANNEL_NAME.XIAOMI
    elif record.appid.startswith("promotion_xiaomi"):
        channel_logger.info("enter in xiao mi branch...")
        func=_xiaomi_channel_activate
        params = {'record': record}

    elif record.appid.startswith("promotion_guangdiantong"):
        channel_logger.info("enter in guangdiantong---")
        guangdiantong_active(record)

        func=_general_channel_activate
        params = {'record': record}

    elif record.appid.startswith(PROMOTION_CHANNEL_NAME.XINYOUXINGKONG):
        channel_logger.info("enter in xinyouxingkong")
        func = xinyouxingkong_active_record
        params = {'record': record}

    elif record.appid.startswith(PROMOTION_CHANNEL_NAME.IN_MOBI):
        channel_logger.info("enter in inmobi")
        func = inmobi_active_record
        params = {'record': record}

    # 爱奇艺
    elif record.appid.startswith(PROMOTION_CHANNEL_NAME.IQIYI):
        channel_logger.info('------- enter in iqiyi -------')
        func = _iqiyi_channel_activate
        params = {'record': record}

    elif record.appid.startswith(PROMOTION_CHANNEL_NAME.BILIBILI):
        channel_logger.info('enter in bilibili')
        func = _bilibili_channel_activate
        params = {'record': record}

    elif record.appid.startswith(PROMOTION_CHANNEL_NAME.OPPO):
        channel_logger.info('enter in oppo')
        func = _oppo_channel_activate
        params = {'record': record}

    else:   # 其他渠道, 通用回调
        channel_logger.info("通用渠道激活----")
        func = _general_channel_activate
        params = {'record': record}

    channel_logger.info("end")
    return func(**params)


@bind('statistic/like_channel_promotion/list')
def like_channels_list():
    """ Like channels 渠道列表（迁移） """
    results = LikePromotionInfo.objects.all()
    data = [{
        "id": item.id,
        "name": item.name,
        "code": item.code,
        "sub_code": item.sub_code,
        "platform": item.platform,
        "app": item.app,
        "appendtime": str(item.appendtime)
    } for item in results]

    return {
        "data": data
    }


@bind('statistic/like_channel_promotion/add')
def like_channels_add(param):
    """ Like Channels 渠道添加（迁移） """

    obj, created = LikePromotionInfo.objects.get_or_create(**param)

    return {
        "result": created
    }


