# -*- coding: utf-8 -*-
import json
from itertools import chain
from collections import defaultdict

from django.db import IntegrityError, transaction
from django.db.models import Q
from gm_types.gaia import TAG_V3_TYPE, TAG_RELATED_WIKI_TYPE

from agile.models import TagSynonym, TagV3, TagMapOldTag
from agile.models.tag import TagV3MapAttrTag, TagV3Relation, TagV3WikiRelation, TagMapTag
from api.models.face.cheek_style import FeatureWeightValue
from rpc.decorators import bind
from rpc.exceptions import RPCIntegrityError
from rpc.context import get_rpc_remote_invoker
from rpc.tool.log_tool import logging_exception


@bind('hera/check_input')
def checkout_synonym(name=None, _type=None, attr_type=None, tag_type=TAG_V3_TYPE.NORMAL):
    """
    检查输入的同义词
    :param name:
    :param tag_type:  标签类型
    :param attr_type: 属性类型，_type=4 时才会传
    :param _type: 1、标签同义词校验 2、属性同义词校验 3、标签名校验 4、属性名校验
    :return:
    """
    result = {
        'error': 0,
        'message': '',
        'data': ''
    }
    if not name:
        return result
    if int(_type) == 1:
        if tag_type:
            if TagSynonym.objects.filter(name=name, tag_type=int(tag_type)).exists() \
                    or TagV3.objects.filter(name=name, tag_type=int(tag_type)).exists():
                result['error'] = 1
                return result
        return result
    elif int(_type) == 2:
        if TagSynonym.objects.filter(name=name).exists() or \
                TagV3.objects.filter(name=name, tag_type=attr_type).exists():
            result['error'] = 1
            return result
    elif int(_type) == 3:
        if int(tag_type) == TAG_V3_TYPE.NORMAL:
            if TagV3.objects.filter(name=name, tag_type=TAG_V3_TYPE.NORMAL).exists():
                result['error'] = 1
                return result
        elif int(tag_type) == TAG_V3_TYPE.FIRST_CLASSIFY:
            if TagV3.objects.filter(name=name, tag_type=TAG_V3_TYPE.FIRST_CLASSIFY).exists():
                result['error'] = 1
                return result
        elif int(tag_type) == TAG_V3_TYPE.SECOND_CLASSIFY:
            if TagV3.objects.filter(name=name, tag_type=TAG_V3_TYPE.SECOND_CLASSIFY).exists():
                result['error'] = 1
                return result
    else:
        if TagV3.objects.filter(name=name, tag_type=attr_type).exists():
            result['error'] = 1
            return result

    return result


