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

import json
from datetime import datetime

from django.db.models import Q

from gm_types.gaia import SECKILL_TYPE

from api.models import (
    Campaign,
    Special,
    CampaignLayout,
    CampaignCouponPage,
    CampaignImageLink,
    CAMPAIGN_MODULE,
)
from api.tool.datetime_tool import get_datetime
from api.tool.log_tool import logging_exception
from api.view.service import get_service_multiget_zone
from rpc.cache import common_cache
from rpc.tool.error_code import gen, CODES
from rpc.decorators import (
    bind, cache_page
)
from rpc.decorators import list_interface
from rpc.tool.dict_mixin import to_dict


@bind('api/campaign/get')
@cache_page(3600)
def get_campaign(id):
    """
    获取一个活动
    :param id 活动ID:
    return
    """
    try:
        campaign = Campaign.objects.get(pk=id)
        return campaign.data()
    except Campaign.DoesNotExist:
        gen(CODES.CAMPAIGN_NOT_FOUND)


@bind("api/campaign/coupongift_direct_claim")
@list_interface(
    offset_name='offset', limit_name='limit', element_model=Campaign,
    element_func_list=[Campaign.data]
)
def campaign_direct_claim_coupongift_list(campaign_id, offset=0, limit=10):
    """get coupongift list for directly claim."""
    try:
        campaign = Campaign.objects.get(id=campaign_id)
    except Campaign.DoesNotExist:
        gen(CODES.CAMPAIGN_NOT_FOUND)

    result = {
        'coupons': [],
        'share': None,
        'rules': campaign.campaigncouponpage.rule,
        'banner': campaign.campaigncouponpage.banner,
        'gifts': [],
    }

    if campaign.campaigncouponpage.share:
        result['share'] = campaign.campaigncouponpage.share.to_dict()

    # get coupongifts
    gifts = campaign.campaigncouponpage.campaigngift_set.order_by('ordering')
    gifts = gifts[offset:offset + limit]
    for g in gifts:
        result['gifts'].append(g.gift.info_data)

    return result


@bind("api/campaign/get_coupons/v2")
@list_interface(offset_name='offset', limit_name='limit', element_model=Campaign, element_func_list=[Campaign.data])
def get_campaign_coupons_v2(id, is_recommand=None, offset=0, limit=10):
    """TODO: delete this after coupon refactor alive.

    获取一个活动下的优惠券.
    :param id 活动ID:
    :param is_recommand 是否是首页推荐优惠券:
    :param offset:
    :param limit:
    return:
    """
    try:
        campaign = Campaign.objects.get(pk=id)
    except Campaign.DoesNotExist:
        gen(CODES.CAMPAIGN_NOT_FOUND)
    try:
        coupons_t = campaign.campaigncouponpage.coupons
    except CampaignCouponPage.DoesNotExist:
        gen(CODES.CAMPAIGNPAGE_NOT_FOUND)

    q = Q()
    if is_recommand is not None:
        q &= Q(is_recommand=is_recommand)

    _d = {}
    coupons = coupons_t.filter(q)[offset:(offset + limit)]
    for coupon in coupons:
        _d[coupon.id] = coupon.data()

    cps = []
    coupons_t = campaign.campaigncouponpage.campaigncoupon_set.order_by(
        'ordering')
    for c in coupons_t:
        if c.coupon_id not in _d:
            continue
        cps.append(_d[c.coupon_id])

    result = {
        'coupons': cps,
        'share': None,
        'rules': campaign.campaigncouponpage.rule,
        'banner': campaign.campaigncouponpage.banner,
    }

    if campaign.campaigncouponpage.share:
        result['share'] = campaign.campaigncouponpage.share.to_dict()

    return result


@bind("api/campaign/get_specials")
@list_interface(
    offset_name='offset',
    limit_name='limit',
    element_model=Special,
    element_func_list=[Special.data]
)
def get_campaign_specials(id, start_time=None, end_time=None,
                          some_time=None, is_seckill=None, is_overflow=None,
                          offset=0, limit=10):
    """
    获取一个活动下的各种专场
    :param id 活动ID:
    :param start_time 开始时间:
    :param end_time 结束时间:
    :param some_time 某个时间，用于找到此时间落到的时间范围内的专场
    :param is_seckill 是否是秒杀专场:
    :param is_overflow 是否是超值专场:
    :param offset:
    :param limit:
    return:
    """
    result = []
    try:
        campaign = Campaign.objects.get(pk=id)
        q = Q()
        if is_seckill is not None:
            q &= Q(is_seckill=is_seckill)
        if is_overflow is not None:
            q &= Q(is_overflow=is_overflow)
        if start_time and end_time:
            start = get_datetime(start_time)
            end = get_datetime(end_time)
            q &= Q(start_time__gte=start)
            q &= Q(end_time__lt=end)
        if some_time:
            some_time = get_datetime(some_time)
            q &= Q(start_time__lte=some_time)
            q &= Q(end_time__gt=some_time)
        specials = campaign.specials.filter(q).order_by('rank')[
            offset:(offset + limit)]
        for special in specials:
            result.append(special.data())
        return result
    except Campaign.DoesNotExist:
        gen(CODES.CAMPAIGN_NOT_FOUND)


