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

import json

from django.db.models import Q
from gm_types.gaia import TAG_TYPE, DOCTOR_TYPE, ACTIVITY_TYPE_ENUM, SERVICE_SELL_TYPE, TAG_V3_TYPE

from api.manager.service_info_manager import service_cache_wrap
from agile.models.tag import TagV3Relation, TagV3
from api.manager.tag_manager import get_service_new_tags, get_service_tags
from api.models import (
    Service, ServiceVideo, CouponInfo,
    Special, ServiceItem,
    ImageRelatedService, Doctor, OrganizationImage, Tag, TagRelation)
from api.tool.image_utils import get_full_path
from api.tool.log_tool import logging_exception, info_logger, cache_logger
from api.tool.service_tool import sell_count_display
from api.tool.user_tool import get_user_from_context
from rpc.cache import service_score_tag_avg
from rpc.decorators import bind, cache_page, bind_context
from rpc.tool.error_code import gen, CODES
from rpc.exceptions import GaiaRPCFaultException

from api.manager import service_info_manager
from api.manager import groupbuy_manager
from .goods_service.service_utils import get_show_special_info, get_service_header_pic_info, calcate_sku_discount_price


@bind_context('api/service/base_service_info')
def get_base_service_info(ctx, service_id, coupon_info_id=None, support_groupbuy=False):
    # 这里添加support_groupbuy参数, 默认为False, 对ship端接口调用表现一致,backend端设置参数为True, 拼团部分不做灰度控制
    try:
        service = Service.objects.get(id=service_id)
    except:
        return gen(CODES.SERVICE_NOT_EXSIT)

    user = get_user_from_context(ctx)
    data = service.get_base_service_detail(user, support_groupbuy)

    coupon_info = None

    if coupon_info_id:
        ci = CouponInfo.objects.filter(id=coupon_info_id).first()
        if ci and ci.user == user:
            coupon_info = ci

    multiattributes = service.get_multiattributes(coupon_info)

    data['multiattributes'] = multiattributes
    # 拼团部分不做灰度控制
    if support_groupbuy:
        sku_info = service.get_sku_detail_info(coupon_info)
        data['sku_info'] = sku_info

    special_list, seckill_list = [], []
    special_info_dict = service.get_can_sell_item_ids_and_current_special_info()
    for siid, sp_info in special_info_dict.items():
        if not sp_info.get('id'):
            continue

        if sp_info and sp_info.get('activity_type') == ACTIVITY_TYPE_ENUM.SECKILL:
            seckill_list.append(sp_info['id'])
        else:
            # special_list.append(sp_info['id'])  # 暂时先隐藏
            pass

    if len(seckill_list) > 0:
        data['special_id'] = max(seckill_list)
        s = Special.objects.get(id=data['special_id'])
        data['special_info'] = s.title
        data['is_seckill'] = s.is_seckill
        data['is_new_special'] = False
        data['special_seckill_type'] = s.seckill_type
    elif len(special_list) > 0:
        data['special_id'] = max(special_list)
        s = Special.objects.get(id=data['special_id'])
        data['special_info'] = s.title
        data['is_seckill'] = s.is_seckill
        data['is_new_special'] = s.is_new_special
        data['special_seckill_type'] = ''
    else:
        data['special_id'] = ''
        data['special_info'] = ''
        data['is_new_special'] = False
        data['is_seckill'] = False
        data['special_seckill_type'] = ''
    data['header_pic'] = []
    data_video = ServiceVideo.objects.filter(service=service_id)
    if data_video:
        video_info = data_video[0].get_video_info()
        data['header_pic'].append({'video_url':video_info.get('video_url'),'pic':video_info.get('video_pic')})
    data['header_pic'].append({'video_url':'','pic':data['pic']})
    return data


@bind_context('api/service/base_service_info_v2')
def get_base_service_info_v2(ctx, service_id, coupon_info_id=None):
    '''
    since: 7710
    获取基础美购信息---
    '''
    user = get_user_from_context(ctx)
    try:
        service = Service.objects.get(id=service_id)
    except:
        return gen(CODES.SERVICE_NOT_EXSIT)

    support_groupbuy = service.service_type != SERVICE_SELL_TYPE.FLAGSHIP_STORE_SERVICE
    data = service.get_base_service_detail(user, support_groupbuy=support_groupbuy)

    special_info = get_show_special_info(service)
    data.update(special_info)
    data['header_pic'] = get_service_header_pic_info(service)[:6]
    return data