@bind('hera/tag_v3_get')
def get_tag_by_id(tag_id):
    if not tag_id:
        return {}
    try:
        tag = TagV3.objects.get(id=tag_id)
    except TagV3.DoesNotExist:
        return {}
    tag_synonym = list(TagSynonym.objects.filter(tag_id=tag_id).values_list('name', flat=True))
    related_tags = list(TagMapOldTag.objects.filter(tag_id=tag_id).values_list('old_tag_id', flat=True))
    all_tag_attr_ids = list(TagV3MapAttrTag.objects.filter(tag_id=tag_id).values_list('tag_attr_id', flat=True))
    # 二级症状
    symptom_attr_ids = list(TagV3.objects.filter(
        id__in=all_tag_attr_ids, tag_type=TAG_V3_TYPE.SECOND_SYMPTOM, is_online=True,
    ).values_list('id', flat=True))
    # 一级症状
    first_symptom_attr_ids = list(TagV3.objects.filter(
        id__in=all_tag_attr_ids, tag_type=TAG_V3_TYPE.FIRST_SYMPTOM, is_online=True,
    ).values_list('id', flat=True))
    # 二级方式
    mode_attr_ids = list(TagV3.objects.filter(
        id__in=all_tag_attr_ids, tag_type=TAG_V3_TYPE.FIRST_BRAND, is_online=True,
    ).values_list('id', flat=True))
    # 一级方式
    macroscopic_mode_attr_ids = list(TagV3.objects.filter(
        id__in=all_tag_attr_ids, tag_type=TAG_V3_TYPE.MACROSCOPIC_MODE, is_online=True,
    ).values_list('id', flat=True))
    # 二级部位
    position_attr_ids = list(TagV3.objects.filter(
        id__in=all_tag_attr_ids, tag_type=TAG_V3_TYPE.SECOND_POSITION, is_online=True,
    ).values_list('id', flat=True))
    # 一级部位
    first_position_attr_ids = list(TagV3.objects.filter(
        id__in=all_tag_attr_ids, tag_type=TAG_V3_TYPE.FIRST_POSITION, is_online=True,
    ).values_list('id', flat=True))
    # 品牌
    first_brand_attr_ids = list(TagV3.objects.filter(
        id__in=all_tag_attr_ids, tag_type=TAG_V3_TYPE.FIRST_BRAND, is_online=True,
    ).values_list('id', flat=True))
    # 品牌
    brand_attr_ids = list(TagV3.objects.filter(
        id__in=all_tag_attr_ids, tag_type=TAG_V3_TYPE.SECOND_BRAND, is_online=True,
    ).values_list('id', flat=True))
    # 一级诉求
    first_appeal_attr_ids = list(TagV3.objects.filter(
        id__in=all_tag_attr_ids, tag_type=TAG_V3_TYPE.FIRST_APPEAL, is_online=True,
    ).values_list('id', flat=True))
    # 二级诉求
    second_appeal_attr_ids = list(TagV3.objects.filter(
        id__in=all_tag_attr_ids, tag_type=TAG_V3_TYPE.SECOND_APPEAL, is_online=True,
    ).values_list('id', flat=True))
    second_classify, first_classify, related_new_tags = [], [], []
    if tag.tag_type == TAG_V3_TYPE.NORMAL:              # 二级分类上级
        second_classify = list(tag.parents_tags.values_list('parent_id', flat=True))
    elif tag.tag_type == TAG_V3_TYPE.FIRST_CLASSIFY:    # 二级分类下级
        second_classify = list(tag.children_tags.values_list('child_id', flat=True))
    elif tag.tag_type == TAG_V3_TYPE.SECOND_CLASSIFY:
        first_classify = list(tag.parents_tags.values_list('parent_id', flat=True))
        related_new_tags = list(TagV3Relation.objects.filter(
            parent_id=tag.id, is_online=True,
        ).values_list('child_id', flat=True))
    # 关联的新标签
    _ids = list(TagMapTag.objects.filter(tag_id=tag_id).values_list('related_tag_id', flat=True))

    return {
        'name': tag.name,
        'is_online': tag.is_online,
        'is_display': tag.is_display,
        'homoionym': json.loads(tag.homoionym) if tag.homoionym else [],
        'synonym_keywords': tag_synonym,
        'related_tags': related_tags,
        'symptom': symptom_attr_ids,
        'mode': mode_attr_ids,
        'macroscopic_mode': macroscopic_mode_attr_ids,
        'position': position_attr_ids,
        'brand': brand_attr_ids,
        'first_appeal': first_appeal_attr_ids,
        'second_appeal': second_appeal_attr_ids,
        'first_symptom': first_symptom_attr_ids,
        'first_position': first_position_attr_ids,
        'first_classify': first_classify,
        'second_classify': second_classify,
        'related_new_tags': related_new_tags,
        'first_brand': first_brand_attr_ids,
        'doctor_display': tag.doctor_display,
        'tag_type': tag.tag_type,
        'related_special_tags': _ids,
    }