@bind("api/seckill/list")
@list_interface(offset_name='offset', limit_name='limit', element_model=Special, element_func_list=[Special.data])
def get_seckill_specials(start_time=None, end_time=None, offset=0, limit=50):
    """
    取秒杀专场
    """
    result = []
    try:
        q = Q(is_seckill=True) & Q(is_online=True) & Q(seckill_type=SECKILL_TYPE.GENGMEI)
        if start_time and end_time:
            start = get_datetime(start_time)
            q &= Q(start_time__gte=start)
            # q &= Q(end_time__lt=end)
            # 结束时间不做为筛选条件

        specials = Special.objects.filter(q).order_by('start_time')[
            offset:(offset + limit)]
        for special in specials:
            result.append(special.data())
    except:
        logging_exception()

    return result


@bind("api/seckill/get")
def get_seckill(special_id):
    """
    取秒杀专场
    """
    try:
        seckill = Special.objects.get(id=special_id)
        return seckill.data()
    except Special.DoesNotExist:
        return gen(CODES.SPECIAL_DOES_NOT_EXIST)


@bind('api/campaingn/campaingnlayout_relation_list')
@cache_page(120)
def get_campaingnlayout_relation_list(campaign_id=None):
    """
    NOTE:
        Desc: 根据campaingn_id获取活动所有关联的banner id等等的关联的id列表和顺序
        :param campaingnlayout_id:
        :return:
        change log: v5.6.0
    """
    query = Q(campaign_id=campaign_id) & Q(is_visible=True)
    campaingnlayout_list = CampaignLayout.objects.filter(
        query).order_by("ordering")

    campaingn_id_list = []
    for info in campaingnlayout_list:
        related = info.related
        info = to_dict(info)
        content, ids = '', []

        if info.get('module') == CAMPAIGN_MODULE.DESCRIPTION:
            content = related
        elif info.get('module') == CAMPAIGN_MODULE.DESCRIPTION2:
            content = related
        elif info.get('module') == CAMPAIGN_MODULE.DESCRIPTION3:
            content = related
        elif info.get('module') == CAMPAIGN_MODULE.COUPON_FETCH:
            content = related
        else:
            ids = info['related']

        campaingn_id_list.append({
            'module': info['module'],
            'id': ids,
            'content': content,
        })

    return campaingn_id_list


@bind('api/campaingn/campaingnlayout_detail')
@cache_page(120)
def get_campaingnlayout_info(imagelink_id):
    """
    NOTE:
        Desc: 根据campaingnlayout中获取的id和module type来获取详细信息
        :return:
        :param campaingn_id:
        change log: v5.6.0
    """
    query = Q(id=imagelink_id) & Q(is_online=True)

    try:
        imagelink = CampaignImageLink.objects.get(query)
    except CampaignImageLink.DoesNotExist:
        return []

    return to_dict(imagelink)


@bind('api/newest_gengmei_seckill_info')
def get_current_gengmei_seckill_detail():
    """获取当前更美秒杀专场或者下一个专场点信息"""
    newest_gengmei_seckill_info = common_cache.get('newest_gengmei_seckill_info')
    if newest_gengmei_seckill_info is None:
        newest_gengmei_seckill_info = Special.get_newest_gengmei_seckill_info()
        common_cache.set('newest_gengmei_seckill_info', json.dumps(newest_gengmei_seckill_info), 30)
        return newest_gengmei_seckill_info
    return json.loads(newest_gengmei_seckill_info)


@bind('api/campaingn/newest_seckill_info')
def get_current_seckill_detail():
    """
    NOTE:
        Desc: 获取当前秒杀专场或者下一个专场点信息
        :return:
        change log: v5.6.0
    """
    result = {}
    try:
        query = Q(is_seckill=True) & Q(is_online=True)
        current_time = datetime.now()
        query &= Q(start_time__lt=current_time)
        query &= Q(end_time__gte=current_time)
        specials = Special.objects.filter(query).order_by('-start_time')

        if not len(specials):
            query = Q(is_seckill=True) & Q(is_online=True)
            query &= Q(start_time__gt=current_time)
            specials = Special.objects.filter(query).order_by('start_time')

        result = specials[0].data() if specials else {}

    except:
        logging_exception()
        return {}

    return result


@bind('api/campaingn/campaingnlayout_promotion_zone')
@cache_page(120)
def get_campaingnlayout_promotion_zone(campaign_id=None):
    """
    NOTE:根据campaingn_id获取活动所有关联的美购分区
    """
    result = {}
    try:
        query = Q(campaign_id=campaign_id) & Q(is_visible=True) & \
                    Q(module=CAMPAIGN_MODULE.SERVICE_ZONE)
        promotion_zones = CampaignLayout.objects.get(query)
    except CampaignLayout.DoesNotExist:
        return result

    related = promotion_zones.related
    try:
        related = json.loads(related)
    except:
        logging_exception()
        return result

    result['banner'] = related[0]
    zones = related[1:]
    zone_list = []
    for zone_items in zones:
        tmp_zone = {}
        for zone_item in zone_items:
            if isinstance(zone_item, basestring):
                tmp_zone['banner'] = zone_item
                tmp_zone['lst'] = []
            elif isinstance(zone_item, list):
                tmp_service = {}
                tmp_service['tab'] = zone_item[0]
                service_ids = zone_item[1:]
                tmp_service['benefits'] = get_service_multiget_zone(service_ids)
                tmp_zone['lst'].append(tmp_service)
        zone_list.append(tmp_zone)
    result['zones'] = zone_list
    return result


@bind('api/campaingn/get_special_info')
def get_special_info_by_id(special_id):
    try:
        s = Special.objects.get(id=special_id)
        return {
            'special_name': s.title
        }
    except Special.DoesNotExist:
        logging_exception()
