# coding=utf-8
from hera.queries.packageservice import PackageServiceDQ
from hera.queries.skupricelog import SKUPriceLogDQ
from rpc.decorators import bind_context
from api.models import Service, Tag, ServiceTag, ServiceItem, ServiceRegister, ServiceReviewRecord, \
    ServiceRegisterItem, Q, PackageServiceRemark, SimpleActionLog, AuditAttrOptions, TagV3, ServiceNewTag, \
    CommodityCategoryRelation, CommodityCategory, CommodityCategoryPropertyRelation
from django.db import transaction
from rpc.exceptions import RPCNotFoundException
from rpc.tool.log_tool import info_logger
from rpc.tool.dict_mixin import to_dict
from gm_types.gaia import SERVICE_REVIEW_STATUS, YINUO_TYPE, TAG_TYPE, SERVICE_SELL_TYPE, CommodityCategoryProperty

from .serviceregister import new_project_type
from ..models import UserPerm
from ..utils import check_business, check_operate, operate_business
from datetime import datetime

from api.tasks.service_task import refresh_service_cache_info
from api.manager.service_info_manager import get_sku_id_to_sku_name_info, get_register_sku_id_to_sku_name_info

uri_pre = 'hera/packageservice'
special_approve = 'hera/specialapprove'


@bind_context(special_approve + '/query')
def specialapprovel_query(ctx, options):
    init_q = Q(review_status=SERVICE_REVIEW_STATUS.SPECIAL_UNDER_REVIEW)
    if check_operate(ctx.session.user_id):
        business_ids = operate_business(ctx.session.user_id)
        init_q &= Q(doctor__business_partener__id__in=business_ids)
    elif check_business(ctx.session.groups):
        # 判断是商务并且非商务leader
        user = ctx.session.user
        members = UserPerm.members(user)
        init_q &= Q(doctor__business_partener__in=members)
    dqobj = PackageServiceDQ(init_q=init_q)
    return dqobj.process(**options)


@bind_context(uri_pre + '/query')
def packageservice_query(ctx, options):
    init_q = Q(review_status=SERVICE_REVIEW_STATUS.PASS)
    if check_business(ctx.session.groups):
        # 判断是商务并且非商务leader
        user = ctx.session.user
        members = UserPerm.members(user)
        init_q &= Q(doctor__business_partener__in=members)
    elif check_operate(ctx.session.user_id):
        business_ids = operate_business(ctx.session.user_id)
        init_q &= Q(doctor__business_partener__id__in=business_ids)
    dqobj = PackageServiceDQ(init_q=init_q)
    return dqobj.process(**options)


@bind_context(special_approve + '/edit')
@transaction.atomic
def specialapprovel_edit(ctx, servicereg_id=None, service_info=None):
    if servicereg_id is None:
        return None
    attr_items = service_info.pop('attr_items', [])
    if service_info is None:
        return None
    else:
        servicereg = ServiceRegister.objects.get(id=servicereg_id)
        
        if servicereg.review_status != SERVICE_REVIEW_STATUS.SPECIAL_UNDER_REVIEW:
            return -1
        servicereg.review_status = service_info['state']
        servicereg.save()
        # next save ServiceReviewRecord记录
        record = servicereg.servicereviewrecord_set.all().last()
        if record:
            record.now_review_status = service_info['state']
            record.reason = service_info['reason']
            record.audit_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            record.operator = ctx.session.user.person
            record.save()
    service_item_ids = []
    for attr_item in attr_items:
        service_item = ServiceRegisterItem.objects.get(id=attr_item.pop('id'))
        service_item_ids.append(service_item.id)
        for ks, vs in attr_item.iteritems():
            setattr(service_item, ks, vs)
        service_item.save()
    # 更新缓存
    refresh_service_cache_info.delay(service_item_ids=service_item_ids)

    return servicereg_id