@bind('hera/tag_v3_edit')
def tag_v3_edit(tag_data, tag_id):
    result = {
        'error': 0,
        'message': '创建成功',
        'data': ''
    }
    tag_type = int(tag_data.get('tag_type', 1))

    doctor_display = True
    if tag_type == TAG_V3_TYPE.NORMAL:
        doctor_display = tag_data.get('doctor_display', False)
    synonym = tag_data.get('synonym', [])                                       # 同义词
    related_tags = tag_data.get('related_tags', [])                             # 关联老标签
    symptom = tag_data.get('symptom', [])                                       # 症状
    first_symptom = tag_data.get('first_symptom', [])                           # 一级症状
    mode = tag_data.get('mode', [])                                             # 一级方式
    macroscopic_mode = tag_data.get('macroscopic_mode', [])                     # 二级方式
    first_position = tag_data.get('first_position', [])                         # 一级位置
    position = tag_data.get('position', [])                                     # 位置
    brand = tag_data.get('brand', [])                                           # 品牌
    first_brand = tag_data.get('first_brand', [])                               # 品牌
    second_appeal = tag_data.get('second_appeal', [])                           # 二级诉求
    first_appeal = tag_data.get('first_appeal', [])                             # 一级诉求
    homoionym = tag_data.get('homoionym', [])                                   # 近义词

    tag_info = {
        'name': tag_data.get('name'),
        'is_online': tag_data.get('is_online'),
        'is_display': tag_data.get('is_display'),
        'homoionym': json.dumps(homoionym) if homoionym else None,
        'tag_type': tag_type,
        'doctor_display': doctor_display,
    }
    if not tag_info['name']:
        result['error'] = -1
        result['message'] = '名称不能为空'
        return result
    if not tag_id:
        try:
            tag = TagV3.objects.create(**tag_info)
        except IntegrityError:
            raise RPCIntegrityError(message='名称不能重复')
    else:
        tag = TagV3.objects.get(id=tag_id)
        try:
            for key, value in tag_info.items():
                setattr(tag, key, value)
            tag.save()
        except IntegrityError:
            result['error'] = -1
            result['message'] = '名称不能重复'
            result['data'] = tag.id
            return result

    # 标签分类处理 --begin--
    new_related_classify_ids, related_new_tag_ids, new_related_objs, del_related_new_tag_ids = [], [], [], []
    classify_objs = []
    if tag_type == TAG_V3_TYPE.SECOND_CLASSIFY:
        new_related_classify_ids = tag_data.get('first_classify', [])  # 一级分类
        related_new_tag_ids = tag_data.get('related_new_tags', [])  # 二级分类关联新标签
    elif tag_type in [TAG_V3_TYPE.FIRST_CLASSIFY, TAG_V3_TYPE.NORMAL]:
        new_related_classify_ids = tag_data.get('second_classify', [])  # 二级分类
    new_related_classify_ids = map(int, new_related_classify_ids)
    new_related_tag_ids = map(int, related_new_tag_ids)

    if tag_type == TAG_V3_TYPE.NORMAL:
        second_classify = list(tag.parents_tags.values_list('parent_id', flat=True))
        old_classify_tag_ids = list(TagV3.objects.filter(
            id__in=second_classify, is_online=True, tag_type=TAG_V3_TYPE.SECOND_CLASSIFY,
        ).values_list('id', flat=True))
        need_create_classify_ids = set(new_related_classify_ids) - set(old_classify_tag_ids)
        classify_objs = [
            TagV3Relation(
                parent_id=_id,
                child_id=tag.id,
            ) for _id in need_create_classify_ids
        ]
    elif tag_type == TAG_V3_TYPE.SECOND_CLASSIFY:
        # 一级分类
        first_classify = list(tag.parents_tags.values_list('parent_id', flat=True))
        old_classify_tag_ids = list(TagV3.objects.filter(
            id__in=first_classify, is_online=True, tag_type=TAG_V3_TYPE.FIRST_CLASSIFY,
        ).values_list('id', flat=True))
        need_create_classify_ids = set(new_related_classify_ids) - set(old_classify_tag_ids)
        classify_objs = [
            TagV3Relation(
                parent_id=_id,
                child_id=tag.id,
            ) for _id in need_create_classify_ids
        ]
        # 关联新标签
        old_related_tag_ids = list(tag.children_tags.values_list('child_id', flat=True))
        create_related_new_tag_ids = set(new_related_tag_ids) - set(old_related_tag_ids)
        del_related_new_tag_ids = set(old_related_tag_ids) - set(new_related_tag_ids)
        new_related_objs = [
            TagV3Relation(
                parent_id=tag.id,
                child_id=_id,
            ) for _id in create_related_new_tag_ids
        ]

    elif tag_type == TAG_V3_TYPE.FIRST_CLASSIFY:
        second_classify = list(tag.children_tags.values_list('child_id', flat=True))
        old_classify_tag_ids = list(TagV3.objects.filter(
            id__in=second_classify, is_online=True, tag_type=TAG_V3_TYPE.SECOND_CLASSIFY,
        ).values_list('id', flat=True))
        need_create_classify_ids = set(new_related_classify_ids) - set(old_classify_tag_ids)
        classify_objs = [
            TagV3Relation(
                parent_id=tag.id,
                child_id=_id,
            ) for _id in need_create_classify_ids
        ]
    need_del_classify_ids = set(old_classify_tag_ids) - set(new_related_classify_ids)

    # 标签分类处理 --end--

    # 同义词创建
    synonym_list = [
        TagSynonym(
            name=item,
            tag_id=tag.id,
            tag_type=tag_type,
        ) for item in synonym
    ]
    # 关联老标签
    old_tag_mapping = list(TagMapOldTag.objects.filter(
        tag_id=tag.id, is_online=True).values_list('old_tag_id', flat=True))
    related_old_tags = [int(item) for item in related_tags]
    need_create_tag_mapping = set(related_old_tags) - set(old_tag_mapping)
    if tag_type in [TAG_V3_TYPE.SECOND_CLASSIFY, TAG_V3_TYPE.FIRST_CLASSIFY]:
        base_query = ~Q(tag_id=tag.id)
        base_query &= Q(old_tag_id__in=need_create_tag_mapping, is_online=True,)
        old_ids = list(TagMapOldTag.objects.filter(base_query).distinct().values_list('old_tag_id', flat=True))
        if old_ids:
            result['error'] = -2
            result['message'] = '标签{}，不能重复关联'.format(json.dumps(old_ids))
            result['data'] = tag.id
            return result

    need_del_tag_mapping = set(old_tag_mapping) - set(related_old_tags)
    tag_map_list = [TagMapOldTag(tag_id=tag.id, old_tag_id=_id) for _id in need_create_tag_mapping]

    # 标签属性 几大类
    new_symptom_list = set()
    old_symptom_list = list(TagV3MapAttrTag.objects.filter(
        tag_id=tag.id).values_list('tag_attr_id', flat=True))
    # 症状
    new_symptom_list.update(symptom)
    # 微观方式
    new_symptom_list.update(mode)
    # 宏观方式
    new_symptom_list.update(macroscopic_mode)
    # 位置
    new_symptom_list.update(position)
    # 品牌
    new_symptom_list.update(brand)
    new_symptom_list.update(first_brand)
    # 一级诉求
    new_symptom_list.update(first_appeal)
    # 二级诉求
    new_symptom_list.update(second_appeal)
    # 一级症状
    new_symptom_list.update(first_symptom)
    # 一级部位
    new_symptom_list.update(first_position)

    # 处理下类型
    new_symptom_list = set([int(item) for item in new_symptom_list])
    old_symptom_list = set([int(_id) for _id in old_symptom_list])

    need_create_attr_tag = new_symptom_list - old_symptom_list
    need_del_attr_tag = old_symptom_list - new_symptom_list
    attr_tag_list = [TagV3MapAttrTag(
        tag_id=tag.id,
        tag_attr_id=_id,
    ) for _id in need_create_attr_tag]

    with transaction.atomic():
        # 标签映射
        TagMapOldTag.objects.bulk_create(tag_map_list)
        TagMapOldTag.objects.filter(tag_id=tag.id, old_tag_id__in=need_del_tag_mapping).delete()
        # 同义词
        TagSynonym.objects.filter(tag_id=tag.id).delete()
        TagSynonym.objects.bulk_create(synonym_list)
        # 标签属性
        TagV3MapAttrTag.objects.filter(tag_attr_id__in=need_del_attr_tag).delete()
        TagV3MapAttrTag.objects.bulk_create(attr_tag_list)
        # 标签分类
        if tag_type == TAG_V3_TYPE.SECOND_CLASSIFY:
            # 关联一级分类
            TagV3Relation.objects.filter(parent_id__in=need_del_classify_ids).delete()
            TagV3Relation.objects.bulk_create(classify_objs)
            # 关联标签 mmp
            TagV3Relation.objects.filter(parent_id=tag.id, child_id__in=del_related_new_tag_ids).delete()
            if new_related_objs:
                TagV3Relation.objects.bulk_create(new_related_objs)
        elif tag_type == TAG_V3_TYPE.NORMAL:
            TagV3Relation.objects.filter(parent_id__in=need_del_classify_ids).delete()
            TagV3Relation.objects.bulk_create(classify_objs)
        elif tag_type == TAG_V3_TYPE.FIRST_CLASSIFY:
            TagV3Relation.objects.filter(child_id__in=need_del_classify_ids).delete()
            TagV3Relation.objects.bulk_create(classify_objs)
    result['data'] = tag.id

    # 标签调整，同步对应的内容上的标签
    try:
        delete_relations = [
            {"tag_id": tag_id, "tag_v3_id": tag.id}
            for tag_id in need_del_tag_mapping
        ]
        delete2old_tag_ids = defaultdict(list)
        if need_del_tag_mapping:
            for item in TagMapOldTag.objects.filter(tag_id=tag.id):
                if item.old_tag_id in need_del_tag_mapping:
                    continue
                delete2old_tag_ids[item.tag_id].append(item.old_tag_id)
        add_relations = [
            {"tag_id": tag_id, "tag_v3_id": tag.id}
            for tag_id in need_create_tag_mapping
        ]
        if delete_relations or add_relations:
            get_rpc_remote_invoker()["mimas/tag_mapping/sync"](
                add_relations=add_relations,
                delete_relations=delete_relations,
                delete2old_tag_ids=delete2old_tag_ids,
            ).unwrap()
    except:
        logging_exception()

    return result


