# -*- coding: utf-8 -*-
import json
from django.conf import settings

from gm_types.error import ERROR
from gm_types.gaia import (
    AGILE_TAG_RECOMMEND_TYPE,
    AGILE_TAG_HERA_RECOMMEND_TAB_TYPE,
)

from rpc.decorators import bind, bind_context

from agile.services import (
    AgileTagService,
    AgileTagTypeService,
    AgileTagMappingTagService,
    AgileTagRecommendTypeService,
    AgileTagRelationPolymerService,
    AgileTagHeraRecommendService,
    TagV3Service
)

from rpc.tool.error_code import gen
from .common import AgileTagFormat
from rpc.cache import old_new_tag_mapping_cache


@bind('api/agile/create')
def agile_tag_create(name, description='', order=None, create_tag_type=None, style=None,
                     agile_tag_types=None, agile_recommend_types=None, relation_polymer_id=None):
    """
    新标签创建
    :param name:
    :param description:
    :param order:
    :param create_tag_type:
    :param style:
    :param agile_tag_types:
    :param agile_recommend_types:
    :return:
    """
    if not name:
        return gen(ERROR.AGILE_TAG_NAME_ERR)

    agile = AgileTagService.create(name=name)
    agile_id = agile.get('tag_id')
    AgileTagTypeService.create(agile_id)
    # 需要建立关联聚合页的话
    if relation_polymer_id:
        AgileTagRelationPolymerService.create(
            agile_tag_id=agile_id,
            polymer_id=relation_polymer_id
        )

    return agile


@bind('api/agile_tags/by_type')
def get_agile_by_type(agile_type, recommend_type=AGILE_TAG_RECOMMEND_TYPE.TRACTATE, show_style=False, start_num=0, offset=15):
    """
    根据标签类型  获取热门标签
    :param agile_type:
    :param recommend_type: 标签推荐范围
    :param show_style:
    :param start_num:
    :param offset:
    :return:
    """
    result = {}

    if not agile_type:
        agile_type = AGILE_TAG_HERA_RECOMMEND_TAB_TYPE.ALL

    # 获取有序的推荐标签
    _recommend_agile_tag_ids = AgileTagHeraRecommendService.get_hera_recommend_agile_tag_ids(
        recommend_type=recommend_type,
        tab_type=agile_type,
        start_num=start_num,
        count=offset
    )
    _tag_list = (
        AgileTagService.get_tag_by_ids(
            agile_ids=_recommend_agile_tag_ids
        ) or {}).get("result", [])
    tags = sorted(_tag_list, key=lambda item: _recommend_agile_tag_ids.index(item.get("id", 0)))

    result.update({'agile_tags': tags})

    return {'result': result}


@bind("api/agile_tag/info_by_ids")
def get_agile_tag_by_ids(agile_tag_ids, simple=True, only_need_old_tag_ids=True, return_dic=False):
    """
    通过标签id获取数据
    :param agile_tag_ids:
    :param simple: 基本数据
    :param only_need_old_tag_ids:仅需要老标签id
    :param return_dic: 返回的数据结构 True dict False []
    :return:
    """
    result = {} if return_dic else []

    if agile_tag_ids:
        assert len(agile_tag_ids) <= settings.COUNT_LIMIT, 'too many agile_tag_ids'
        agile_tag_info_dic = AgileTagFormat.agile_tags_info_format(
            agile_tag_ids,
            simple=simple,
            only_need_old_tag_ids=only_need_old_tag_ids
        )
        # 数据结构返回控制
        if return_dic:
            result = agile_tag_info_dic
        else:
            result = list(agile_tag_info_dic.values())
    return result