@bind_context(special_approve + '/get')
def specialapprovel_get(ctx, servicereg_id, options=None):
    """
    获取美购注册根据id
    """
    servicreg = ServiceRegister.objects.get(id=servicereg_id)

    if options is None:
        options = {
            'fields': None,
            'excludes': None,
            'expands': None,
        }
    service_data = {}
    service_data['id'] = servicereg_id
    service_data['service_type'] = servicreg.service_type
    # service_data['itemwiki'] = list(
    #     ServiceItemWiki.objects.filter(service_id=service.id).values_list('itemwiki_id', flat=True))
    items = []
    attrs_parent = []
    temp_attr = []
    service_items = servicreg.items.filter(is_online=True).filter(is_delete=False)
    all_servicereg_item_id = [item.property_id for item in service_items if item.property_id]
    servicereg_item_id_to_sku_name_info = get_register_sku_id_to_sku_name_info(all_servicereg_item_id)

    for item in service_items:
        determine_items = {}
        determine_dict = dict()
        if not item.service_register.upgrade:
            service_keys = item.serviceregisteritemkey_set.all()
            for service_key in service_keys:
                determine_item = service_key.serviceregisterattroption
                determine_item_parent_name = getattr(determine_item.tag_attr if hasattr(determine_item, 'tag_attr')
                                                     else '', 'name', 'SKU名称')
                determine_item_parent_id = getattr(determine_item.tag_attr if hasattr(determine_item, 'tag_attr')
                                                   else '', 'id', 'skumingcheng')
                auditattroptions = AuditAttrOptions.objects.filter(serviceregisteritem=service_key.serviceregisteritem).first()
                if auditattroptions:
                    determine_item_name = auditattroptions.name
                else:
                    determine_item_name = determine_item.name
                determine_dict = {
                    determine_item_parent_id: determine_item_name
                }
                if determine_item_parent_id not in temp_attr:
                    temp_attr.append(determine_item_parent_id)
                    attrs_parent.append({'item_parent_id': determine_item_parent_id,
                                         'item_parent_name': determine_item_parent_name})
        else:
            determine_item = servicereg_item_id_to_sku_name_info.get(str(item.property_id), {}).get('tob_sku_name', '')
            if not determine_item:
                determine_item = item.service_register.name
            determine_dict = {
                str(item.id): determine_item
            }
            attrs_parent.append({'item_parent_id': str(item.id),
                                'item_parent_name': determine_item})
        determine_items.update(determine_dict)

        item_data = to_dict(item)
        item_data['upgrade'] = item.service_register.upgrade
        item_data['determine_items'] = determine_items
        item_data['serviceitem_id'] = item.serviceitem.id if item.serviceitem else u''
        item_data['city_name'] = item.city.name if item.city else ''
        item_data['sku_description'] = item.sku_description

        commodityCategoryRelationItem = CommodityCategoryRelation.objects.filter(commodity_id=item.serviceitem.id).first() if item.serviceitem else CommodityCategoryRelation.objects.filter(commodity_register_id=item.id).first()
        category_id = commodityCategoryRelationItem.category_id if commodityCategoryRelationItem else ''
        comdityCategoryItem = CommodityCategory.objects.filter(id=category_id).first() if category_id else ''
        item_data['category_name'] = comdityCategoryItem.name if comdityCategoryItem else ''

        item_data['positon_property'] = ''
        item_data['instrument_property'] = ''
        item_data['materials_property'] = ''
        item_data['measure_property'] = ''
        relItems = CommodityCategoryPropertyRelation.objects.filter(commodity_id=item.serviceitem.id) if item.serviceitem else CommodityCategoryPropertyRelation.objects.filter(commodity_register_id=item.id)
        for it in relItems:
            if it.property_type == CommodityCategoryProperty.POSITON:
                item_data['positon_property'] = it.property_name
            if it.property_type == CommodityCategoryProperty.INSTRUMENT:
                item_data['instrument_property'] = it.property_name
            if it.property_type == CommodityCategoryProperty.MATERIALS:
                item_data['materials_property'] = it.property_name
            if it.property_type == CommodityCategoryProperty.MEASURE:
                item_data['measure_property'] = it.property_name

        items.append(item_data)
    service_data['attr_items'] = items
    service_data['attr_items_head'] = attrs_parent
    service_data['service_lock'] = getattr(servicreg.service, 'is_lock', False)
    return service_data