@bind('hera/attrtag_get')
def get_tag_by_id(tag_id, tag_type):
    if not all([tag_id, tag_type]):
        return {}
    try:
        tag = TagV3.objects.get(id=tag_id)
    except TagV3.DoesNotExist:
        return {}
    tag_synonym = list(TagSynonym.objects.filter(tag_id=tag_id).values_list('name', flat=True))
    # 关联的所有标签ID
    related_tags = list(TagV3MapAttrTag.objects.filter(tag_attr_id=tag_id).values_list('tag_id', flat=True))
    # 关联的一级、二级分类标签ID
    related_first_classify = list(TagV3.objects.filter(id__in=related_tags, tag_type=TAG_V3_TYPE.FIRST_CLASSIFY).values_list('id', flat=True))
    related_second_classify = list(TagV3.objects.filter(id__in=related_tags, tag_type=TAG_V3_TYPE.SECOND_CLASSIFY).values_list('id', flat=True))
    # 关联的品牌标签ID
    related_brand_tags = list(TagV3.objects.filter(id__in=related_tags, tag_type=TAG_V3_TYPE.BRAND).values_list('id', flat=True))
    # 通用三级标签ID
    related_tags = set(related_tags) - set(related_first_classify) - set(related_second_classify) - set(related_brand_tags)
    # 关联二级属性
    related_second_brand = list(TagV3Relation.objects.filter(parent_id=tag_id).values_list('child_id', flat=True))

    data = {
        'name': tag.name,
        'is_online': tag.is_online,
        'is_using_ai': tag.is_using_ai,
        'homoionym': json.loads(tag.homoionym) if tag.homoionym else [],
        'synonym_keywords': tag_synonym,
        'related_tags': list(related_tags),
        'related_first_classify': related_first_classify,
        'related_second_classify': related_second_classify,
        'related_item': [],
        'related_brand': [],
        'related_product': [],
        'related_brand_tags': related_brand_tags,
        'related_second_brand': related_second_brand,
        # 'sub_attr_type': tag.sub_attr_type,
        'related_second_attr_ids': related_second_brand,
    }

    if tag_type == TAG_V3_TYPE.FIRST_BRAND:
        item_wiki = list(TagV3WikiRelation.objects.filter(
            attr_tag_id=tag.id, wiki_type=TAG_RELATED_WIKI_TYPE.ITEM
        ).values_list('wiki_id', flat=True))
        brand_wiki = list(TagV3WikiRelation.objects.filter(
            attr_tag_id=tag.id, wiki_type=TAG_RELATED_WIKI_TYPE.BRAND
        ).values_list('wiki_id', flat=True))
        product_wiki = list(TagV3WikiRelation.objects.filter(
            attr_tag_id=tag.id, wiki_type=TAG_RELATED_WIKI_TYPE.PRODUCT
        ).values_list('wiki_id', flat=True))
        data.update({
            'related_item': item_wiki,
            'related_brand': brand_wiki,
            'related_product': product_wiki,
        })

    return data