@bind('api/service/get_service_feature')
def get_service_features(service_id):
    service = Service.objects.filter(id=service_id).first()
    if not service:
        return {}
    return service.get_service_features()


@bind('api/service/get_service_base_comment')
def get_service_base_comment(service_id):
    return {
        'count': '0',
        'tags': [],
        'comment': []
    }


@bind('api/service/get_group_buy_rolling_info')
def get_group_buy_rolling_info(service_id):
    '''
    获取美购详情页中 基于sku的跑马灯信息 及 基于全场的拼团成功提示
    '''
    unfinished_groupbuy_team_info = groupbuy_manager.get_groupbuy_unfinished(None, service_id=service_id)
    un_format_list = []
    for k, v in unfinished_groupbuy_team_info.items():
        un_format_list.append({
            'service_item_id': k,
            'groupbuy_teams': v
        })
    suc_top_show_info = groupbuy_manager.get_groupbuy_success_show_info()
    result = {
        'groupbuy_info_rolling': un_format_list,
        'groupbuy_suc_top': suc_top_show_info
    }
    return result


@bind('api/service/get_doctor_info')
@cache_page(60 * 5)
def get_service_doctor_info(service_id):
    service = Service.objects.select_related('doctor__hospital').get(id=service_id)
    return service.get_doctor_info()


@bind('api/service/get_hospital_doctor_info')
@cache_page(60 * 5)
def get_service_hospital_and_doctor_info(service_id):
    try:
        service = Service.objects.select_related('doctor__hospital').get(id=service_id)
        return service.get_hospital_and_doctor_info()
    except:
        return gen(CODES.SERVICE_NOT_EXSIT)


@bind('api/service/get_related_service')
def get_related_service(service_id):
    data = []
    service = Service.objects.get(id=service_id)
    recommand_service = service.get_recommend_services_object().exclude(recommend_service_id=service_id)
    exclude_ids = []
    service_id_list = service_info_manager.add_double_eleven_image()

    for recommand in recommand_service:
        service = recommand.recommend_service
        double_eleven_image = ''
        if service.id in service_id_list:
            double_eleven_image = 'https://heras.igengmei.com/serviceactivity/2019/10/21/d9c715646c'
        d = {
            'service_id': service.id,
            'service_name': service.project_type.name if service.project_type else service.name,
            'prices': service.gengmei_price_display,
            'is_multiattribute': service.is_multiattribute,
            'pic': get_full_path(service.image_header, '-half'),
            'is_recommend': True,
            'double_eleven_image': double_eleven_image,
        }
        exclude_ids.append(service.id)
        if service.is_multiattribute:
            d['prices'] = d['prices'].split('-')[0]
        data.append(d)

    services = Service.objects.filter(doctor=service.doctor,
                                      is_online=True).exclude(id__in=exclude_ids).exclude(id=service_id)
    services = services[0:9 - len(data)]
    for service in services:
        double_eleven_image = ''
        if service.id in service_id_list:
            double_eleven_image = 'https://heras.igengmei.com/serviceactivity/2019/10/21/d9c715646c'
        d = {
            'service_id': service.id,
            'service_name': service.project_type.name if service.project_type else service.name,
            'prices': service.gengmei_price_display,
            'is_multiattribute': service.is_multiattribute,
            'pic': get_full_path(service.image_header, '-half'),
            'is_recommend': False,
            'double_eleven_image': double_eleven_image,
        }
        if service.is_multiattribute:
            d['prices'] = d['prices'].split('-')[0]
        data.append(d)
    return data