@bind_context(uri_pre + '/edit')
@transaction.atomic
def packageservice_edit(ctx, service_id=None, service_info=None):
    if service_info is None:
        return None
    service_info.pop('id', '')
    service_info.pop('servicereg_id', '')
    attr_items = service_info.pop('attr_items', [])
    service_info.pop('photo_details_doctor')
    tags = service_info.pop('tags', [])
    new_tagsv3 = service_info.pop('new_tags', [])
    specialtags = service_info.pop('specialtag', [])
    tags = tags + specialtags
    service_info['wiki_id'] = service_info.pop('wiki')
    service_info['is_insurance'] = not (service_info.get('yinuo_type') == YINUO_TYPE.NONE)
    if service_id is None:
        return None
    else:
        try:
            service = Service.objects.get(id=service_id)
        except:
            info_logger.info(__import__('traceback').format_exc())
            raise RPCNotFoundException
        for k, v in service_info.iteritems():
            setattr(service, k, v)
        # top save self
        # next save serviceregister 相关的数据
        service_register = service.servicereg.all()
        if service_register and service_register[0].is_register:
            if service_register[0].review_status != SERVICE_REVIEW_STATUS.PASS:
                return -1
            from datetime import datetime
            service_register[0].online_time = datetime.now()
            service_register[0].is_register = False
            service_register[0].save()
            setattr(service, 'is_online', True)
        setattr(service, 'sell_num_limit', service.real_stock)
        service.save()
        # doctor
        service.smart_self_support()
        # next save tag
        if tags:
            new_tags = set(Tag.objects.filter(id__in=tags))
            old_tags = set(service.tags.all())
            for tag_obj in (new_tags - old_tags):
                ServiceTag.objects.get_or_create(
                    service_id=service.id,
                    tag=tag_obj)
            ServiceTag.objects.filter(
                service_id=service.id,
                tag__in=(old_tags - new_tags),
            ).delete()
        if new_tagsv3:
            new_tags_v3 = set(TagV3.objects.filter(id__in=new_tagsv3))
            old_tags_v3 = set(service.new_tags.all())
            for tag_obj in (new_tags_v3 - old_tags_v3):
                ServiceNewTag.objects.get_or_create(
                    service_id=service.id,
                    tag=tag_obj)
            ServiceNewTag.objects.filter(
                service_id=service.id,
                tag__in=(old_tags_v3 - new_tags_v3),
            ).delete()
        # next save attr
        refresh_service_item_ids = []
        for attr_item in attr_items:
            service_item = ServiceItem.objects.get(id=attr_item['id'])
            refresh_service_item_ids.append(service_item.id)
            service_item.cost_price = attr_item.pop('cost_price', 0)
            service_item.save(update_fields=['cost_price'])
            price_info = service_item.get_default_price_info()
            if attr_item['cash_back_fee'] and attr_item['cash_back_fee']:
                service_item.update_price(price_id=price_info['id'],
                                      cash_back_fee=attr_item['cash_back_fee'],
                                      cash_back_rate=attr_item['cash_back_rate'],
                                      self_support_discount=attr_item['self_support_discount']
                                      )
            else:
                service_item.update_price(price_id=price_info['id'],
                                      self_support_discount=attr_item['self_support_discount'])

            #  无申请id的活动价同步更新
            activity_ids = service_item.specialitem_set.filter(doctorseckillapply__isnull=True).\
                values_list('special_id', flat=True)
            price_ids = service_item.serviceitemprice_set.filter(selling_rule__activity_id__in=activity_ids).\
                values_list('id', flat=True)
            for price_id in price_ids:
                if attr_item['cash_back_fee'] and attr_item['cash_back_rate']:
                    service_item.update_price(price_id=price_id,
                                          cash_back_fee=attr_item['cash_back_fee'],
                                          cash_back_rate=attr_item['cash_back_rate'],
                                          self_support_discount=attr_item['self_support_discount'])
                else:
                    service_item.update_price(price_id=price_id, self_support_discount=attr_item['self_support_discount'])
            # setattr(service_item, 'cash_back_fee', attr_item['cash_back_fee'])
            # setattr(service_item, 'cash_back_rate', attr_item['cash_back_rate'])
            # setattr(service_item, 'self_support_discount', attr_item['self_support_discount'])
            # service_item.save()
        refresh_service_cache_info(service_item_ids=refresh_service_item_ids)
        # save remark record
        packageserviceremark = PackageServiceRemark(
            service_id=service_id,
            person=ctx.session.user.person,
            remark=service_info['notes'],
        )
        packageserviceremark.save()
    refresh_service_cache_info(service_ids=[service_id])
    return service_id