@bind('hera/attrtag_edit')
@transaction.atomic
def attrtag_v3_edit(tag_data, tag_id):
    result = {
        'error': 0,
        'message': '创建成功',
        'data': ''
    }
    attr_type = tag_data.get('tag_type')
    synonym = tag_data.get('synonym', [])               # 同义词
    related_tags = tag_data.get('related_tags', [])     # 关联标签
    homoionym = tag_data.get('homoionym', [])           # 近义词
    related_first_classify = tag_data.get('related_first_classify', [])             # 关联一级分类
    related_second_classify = tag_data.get('related_second_classify', [])           # 关联二级分类
    related_brand_tags = tag_data.get('related_brand_tags', [])                     # 二级药品仪器耗材关联品牌标签
    related_second_brand = list(map(int, tag_data.get('related_second_brand', []))) # 药品仪器耗材关联二级药品仪器耗材

    # 一级属性关联二级属性，根据tag_type区分类型
    related_second_attr_ids = list(map(int, tag_data.get('related_second_attr_ids', [])))

    related_tags.extend(related_brand_tags)

    related_wiki_new = {
        TAG_RELATED_WIKI_TYPE.ITEM: tag_data.get('related_item') or [],
        TAG_RELATED_WIKI_TYPE.BRAND: tag_data.get('related_brand') or [],
        TAG_RELATED_WIKI_TYPE.PRODUCT: tag_data.get('related_product') or [],
    }

    tag_info = {
        'name': tag_data.get('name'),
        'is_online': tag_data.get('is_online'),
        'is_using_ai': tag_data.get('is_using_ai'),
        'homoionym': json.dumps(homoionym) if homoionym else None,
        'tag_type': tag_data.get('tag_type'),
        # 'sub_attr_type': tag_data.get('sub_attr_type', '0'),
    }
    if not tag_id:
        tag = TagV3.objects.create(**tag_info)
    else:
        tag = TagV3.objects.get(id=tag_id)
        for key, value in tag_info.items():
            setattr(tag, key, value)
        tag.save()

    # 同义词创建
    synonym_list = [
        TagSynonym(
            name=item,
            tag_id=tag.id,
            tag_type=tag.tag_type,
        ) for item in synonym
    ]
    # 关联标签
    old_tag_mapping = list(TagV3MapAttrTag.objects.filter(
        tag_attr_id=tag.id, is_online=True).values_list('tag_id', flat=True))

    # 处理下类型
    new_related_tags = set([int(item) for item in related_tags])
    old_tag_mapping = set([int(_id) for _id in old_tag_mapping])
    related_first_classify = map(int, related_first_classify)
    related_second_classify = map(int, related_second_classify)
    new_related_tags.update(related_first_classify)
    new_related_tags.update(related_second_classify)

    need_create_tag_mapping = new_related_tags - old_tag_mapping
    need_del_tag_mapping = old_tag_mapping - new_related_tags
    tag_map_list = [TagV3MapAttrTag(tag_attr_id=tag.id, tag_id=_id) for _id in need_create_tag_mapping]

    # 关联属性
    related_second_attr_ids = chain(related_second_brand, related_second_attr_ids)
    attr_map_list = [TagV3Relation(parent_id=tag.id, child_id=_id) for _id in related_second_attr_ids]

    TagV3Relation.objects.filter(parent_id=tag.id).delete()  # 老的关联关系 直接删掉 mmp...
    TagV3Relation.objects.bulk_create(attr_map_list)

    if attr_type == TAG_V3_TYPE.FIRST_BRAND  :
        for _type, _ in TAG_RELATED_WIKI_TYPE:
            """项目百科；品牌百科；药品、仪器、材料百科"""
            wiki_objs = []
            new_wiki = related_wiki_new.get(_type) or []
            related_wiki = list(TagV3WikiRelation.objects.filter(
                attr_tag_id=tag.id, wiki_type=_type,
            ).values_list('wiki_id', flat=True))
            item_wiki_c = set(new_wiki) - set(related_wiki)
            item_wiki_d = set(related_wiki) - set(new_wiki)
            wiki_objs.extend([
                TagV3WikiRelation(
                    attr_tag_id=tag.id,
                    wiki_id=_id,
                    wiki_type=_type,
                ) for _id in item_wiki_c
            ])
            TagV3WikiRelation.objects.filter(wiki_id__in=item_wiki_d, wiki_type=_type).delete()
            TagV3WikiRelation.objects.bulk_create(wiki_objs)

    # 标签映射
    TagV3MapAttrTag.objects.filter(tag_attr_id=tag_id, tag_id__in=need_del_tag_mapping).delete()
    TagV3MapAttrTag.objects.bulk_create(tag_map_list)
    # 同义词
    TagSynonym.objects.filter(tag_id=tag_id).delete()
    TagSynonym.objects.bulk_create(synonym_list)

    result['data'] = tag.id

    return result


