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

from django.db.models import F

from gm_types.gaia import COUPON_TYPES

from api.tool.service_tool import get_serviceitem_by_option_id
from api.tool.user_tool import get_user_from_context
from api.tool.log_tool import logging_exception
from api.tool.buryiny_point_tool import add_to_shopcart
from api.tool.geo_tool import get_location_tag_id_by_city_id
from api.models import Service, ServiceItem, Shopcart
from api.models.types import PAYMENT_TYPE
from api.models import Order, CouponInfo
from api.view.coupon import get_unclaimed_coupons_dict_for_coupon_gift, get_forge_couponinfo
from api.view.settlement import get_couponinfo_deduction
from api.manager.coupon_manager import get_coupon_gift_info_for_service_detail_with_type
from api.manager.service_info_manager import get_toc_spu_info_list_mapping_by_spu_ids
from pay.manager import settlement_manager

from search.utils.service import filter_service

from rpc.tool.error_code import gen, CODES
from rpc.decorators import bind_context
from rpc.context import get_rpc_remote_invoker
from rpc.tool.log_tool import info_logger
from rpc.decorators import list_interface
from gm_types.gaia import SERVICE_ORDER_TYPE


@bind_context('api/shopcart/add/number', login_required=True)
def api_shopcart_add_number(ctx, service_item_id, number):
    user = get_user_from_context(ctx)

    number = int(number)

    now = datetime.datetime.now()

    if number <= 0 or number > 1024:
        return gen(CODES.SUCCESS)

    service_item = ServiceItem.objects.get(id=service_item_id, is_delete=False)
    gengmei_price = service_item.gengmei_price

    if service_item.service.payment_type in (PAYMENT_TYPE.FREE_PAYMENT, PAYMENT_TYPE.EXCHANGE_GIFT):
        return gen(CODES.SERVICE_CAN_NOT_ADD_TO_SHOPCART)

    Shopcart.add_or_create(user.person.id, service_item.service.id, service_item.id, number, gengmei_price, now)

    # 数据埋点, http://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=23892080
    try:
        ctx.logger.app(**add_to_shopcart(service_id=service_item.service.id, user_id=user.id))
    except:
        pass

    return gen(CODES.SUCCESS)


@bind_context('api/shopcart/set/number', login_required=True)
def api_shopcart_set_number(ctx, shopcart_id, number):
    user = get_user_from_context(ctx)

    now = datetime.datetime.now()

    update_count = 0

    number = int(number)

    if 1024 > number > 0:
        service_item_id = Shopcart.objects.filter(
            person=user.person, id=shopcart_id).values_list('service_item_id', flat=True).first()
        try:
            service_item = ServiceItem.objects.get(id=service_item_id, is_delete=False)
            gengmei_price = service_item.gengmei_price

            update_count = Shopcart.objects.filter(
                person=user.person, id=shopcart_id
            ).update(
                number=number, update_time=now,
                gengmei_price_at_add=gengmei_price,
                gengmei_price_at_last_push=gengmei_price,
            )
        except ServiceItem.DoesNotExist:
            return update_count

    return update_count


@bind_context('api/shopcart/delete', login_required=True)
def api_shopcart_delete(ctx, id):
    """delete item in shopcart."""
    user = get_user_from_context(ctx)

    try:
        sc = Shopcart.objects.get(id=id, person=user.person)
    except Shopcart.DoesNotExist:
        return gen(CODES.SHOPCART_ITEM_NOT_FOUND)

    sc.delete()
    return gen(CODES.SUCCESS)


@bind_context('api/shopcart/list/v1', login_required=True)
def api_shopcart_list(ctx, start_num=0, count=10):
    """list items in shopcart."""
    user = get_user_from_context(ctx)

    scs = Shopcart.objects.filter(person=user.person, service_item__is_delete=False)
    # total_num = scs.count()
    # scs_obj = scs.order_by('-update_time')[start_num:start_num + count]
    scs_obj = scs.order_by('-update_time')

    cart = Shopcart.get_shopcart_info_list(scs_obj)
    all_valid_num = 0
    for c in cart:
        if c.get('shopcart_item_can_sold'):
            all_valid_num += 1
    cart = cart[start_num:start_num + count]
    return {
        'total_num': all_valid_num,
        'cart': cart,
    }