@bind("api/agile_tag/get_mapping_old_tag_ids_by_ids")
def get_mapping_old_tag_ids_by_agile_tag_ids(agile_tag_ids, only_need_old_tag_ids=True):
    """
    仅获取新标签映射的老标签
    :param agile_tag_ids:
    :param only_need_old_tag_ids:
    :return:
    """
    result = {
        "tag_mapping": {}
    }

    if agile_tag_ids:
        assert len(agile_tag_ids) <= settings.COUNT_LIMIT, 'too many agile_tag_ids'
        # 新标签，标签映射老标签数据
        result["tag_mapping"] = AgileTagMappingTagService.get_mapping_tags_by_agile_tag_ids(
            agile_tag_ids,
            only_need_old_tag_ids=only_need_old_tag_ids
        )

    return result


@bind("api/agile_tag/get_agile_tags_by_old_tag_ids")
def get_agile_tags_by_old_tag_ids(old_tag_ids):
    """
    通过老标签，获取对应的新标签
    :param old_tag_ids:
    :param only_need_new_tag_ids:
    :return:
    """
    result = {
        "tag_mapping": {}
    }

    if old_tag_ids:
        assert len(old_tag_ids) <= settings.COUNT_LIMIT, 'too many old_tag_ids'
        result["tag_mapping"] = AgileTagMappingTagService.get_mapping_tags_by_old_tag_ids(old_tag_ids)

    return result


@bind("api/agile_tag/tuple_new_tags")
def get_agile_tags_tuple_by_old_tag_ids(old_tag_ids):
    result = get_cache_data(old_tag_ids, True)
    return result


@bind("api/agile_tag/cache")
def get_cache_agile_data(old_tag_ids):
    """
    Get hash list cache mapping data
    :param old_tag_ids:
    :return:
    """
    result = get_cache_data(old_tag_ids)
    return result


def get_cache_data(old_tag_ids, use_tuple=False):
    result = list()
    if old_tag_ids is None:
        return result
    if not isinstance(old_tag_ids, list):
        return result
    cache_name = settings.TAT_MAPPING_HASH_NAME
    pipe = old_new_tag_mapping_cache.pipeline()
    for key in old_tag_ids:
        pipe.hget(cache_name, key)
    data = pipe.execute()
    for item in data:
        if item:
            _info = json.loads(item)
            if use_tuple:
                result.append((_info.get('id'), _info.get('name')))
            else:
                result.append(_info)
    return result


@bind("api/agile_tag/section_tags")
def get_section_tags():
    section_tags = TagV3Service.get_section_tags()
    return {"section_tags": section_tags}


@bind("api/agile_tag/improve_appeals")
def get_improve_appeals(section_tag_ids):
    improve_appeals = TagV3Service.get_improve_appeals(section_tag_ids)
    return {"improve_appeals": improve_appeals}


@bind("api/agile_tag/suit_projects")
def get_suit_projects(improve_appeal_ids):
    suit_projects = TagV3Service.get_suit_projects(improve_appeal_ids)
    return {"suit_projects": suit_projects}


@bind("api/agile_tag/get_section_tag")
def get_section_tag(section_tag_id):
    return TagV3Service.section_tag_data(section_tag_id)


@bind("api/agile_tag/get_improve_appeal")
def get_improve_appeal(improve_appeal_id):
    return TagV3Service.improve_appeal_data(improve_appeal_id)


@bind("api/agile_tag/get_suit_project")
def get_suit_project(suit_project_id):
    return TagV3Service.suit_project_data(suit_project_id)


@bind("api/agile_tag/get_old_attr_tag")
def gets_old_attr_tag(aggregate_type, offset=0, size=100):
    """ 仅用于数据迁移 PS：业务不可用 """
    from agile.models import AttrTag
    attrs = AttrTag.objects.filter(aggregate_type=aggregate_type)[offset: size]
    return {str(item.id): item.name for item in attrs}


@bind("api/agile_tag/get_new_tag")
def gets_new_tag(tag_type, offset=0, size=100):
    """ 仅用于数据迁移 PS：业务不可用 """
    from agile.models import TagV3
    tags = TagV3.objects.filter(tag_type=tag_type)[offset: size]
    return {str(item.id): item.name for item in tags}