@bind('api/service/get_related_service_hybrid')
def get_related_service_hybrid(service_id, start_num, count):
    service = Service.objects.get(id=service_id)
    services = Service.objects.filter(doctor=service.doctor, is_online=True)
    services = services[start_num:start_num + count]
    data = []
    for service in services:
        data.append({
            'id': service.id,
            'image': get_full_path(service.image_header, '-half'),
            'desc': service.name,
            'price': min(service.gengmei_price_list),
            'is_price_range': service.is_multiattribute,
            'appoint_count': sell_count_display(service.sell_amount_display),
            'label': service.label,
            'is_soldout': service.is_can_be_sold()
        })
    return data


@bind('api/service/guess_you_like')
def get_guess_you_like(service_id, start_num, count, user_city_tag_id=None, user_city_id=None, use_tagv3=False):
    service = Service.objects.select_related('doctor').get(id=service_id)

    hospital_id = service.doctor.hospital_id if service.doctor and service.doctor.hospital_id else None

    if hospital_id is None:
        return []

    tag_list = []
    data = []
    new_tag_list = []
    if use_tagv3:
        tags = service.new_tags.all()
        for tag in tags:
            if tag.tag_type == TAG_V3_TYPE.SECOND_CLASSIFY:
                new_tag_list.append(tag.id)
            if tag.tag_type == TAG_V3_TYPE.NORMAL:
                parents_relations = TagV3Relation.objects.filter(child=tag, is_online=True)
                p_tags = [r.parent for r in parents_relations]
                # p_tags = tag.parent_tags()
                for p_tag in p_tags:
                    if p_tag.tag_type == TAG_V3_TYPE.SECOND_CLASSIFY:
                        new_tag_list.append(p_tag.id)
    else:
        tags = service.tags.all()
        for tag in tags:
            if tag.tag_type == TAG_TYPE.BODY_PART_SUB_ITEM:
                tag_list.append(tag.id)
            if tag.tag_type == TAG_TYPE.ITEM_WIKI:
                p_tags = tag.parent_tags()
                for p_tag in p_tags:
                    if p_tag.tag_type == TAG_TYPE.BODY_PART_SUB_ITEM:
                        tag_list.append(p_tag.id)

    try:
        from rpc.context import get_rpc_remote_invoker

        # max_size = 20
        query_size = count + 5  # 多捞几个，避免几种不同方式里面有当前service_id导致捞不足够max_size

        tag_id = None
        if len(tag_list) > 0:
            tag_id = tag_list[0]
        tagv3_id=None
        if len(new_tag_list) > 0:
            tagv3_id = new_tag_list[0]

        user_city_info = {}
        if user_city_tag_id and user_city_id:
            user_city_info = {
                "user_city_tag_id": user_city_tag_id,
                "user_city_id": user_city_id,
            }

        result = get_rpc_remote_invoker()['doris/search/guess_you_like_service'](
            hospital_id=hospital_id, tagv3_id=tagv3_id, use_tagv3=use_tagv3,
            tag_id=tag_id, user_city_info=user_city_info, service_id=service_id,
            offset=start_num, size=query_size).unwrap()

        # 去掉潜在重复的id（当前美购id），然后把冗余的数据去掉，只要前20条
        result_ids = [sid for sid in result['service_ids'] if sid != service_id][:20]
        service_ids = result_ids[start_num: start_num + count]

        sid_to_service_info = service_info_manager.get_toc_spu_info_list_mapping_by_spu_ids(service_ids)

        for sid in service_ids:
            if str(sid) in sid_to_service_info:
                si = sid_to_service_info[str(sid)]
                try:
                    data.append({
                        'id': si["service_id"],
                        'image': get_full_path(si["image_header"], '-half'),
                        'desc': si["service_name"],
                        'price': si["seckill_price"] if si["is_seckill"] else si["gengmei_price"],
                        'is_price_range': si["is_price_range"],
                        'appoint_count': sell_count_display(si["sell_amount"]),
                        'label': si["label"],
                        'is_soldout': si["is_can_be_sold"],
                        'double_eleven_image': si.get("double_eleven_image") or '',
                    })
                except:
                    logging_exception()
        return data
    except:
        logging_exception()
        return []