@bind_context(uri_pre + '/get')
def packageservice_get(ctx, service_id, options=None):
    """
    获取美购根据id
    """
    try:
        service = Service.objects.get(id=service_id)
    except Exception as ex:
        raise RPCNotFoundException
    if options is None:
        options = {
            'fields': None,
            'excludes': None,
            'expands': None,
        }
    service_data = to_dict(service, **options)

    # 筛选出个性化标签
    tags = service_data.get('tags',[])
    commontag = []
    specialtag = []
    if tags:
        for tag_obj in tags:
            service_obj = ServiceTag.objects.get_or_create(
                service_id=service.id,
                tag=tag_obj)
            tag = Tag.objects.get_or_create(id=service_obj[0].tag_id)
            if tag[0].tag_type == TAG_TYPE.YUNYING:
                specialtag.append(tag_obj)
            else:
                commontag.append(tag_obj)
    service_data['specialtag'] = specialtag
    service_data['tags'] = commontag
    # service_data['itemwiki'] = list(
    #     ServiceItemWiki.objects.filter(service_id=service.id).values_list('itemwiki_id', flat=True))
    new_all_ids, check_new_tags = new_project_type(tag_id=commontag,service_id=service_id)
    service_data["check_new_tags"] = check_new_tags
    service_data['new_tags'] = new_all_ids
    service_data['order_amount'] = service.real_order_amount
    service_data['is_register'] = service.servicereg.all()[0].is_register
    service_data['stock'] = service.sell_num_limit
    service_data['is_register'] = getattr(service.servicereg, 'is_register', False)
    service_data['is_floor_price'] = u'是' if service.is_floor_price else u'否'
    service_data['button_prefix'] = getattr(service.servicereg.all().last().upload_button, 'button_prefix', '')
    service_data['is_online'] = u'是' if service.is_online else u'否'
    service_data['doctor_name'] = getattr(service.doctor, 'name', '')
    service_data['hospital_name'] = getattr(service.doctor.hospital, 'name', '')
    service_data['tags_name'] = getattr(service.project_type, 'name', '')
    service_data['sell_time'] = '%s---%s' % (getattr(service, 'start_time', ''),
                                             getattr(service, 'end_time', '')
                                             )
    service_data['business_partener_name'] = getattr(service.doctor.business_partener, 'username', u'无')
    # 美购改版 2017-03-31
    service_data['supplement_images'] = service.get_supplement_images()
    service_data['recommend_services'] = service.get_recommend_services()
    service_data['service_type'] = service.service_type
    service_data['service_type_desc'] = SERVICE_SELL_TYPE.getDesc(service.service_type)

    # 后台展示注册id
    try:
        service_data['servicereg_id'] = service.servicereg.last().id
    except:
        service_data['servicereg_id'] = ''

    # next多属性是否需要添加
    items = []
    temp_attr = []
    attrs_parent = []
    service_items = service.items.filter(is_delete=False)
    all_service_item_id = [item.id for item in service_items]
    service_item_id_to_sku_name_info = get_sku_id_to_sku_name_info(all_service_item_id, False)
    for item in service_items:
        determine_items = {}
        determine_dict = dict()
        if not item.service.upgrade:
            service_keys = item.serviceitemkey_set.all()
            for service_key in service_keys:
                determine_item = service_key.serviceattroption
                determine_item_name =determine_item.name
                determine_item_parent_name = getattr(determine_item.tag_attr if hasattr(determine_item, 'tag_attr')
                                                     else '', 'name', 'SKU名称')
                determine_item_parent_id = getattr(determine_item.tag_attr if hasattr(determine_item, 'tag_attr')
                                                   else '', 'id', 'skumingcheng')
                determine_dict = {
                    determine_item_parent_id: determine_item_name
                }
                if determine_item_parent_id not in temp_attr:
                    temp_attr.append(determine_item_parent_id)

                    attrs_parent.append({'item_parent_id': determine_item_parent_id,
                                         'item_parent_name': determine_item_parent_name})
        else:
            determine_item_name = service_item_id_to_sku_name_info[str(item.id)].get('name', '')
            if not determine_item_name:
                determine_item_name = item.service.name
            determine_dict = {
                str(item.id): determine_item_name
            }
            attrs_parent.append({'item_parent_id': str(item.id),
                                 'item_parent_name': determine_item_name})
        determine_items.update(determine_dict)
        price_info = item.get_default_price_info()
        item_data = {'determine_items': determine_items}
        item_data.update(price_info)
        try:
            item_data['discount_rate'] = int(item_data.get('discount') / (item_data.get('gengmei_price') * 1.0) * 100)
        except:
            info_logger.info(__import__('traceback').format_exc())
            item_data['discount_rate'] = 0

        item_data['id'] = item.id
        item_data['upgrade'] = item.service.upgrade
        item_data['sku_stock'] = item.sku_stock
        item_data['self_support_discount_rate'] = int(item_data['self_support_discount'] * 1.0/item_data['gengmei_price'] * 100)
        item_data['cost_price'] = item.cost_price
        item_data['city_name'] = item.city.name if item.city else ''
        item_data['sku_description'] = item.sku_description

        commodityCategoryRelationItem = CommodityCategoryRelation.objects.filter(commodity_id=item.id).first()
        category_id = commodityCategoryRelationItem.category_id if commodityCategoryRelationItem else ''
        comdityCategoryItem = CommodityCategory.objects.filter(id=category_id).first() if category_id else ''
        item_data['category_name'] = comdityCategoryItem.name if comdityCategoryItem else ''

        item_data['positon_property'] = ''
        item_data['instrument_property'] = ''
        item_data['materials_property'] = ''
        item_data['measure_property'] = ''
        item_data['image_header'] = item.image_header
        relItems = CommodityCategoryPropertyRelation.objects.filter(commodity_id=item.id)
        for it in relItems:
            if it.property_type == CommodityCategoryProperty.POSITON:
                item_data['positon_property'] = it.property_name
            if it.property_type == CommodityCategoryProperty.INSTRUMENT:
                item_data['instrument_property'] = it.property_name
            if it.property_type == CommodityCategoryProperty.MATERIALS:
                item_data['materials_property'] = it.property_name
            if it.property_type == CommodityCategoryProperty.MEASURE:
                item_data['measure_property'] = it.property_name

        items.append(item_data)
    service_data['attr_items'] = items
    service_data['attr_items_head'] = list(attrs_parent)
    # add package record
    service_data['remarks'] = get_package_remark(service_id)
    service_data['logs'] = get_logs(service.servicereg.all().last().id)
    # 是否是商务
    service_data['is_business'] = False
    if 'business' in ctx.session.groups:
        service_data['is_business'] = True
    service_data['is_lock'] = service.is_lock
    service_data['merchant'] = service.get_merchant().get('name','') if service.get_merchant() else ''
    return service_data