@bind('hera/special_tag_v3_edit')
def special_tag_v3_edit(tag_data, tag_id):
    result = {
        'error': 0,
        'message': '创建成功',
        'data': ''
    }
    tag_type = int(tag_data.get('tag_type', 1))

    synonym = tag_data.get('synonym', [])                                       # 同义词
    homoionym = tag_data.get('homoionym', [])                                   # 近义词
    related_special_tags = tag_data.get('related_special_tags', [])

    tag_info = {
        'name': tag_data.get('name'),
        'is_online': tag_data.get('is_online'),
        'is_display': tag_data.get('is_display'),
        'homoionym': json.dumps(homoionym) if homoionym else None,
        'tag_type': tag_type,
        'doctor_display': tag_data.get('doctor_display', False),
    }
    if not tag_info['name']:
        result['error'] = -1
        result['message'] = '名称不能为空'
        return result
    if not tag_id:
        try:
            tag = TagV3.objects.create(**tag_info)
        except IntegrityError:
            raise RPCIntegrityError(message='名称不能重复')
    else:
        tag = TagV3.objects.get(id=tag_id)
        try:
            for key, value in tag_info.items():
                setattr(tag, key, value)
            tag.save()
        except IntegrityError:
            result['error'] = -1
            result['message'] = '名称不能重复'
            result['data'] = tag.id
            return result

    # 标签关联处理 --begin-- 1、删除老的双向关联关系 2、创建新关联
    TagMapTag.objects.filter(Q(tag_id=tag.id) | Q(related_tag_id=tag.id)).delete()
    # 新增关联关系 -----双向-----
    create_objects = []
    for _id in related_special_tags:
        create_objects.extend([
            TagMapTag(tag_id=tag.id, related_tag_id=_id,),
            TagMapTag(tag_id=_id, related_tag_id=tag.id,),
        ])
    # 标签分类处理 --end--

    # 同义词创建
    synonym_list = [
        TagSynonym(
            name=item,
            tag_id=tag.id,
            tag_type=tag_type,
        ) for item in synonym
    ]
    with transaction.atomic():
        # 同义词
        TagSynonym.objects.filter(tag_id=tag.id).delete()
        TagSynonym.objects.bulk_create(synonym_list)
        # 标签关联
        TagMapTag.objects.bulk_create(create_objects)

    result['data'] = tag.id

    return result