@bind('api/service/guess_you_like_v2')
def get_guess_you_like_v2(service_id, start_num, count, user_city_tag_id=None, user_city_id=None, use_tagv3=False):
    service = Service.objects.select_related('doctor').get(id=service_id)

    hospital_id = service.doctor.hospital_id if service.doctor and service.doctor.hospital_id else None

    if hospital_id is None:
        return []

    tag_list = []
    new_tag_list = []
    if use_tagv3:
        tags = service.new_tags.all()
        for tag in tags:
            if tag.tag_type == TAG_V3_TYPE.SECOND_CLASSIFY:
                new_tag_list.append(tag.id)
                break
            elif tag.tag_type == TAG_V3_TYPE.NORMAL:
                parent_tag_ids = TagV3Relation.objects.filter(child=tag, is_online=True).only('parent_id').\
                    values_list('parent_id', flat=True)
                #按照类别过滤
                tagv3_obj = TagV3.objects.filter(id__in=parent_tag_ids, tag_type=TAG_V3_TYPE.SECOND_CLASSIFY).first()
                if tagv3_obj:
                    new_tag_list.append(tagv3_obj.id)
                    break
    else:
        tags = service.tags.all()
        for tag in tags:
            if tag.tag_type == TAG_TYPE.BODY_PART_SUB_ITEM:
                tag_list.append(tag.id)
                break
            elif tag.tag_type == TAG_TYPE.ITEM_WIKI:
                parent_tag_ids = TagRelation.objects.filter(child_id=tag.id, is_deleted=False).values_list('parent_id')
                tag_obj = Tag.objects.filter(id__in=parent_tag_ids, tag_type=TAG_TYPE.BODY_PART_SUB_ITEM).first()
                if tag_obj:
                    tag_list.append(tag_obj.id)
                    break

    try:
        from rpc.context import get_rpc_remote_invoker

        # max_size = 20
        query_size = count + 5  # 多捞几个，避免几种不同方式里面有当前service_id导致捞不足够max_size

        tag_id = None
        if len(tag_list) > 0:
            tag_id = tag_list[0]
        tagv3_id = None
        if len(new_tag_list) > 0:
            tagv3_id = new_tag_list[0]

        user_city_info = {}
        if user_city_tag_id and user_city_id:
            user_city_info = {
                "user_city_tag_id": user_city_tag_id,
                "user_city_id": user_city_id,
            }

        result = get_rpc_remote_invoker()['doris/search/guess_you_like_service'](
            hospital_id=hospital_id, tagv3_id=tagv3_id, use_tagv3=use_tagv3,
            tag_id=tag_id, user_city_info=user_city_info, service_id=service_id,
            offset=start_num, size=query_size).unwrap()

        # 去掉潜在重复的id（当前美购id），然后把冗余的数据去掉，只要前20条
        result_ids = [sid for sid in result['service_ids'] if sid != service_id][:20]
        service_ids = result_ids[start_num: start_num + count]
        return service_ids
    except:
        logging_exception()
        return []


@bind('api/service/get_album_pic')
def get_service_album(service_id, start_num, count=10):
    """
    返回美购对应的相册图片
    """
    result = []
    service = Service.objects.get(id=service_id)
    image_pic = ImageRelatedService.objects.filter(service_id=service_id)
    image_pic_num = image_pic.count()
    doctor = service.doctor
    if doctor.doctor_type == DOCTOR_TYPE.OFFICER:
        doctor_pics = Doctor.objects.filter(hospital_id=doctor.hospital_id,
                                            is_online=True).filter(~Q(portrait=''))
    else:
        doctor_pics = Doctor.objects.filter(id=doctor.id,
                                            is_online=True).filter(~Q(portrait=''))
    doctor_pic_count = doctor_pics.count()
    organization_pics = OrganizationImage.objects.filter(doctor=doctor)

    if start_num < image_pic_num:
        '''先取其他里面的图片'''
        delta_num = image_pic_num - start_num
        if delta_num >= count:
            pics = image_pic[start_num: start_num + count]
            for pic in pics:
                result.append({
                    'pic': get_full_path(pic.image_url, '-half'),
                    'pic_w': get_full_path(pic.image_url, '-w'),
                    'name': u"其他"
                })
            return result
        else:
            pics = image_pic[start_num: start_num + count]
            for pic in pics:
                result.append({
                    'pic': get_full_path(pic.image_url, '-half'),
                    'pic_w': get_full_path(pic.image_url, '-w'),
                    'name': u"其他"
                })
            count = count - delta_num

    if start_num < doctor_pic_count and count > 0:
        '''首先获取医生图片'''
        pics = doctor_pics[start_num:start_num + count]
        for pic in pics:
            result.append({
                'pic': get_full_path(pic.portrait, '-half'),
                'pic_w': get_full_path(pic.portrait, '-w'),
                'name': u"医生 " + pic.name
            })

        '''医生数量不够 用机构图片来弥补'''
        if len(result) < count:
            num = count - len(result)
            pics = organization_pics[0:num]
            for pic in pics:
                result.append({
                    'pic': get_full_path(pic.image_url, '-half'),
                    'pic_w': get_full_path(pic.image_url, '-w'),
                    'name': u"环境"
                })
    else:
        start_num = start_num - doctor_pic_count
        pics = organization_pics[start_num:start_num + count]
        for pic in pics:
            result.append({
                'pic': get_full_path(pic.image_url, '-half'),
                'pic_w': get_full_path(pic.image_url, '-w'),
                'name': u"环境"
            })

    return result