# 获取日志
@bind_context(uri_pre + '/get_log')
def get_all_logs(ctx, servicereg_id):
    return get_logs(servicereg_id)


def get_logs(servicereg_id):
    logs = {
        'apply_log': get_apply_logs(servicereg_id),
        'package_log': get_package_logs(servicereg_id),
    }
    return logs


# 获取申请日志 record——view
def get_apply_logs(servicereg_id):
    apply_log = ServiceReviewRecord.objects.filter(serviceregister_id=servicereg_id)
    logs = []
    for log in apply_log:
        logs.append({
            'person': log.person.user.last_name,
            'created_time': str(log.created_time).split('.')[0],
            'update_data': log.update_data,
            'now_review_status': log.now_review_status,
        })

    return logs


# 获取包装日志 日志表里去读取
def get_package_logs(servicereg_id):
    try:
        servicereg = ServiceRegister.objects.get(id=servicereg_id)
    except Exception as ex:
        raise RPCNotFoundException
    service = getattr(servicereg, 'service', '')
    package_log = []
    if service:
        package_log = SimpleActionLog.objects.filter(
            Q(object_id_json=('"%s"' % str(service.id))) | Q(object_id_json=service.id)).filter(
            object_type='service')
    logs = []
    for log in package_log:
        logs.append({
            'user': log.user.username,
            'action_time': str(log.action_time),
            'message': log.message,
        })
    return logs


# 驳回/医生申请记录
@bind_context(uri_pre + '/get_audit_records')
def get_audit_records(ctx, servicereg_id):
    try:
        servicereg = ServiceRegister.objects.get(id=servicereg_id)
    except Exception as ex:
        raise RPCNotFoundException
    explanation = servicereg.record_info()
    for ex in explanation:
        ex['time'] = str(datetime.fromtimestamp(ex['time'])) if ex['time'] else ''
    return explanation


# 美购包装备注需改/获取包装记录 在get里面获取时候调用这个 记得在edit里面添加一条备注记录.
def get_package_remark(service_id):
    all_remark_set = PackageServiceRemark.objects.filter(service_id=service_id)
    logs = []
    for log in all_remark_set:
        logs.append({
            'person': log.person.user.username,
            'created_time': str(log.created_time).split('.')[0],
            'remark': log.remark,
        })
    return logs


@bind_context(uri_pre + '/get_sku')
def skulog_query(ctx, sku_id):
    sku = ServiceItem.objects.get(id=sku_id)
    price = sku.get_current_price_info()
    return {
        'id': sku.id,
        'name': ''.join(sku.items_name),
        'gengmei_price': price['gengmei_price'],
        'pre_payment_price': price['pre_payment_price'],
        'discount': price['discount'],
        'activity_id': price['selling_rule']['activity_id'] if price.get('selling_rule') else ''
    }


@bind_context(uri_pre + '/sku/log/query')
def skulog_query(ctx, options):
    dqobj = SKUPriceLogDQ()
    return dqobj.process(**options)