@bind('hera/feature_tag_get')
def feature_scope_section_get(tag_id):
    result = {}
    if not tag_id:
        return result

    data = FeatureWeightValue.objects.filter(secondary_demand_id=tag_id)
    if not data:
        return result

    dots = []
    for item in data:
        result['unit'] = item.unit
        dots.append({
            "tags": list(map(int, json.loads(item.tag_ids or '[]'))),
            "X": item.x_value,
            "Y": item.y_value,
            "weight": item.weight,
            "id": item.id,
        })
    result['dots'] = dots

    return result


@bind('hera/feature_tag_edit')
def feature_scope_section_edit(tag_id, data):
    """二级诉求特征类属性标签编辑"""
    if not all([data, data.get('config_checked')]):
        FeatureWeightValue.objects.filter(secondary_demand_id=int(tag_id)).delete()
        return

    unit = data.get('unit', '')
    tag_name = data.get('tag_name')
    for item in data.get('dots', []):
        tags = list(map(int, item.get('tags', [])))
        create_obj = {
            'secondary_demand_id': tag_id,
            'secondary_demand_name': tag_name,
            "unit": unit,
            "tag_ids": json.dumps(tags),
            "x_value": item.get('X'),
            "y_value": item.get('Y'),
            "weight": item.get('weight'),
        }
        _id = item.get('id')
        if not _id:
            FeatureWeightValue.objects.create(**create_obj)
        else:
            feature_obj = FeatureWeightValue.objects.get(id=int(_id))
            for k, v in create_obj.items():
                setattr(feature_obj, k, v)
            feature_obj.save()


@bind('hera/feature_tag/delete')
def feature_scope_section_delete(feature_id):
    """二级诉求特征类属性标签删除"""
    FeatureWeightValue.objects.filter(id=feature_id).delete()