@bind('api/service/get_buy_notice')
def get_buy_notice():
    from api.tool.service_tool import ServiceConfig
    return {"buy_notice": ServiceConfig.get()['config_content']}


@bind('api/service/get_service_score_info')
def get_service_score_info(service_id):
    s = Service.objects.get(id=service_id)
    tag = s.project_type
    avg_score = service_score_tag_avg.get(str(tag.id))
    if avg_score is None:
        avg_score = 0
    else:
        avg_score = float(avg_score)
    if s.rating > avg_score:
        desc = '非常好'
        type = 0
    elif s.rating == avg_score:
        desc = '不错'
        type = 0
    else:
        desc = '一般'
        type = 1

    if s.rating:
        return {
            'total_score': round(s.rating, 1),
            'total_desc': desc,
            'type': type,
            'score_detail': [{
                'score': s.operation_effect_rating,
                'desc': '术后效果',
            }, {
                'score': s.hospital_env_rating,
                'desc': '就医环境'
            }, {
                'score': s.doctor_attitude_rating,
                'desc': '医生态度',
            }]
        }
    else:
        return {}

def _from_service_id_to_service_info_dict(service_ids):
    """
        根据service_id获取美购信息的方法
    """

    if not service_ids:
        return {}
    services_list = []
    for service_id in service_ids:
        service = Service.objects.filter(id=service_id, is_online=True).first()
        if service:
            services_list.append({
                'service_id': service.id,
                'service_name': service.name,
                'short_description': service.short_description,
                'image': service.image_header,
                'sell_num': service.sell_amount_display,
                "sell_or_diary_num_desc": "已购买:{}".format(service.sell_amount_display),
                'gengmei_price': service.gengmei_price_display,
            })
    return {'services': services_list}

@bind('api/service/get_recommend_service_info')
def get_recommend_service_info(service_ids):
    ## 获取推荐袋美购信息
    return _from_service_id_to_service_info_dict(service_ids)

@bind('api/service/get_service_from_doctor')
def get_service_from_doctor(doctor_id=None, search_word=None, service_ids=[]):
    ## 跟据医生id, 搜索词, 搜该医生下的美购
    ## 如果医生是商户的话，只取医生的美购；如果医生不是商户，取该医生关联的医院下所有医生的美购
    services = []
    if doctor_id:
        doctor = Doctor.objects.filter(id=doctor_id).first()
        # 如果医生是商户
        if doctor:
            if doctor.is_merchant:
                s_ids = list(Service.objects.filter(doctor_id=doctor_id, is_online=True, short_description__contains=search_word).values_list('id', flat=True))
                s_ids = [str(s) for s in s_ids]
                service_ids = list(set(s_ids) - set(service_ids))  ##  医生已经添加到推荐袋的美购不返回
                services = _from_service_id_to_service_info_dict(service_ids)
            # 如果医生不是商户
            else:
                hospital_id = doctor.hospital_id
                doctor_ids = list(Doctor.objects.filter(hospital_id=hospital_id, is_online=True).values_list('id', flat=True))
                s_ids = list(
                    Service.objects.filter(doctor_id__in=doctor_ids, is_online=True, short_description__contains=search_word).values_list(
                        'id', flat=True))
                s_ids = [str(s) for s in s_ids]
                service_ids = list(set(s_ids) - set(service_ids))
                services = _from_service_id_to_service_info_dict(service_ids)

    return services