@bind_context('api/shopcart/get_discount_price')
def get_discount_price(ctx, cart_item_info, promotion_item_relation=None):
    """获取购物车页预付款券后价"""
    user = get_user_from_context(ctx)
    service_ids = []
    if cart_item_info:
        shopcart_ids = [item['id'] for item in cart_item_info]
        service_ids = Shopcart.objects.filter(id__in=shopcart_ids).values_list('service_id', flat=True)
    # 1、拿到可领的券 2、把券塞给用户 3、走下单流程
    # 价格竞争力3期
    # 根据 user service_id 获得美券礼包的信息
    coupon_gifts_info_list = []
    for service_id in service_ids:
        coupon_gifts_info = get_coupon_gift_info_for_service_detail_with_type(service_id, user=user, count=500, gift_type=COUPON_TYPES.PLATFORM)
        coupon_gifts_info_list.extend(coupon_gifts_info)
    # 从美券大礼包里拿出 去重后的未领取的美券的信息 以及张数和
    coupons_dict, _ = get_unclaimed_coupons_dict_for_coupon_gift(coupon_gifts_info_list)
    # 把未领取的美券塞进CouponInfo表，伪造CouponInfo表的信息
    now = datetime.datetime.now()
    forge_cps = get_forge_couponinfo(coupons_dict, user, now)
    service_item_id_to_ordering_info = settlement_manager.get_service_item_id_to_ordering_info(
        cart_item_info,
        None, 0,
        user, None, promotion_item_relation
    )

    promotion_ids = promotion_item_relation.keys() if promotion_item_relation else []
    couponinfos = CouponInfo.valid_coupons(user, service_item_id_to_ordering_info, promotion_ids=promotion_ids)

    couponinfos += CouponInfo.get_vaild_coupons(service_item_id_to_ordering_info, forge_cps, promotion_ids=promotion_ids)
    coupon_deduction_info = get_couponinfo_deduction(
        couponinfos, service_item_id_to_ordering_info,
        use_platform_and_doctor_coupon=True,
        coupon_id=None, auto_select_best_coupon=True,
        platform_coupon_id=None, auto_select_platform=True,
        doctor_coupon_id=None, auto_select_doctor=False,
    )
    pre_discount_price = coupon_deduction_info['used_platform_coupon_info'].get('value', 0)
    return pre_discount_price


@bind_context('api/shopcart/recommend/service/list', login_required=True)
def api_shopcart_recommend_service_list(ctx, current_city_id=None, start_num=0, size=10, device_id=None, check_in=False):
    """
    获取购物车推荐数据
    :param ctx:
    :param start_num:
    :param count:
    :return:
    """
    valid_service_ids, city_tag_id = set(), None
    user = get_user_from_context(ctx)
    if not user:
        return gen(CODES.LOGIN_REQUIRED)

    scs = Shopcart.objects.filter(person=user.person, service_item__is_delete=False)
    scs_obj = scs.order_by('-update_time')
    cart = Shopcart.get_shopcart_info_list(scs_obj)

    if current_city_id:
        _, city_tag_id = get_location_tag_id_by_city_id(current_city_id)

    # 获取未失效的美购
    for c in cart:
        if not c.get('shopcart_item_can_sold'):
            continue

        valid_service_ids.add(c["service_id"])

    # 调用策略接口
    rpc_client = get_rpc_remote_invoker()
    query_params = {
        "user_city_tag_id": city_tag_id,
        "user_id": user.id,
        "start_num": start_num,
        "size": size,
        "cl_id": device_id,
        'check_in': check_in,
    }
    try:
        rs = rpc_client['doris/hera/in_city_whitelist'](city_ids=[current_city_id, ]).unwrap()
        in_whitelist = int(bool(rs))
    except:
        in_whitelist = 0

    query_params["in_whitelist"] = in_whitelist
    services = {}
    try:
        services = rpc_client['doris/recommend/shopcart/service'](
            service_ids=list(valid_service_ids), query_params=query_params,
        ).unwrap()
    except Exception:
        logging_exception()

    recommend_service_ids = services.get("service_ids", [])
    info_logger.info("service_ids:" + json.dumps(recommend_service_ids))
    services_info_dic = get_toc_spu_info_list_mapping_by_spu_ids(recommend_service_ids)
    info_logger.info("service_ids_len_1:" + json.dumps(len(services_info_dic)))
    recommend_services = [services_info_dic[str(sid)]
                                    for sid in recommend_service_ids if str(sid) in services_info_dic]
    info_logger.info("service_ids_len_2:" + json.dumps(len(services_info_dic)))
    return {
        'recommend_services': recommend_services,
    }


@bind_context('api/shopcart/recommend/service/list_v2', login_required=True)
def api_shopcart_recommend_service_list_v2(ctx, current_city_id=None, start_num=0, size=10, device_id=None, check_in=False):
    """
    获取购物车推荐数据
    :param ctx:
    :param start_num:
    :param count:
    :return:
    """
    valid_service_ids, city_tag_id = set(), None
    user = get_user_from_context(ctx)
    if not user:
        return gen(CODES.LOGIN_REQUIRED)

    scs = Shopcart.objects.filter(person=user.person, service_item__is_delete=False)
    scs_obj = scs.order_by('-update_time')
    cart = Shopcart.get_shopcart_info_list(scs_obj)

    if current_city_id:
        _, city_tag_id = get_location_tag_id_by_city_id(current_city_id)

    # 获取未失效的美购
    for c in cart:
        if not c.get('shopcart_item_can_sold'):
            continue

        valid_service_ids.add(c["service_id"])

    # 调用策略接口
    rpc_client = get_rpc_remote_invoker()
    query_params = {
        "user_city_tag_id": city_tag_id,
        "user_id": user.id,
        "start_num": start_num,
        "size": size,
        "cl_id": device_id,
        'check_in': check_in,
    }
    try:
        rs = rpc_client['doris/hera/in_city_whitelist'](city_ids=[current_city_id, ]).unwrap()
        in_whitelist = int(bool(rs))
    except:
        in_whitelist = 0

    query_params["in_whitelist"] = in_whitelist
    services = {}
    try:
        services = rpc_client['doris/recommend/shopcart/service'](
            service_ids=list(valid_service_ids), query_params=query_params,
        ).unwrap()
    except Exception:
        logging_exception()

    recommend_service_ids = services.get("service_ids", [])
    info_logger.info("service_ids:" + json.dumps(recommend_service_ids))
    return {
        'recommend_service_ids': recommend_service_ids,
    }