@bind('api/service/get_service_from_hospital')
def get_service_from_hospital(doctor_id=None, hospital_id=None, search_word=None, service_ids=[]):
    ## 跟据医院id, 搜索词, 搜该医院下所有医生的美购
    if not doctor_id and not hospital_id:
        raise GaiaRPCFaultException(CODES.INVALID_PARAMS, u"doctor_id和hospital_id不能同时为空", data=None)

    if not hospital_id:
        doctor = Doctor.objects.filter(id=doctor_id).first()
        hospital_id = doctor.hospital_id

    doctor_ids = list(
        Doctor.objects.filter(hospital_id=hospital_id, is_online=True).values_list(
            'id', flat=True))
    s_ids = list(
        Service.objects.filter(doctor_id__in=doctor_ids, is_online=True,
                               short_description__contains=search_word).values_list(
            'id', flat=True))
    s_ids = [str(s) for s in s_ids]
    service_ids = list(set(s_ids) - set(service_ids))
    services = _from_service_id_to_service_info_dict(service_ids)
    return services


@bind('api/service/get_service_from_hospital_v2')
def get_service_from_hospital_v2(doctor_id=None, hospital_id=None, search_word=None, service_ids=[]):
    ## 跟据医院id, 搜索词, 搜该医院下所有医生的美购
    if not doctor_id and not hospital_id:
        raise GaiaRPCFaultException(CODES.INVALID_PARAMS, u"doctor_id和hospital_id不能同时为空", data=None)

    if not hospital_id:
        doctor = Doctor.objects.filter(id=doctor_id).first()
        hospital_id = doctor.hospital_id

    doctor_ids = list(
        Doctor.objects.filter(hospital_id=hospital_id, is_online=True).values_list(
            'id', flat=True))
    s_ids = list(
        Service.objects.filter(doctor_id__in=doctor_ids, is_online=True,
                               short_description__contains=search_word).values_list(
            'id', flat=True))
    s_ids = [str(s) for s in s_ids]
    service_ids = list(set(s_ids) - set(service_ids))

    return {'service_ids':service_ids}



@bind('api/service/get_tags')
def get_new_tag_by_service(service_id):
    tags = []
    ## 获取推荐袋美购信息
    if service_id:
        try:
            s = Service.objects.get(pk=service_id)
        except:
            return gen(CODES.SERVICE_NOT_EXSIT)
        for tag in s.new_tags.all():
            tags.append({'name': tag.name, 'id': tag.id, "tag_type": tag.tag_type, 'is_new_tag': 1})
        if not tags:  # 若新标签不存在,则返回老标签
            for tag in s.tags.filter(tag_type__in=[TAG_TYPE.BODY_PART, TAG_TYPE.BODY_PART_SUB_ITEM, TAG_TYPE.ITEM_WIKI]):
                tags.append({'name': tag.name, 'id': tag.id, "tag_type": tag.tag_type, 'is_new_tag': 0})
        if tags:
            tags = sorted(tags, key=lambda x: x['tag_type'], reverse=True)
    return {'tags': tags}


@bind('api/service/get_service_id')
def get_service_id(service_item_ids):
    ## 获取美购id
    result = {}
    service_item = ServiceItem.objects.filter(id__in=service_item_ids)
    for s in service_item:
        result[str(s.id)] = s.service_id
    return result


@bind('api/service/get_service_info_from_service_ids')
def get_service_info_from_service_ids(spu_ids=[], sku_ids=[], use_new_service_info_data=False):
    """"
    根据service_ids回去美购详细信息
    """

    result = {}
    if spu_ids:
        result = service_info_manager.get_toc_spu_info_list_mapping_by_spu_ids(service_ids=spu_ids)
    elif sku_ids:
        result = service_info_manager.get_toc_sku_info_list_mapping_by_sku_ids(sku_ids)
    return result
