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

import json

from django.conf import settings
from django.db.models import Q, F
from gm_protocol import GmProtocol
from gm_types.gaia import (
    SLIDE_TYPE,
    SEND_CHANNEL_TYPE,
    DIARY_ORDER_TYPE,
    SERVICE_ORDER_TYPE,
    TOPIC_TYPE,
    INDEX_CARD_TYPE,
    VIDEO_CODE_STATUS,
    VIDEO_LIBRARY_VIDEO_TYPE,
)

from api.manager.tag_manager import get_wiki_by_tag
from api.models import (
    BodyPart,
    ItemWiki,
    Tag,
    TAG_TYPE,
    WikiAdver,
    OptimizeWiki,
    ConnectWiki,
    TagWiki,
    DOCTOR_ORDER_TYPE,
    PROBLEM_ORDER_TYPE,
    FeedOperateV2,
)
from api.tasks.period_task import cache_wiki_list
from api.tool.doctor_tool import get_doctors_hospitals_by_tags
from api.tool.log_tool import logging_exception
from api.tool.service_tool import get_service_by_tags
from api.tool.geo_tool import get_location_tag_id_by_city_id

from rpc.cache import itemwiki_cache
from rpc.context import get_rpc_remote_invoker
from rpc.decorators import bind, bind_context, cache_page
from rpc.decorators import list_interface
from rpc.tool.error_code import gen, CODES

# TODO: NOTE @pengfeix after talos is gone replace with remote rpc invoker
from rpc.context import get_gaia_local_invoker

from search.utils.topic import filter_topic
from talos.tools.diary_tool import get_diaries_by_tags
from wiki.models import VideoLibrary, Item, Collect, Brand, Product

@bind("api/wiki_list")
@bind("api/wiki/list")
@cache_page(120)
def get_all_wiki():
    """百科列表
    PC百科列表
    """
    result = []

    def get_child_tags_info(parent_tag):
        child_tags = parent_tag.online_child_tags()
        child_tags_info = [
            {
                'id': child_tag.id,
                'ordering': child_tag.ordering,
                'obj': child_tag,
            }
            for child_tag in child_tags
        ]
        child_tags_info = sorted(
            child_tags_info,
            key=lambda k: (k['ordering'], k['id'])
        )
        child_tags = [child_tag['obj'] for child_tag in child_tags_info]
        return child_tags

    first_tags = Tag.objects.filter(tag_type=TAG_TYPE.BODY_PART, is_online=True).order_by('ordering', 'id')
    for first_tag in first_tags:
        item = {
            'name': first_tag.name,
            'tag_type': 'body_part',  # TODO: BodyPart中提供的数据
            'tag_id': first_tag.id,
            'id': first_tag.id,
            'icon': first_tag.icon_url,
            'icon_web': first_tag.icon_url,
        }
        item['wiki'] = []
        second_tags = get_child_tags_info(first_tag)
        for second_tag in second_tags:
            third_tags = get_child_tags_info(second_tag)
            for third_tag in third_tags:
                try:
                    wiki = third_tag.itemwiki
                except:
                    continue
                if not wiki.description_md or not wiki.is_online:
                    continue
                item['wiki'].append(wiki.wiki_data())
        if not item['wiki']:
            continue
        result.append(item)
    return result


@bind('api/wiki/iterator')
@list_interface(limit_name='count')
def wiki_iterator(start_num=0, count=10, is_online=True):
    iws = ItemWiki.objects.filter(is_online=is_online, tag__isnull=False)
    return [i.wiki_data() for i in iws[start_num:start_num + count]]


@bind("api/wiki")
@bind("api/wiki/get")
@cache_page(120)
def get_wiki_info(id=None):
    """百科详情
    """
    result = None
    try:
        wiki = ItemWiki.objects.get(id=int(id))
        result = wiki.get_wiki_detail()
    except ItemWiki.DoesNotExist:
        logging_exception()
    return result


@bind("api/project_wiki")
@cache_page(120)
def get_project_wiki_info(id=None):
    """项目百科详情（6.0版本新的百科）
    """
    result = None
    try:
        wiki = ItemWiki.objects.get(id=int(id))
        result = wiki.get_project_wiki_detail()

    except ItemWiki.DoesNotExist:
        pass

    return result


@bind_context('api/tag/wiki')
def get_wiki_list(ctx, channel_id=None, filter_q=None,
                  zone_id=None, tag_id=None):
    zones = BodyPart.objects.exclude(is_deleted=True)
    if channel_id:
        zones = zones.filter(sub_items__channel__id=channel_id).distinct()
    elif zone_id:
        zones = zones.filter(id=zone_id)

    if filter_q and filter_q != 'all':
        type_name, type_id = filter_q.split('__')
        type_id = int(type_id)

        type_filter = Q()
        if type_name == 'bodypart':
            type_filter = Q(id=type_id)
        elif type_name == 'sub_item':
            type_filter = Q(sub_items__id=type_id)

        zones = zones.filter(type_filter)

    zones = zones.order_by('rank')
    wiki_groups = []
    for group in zones:
        group_data = group.wiki_group_data(tag_id)
        if group_data['wiki']:
            wiki_groups.append(group_data)

    return {'wiki_groups': wiki_groups}


@bind('api/itemwiki/by_tag')
def get_online_wiki(tag_id):
    wiki = ItemWiki.objects.filter(
        tag_id=tag_id,
        is_online=True
    ).first()
    result = None
    if wiki:
        result = {
            'id': wiki.id
        }
    return result


@bind_context('api/tags/list')
def get_tag_list(ctx, channel_id=None, filter_q=None,
                 zone_id=None, tag_id=None):
    """ 获取一级和对应二级tag
    """
    zones = BodyPart.objects.exclude(is_deleted=True)
    if channel_id:
        zones = zones.filter(sub_items__channel__id=channel_id).distinct()
    elif zone_id:
        zones = zones.filter(id=zone_id)

    wiki_groups = []

    for zone in zones:
        sub_items = zone.tag.online_child_tags()
        if not sub_items:
            continue

        group_data = {
            'wiki': [],
            'group_name': zone.name,
            'icon': zone.icon,
        }

        for sub_item in sub_items:
            wikis = get_wiki_by_tag(sub_item)
            if not wikis:
                continue

            group_data['wiki'].append({
                'id': sub_item.id,
                'tag_id': sub_item.id,
                'name': sub_item.name,
            })

        if group_data['wiki']:
            wiki_groups.append(group_data)

    return {'wiki_groups': wiki_groups}


@bind('api/itemwiki/list')
@cache_page(120)
def get_itemwiki_list():
    """
    changelog:
    v6.0.0: 创建 用于展示新添加的wiki内容 通过itemwiki对象的description_md判断是否是新添加的wiki内容
    sprint20160801 按照tag的ordering排序 二级下有三级的才展示二级
    """
    wiki_list = []
    protocol = GmProtocol()
    new_itemwikis = ItemWiki.objects.filter(description_md__isnull=False).exclude(description_md=u'')
    tag_ids = new_itemwikis.values_list('tag', flat=True)
    show_tags = Tag.objects.filter(id__in=tag_ids, is_online=True)
    show_second_tags = set(show_tags.filter(tag_type=TAG_TYPE.BODY_PART_SUB_ITEM))

    def get_child_tags_info(parent_tag):
        child_tags = parent_tag.online_child_tags()
        child_tags_info = [
            {
                'id': child_tag.id,
                'obj': child_tag,
                'ordering': child_tag.ordering,
            }
            for child_tag in child_tags
        ]
        child_tags_info = sorted(
            child_tags_info,
            key=lambda k: (k['ordering'], k['id'])
        )
        return child_tags_info

    def build_tag_info(tag):
        info = {
            'tag_name': tag.name,
            'tag_id': tag.id,
            'sub_tags': []
        }
        return info

    first_tags = Tag.objects.filter(tag_type=TAG_TYPE.BODY_PART).order_by('ordering', 'id')

    for first_tag in first_tags:
        first_tag_info = build_tag_info(first_tag)
        second_tags_info = get_child_tags_info(first_tag)

        for _second_tag_info in second_tags_info:
            second_tag = _second_tag_info['obj']
            second_tag_info = build_tag_info(second_tag)
            third_tags_info = get_child_tags_info(second_tag)

            for _third_tag_info in third_tags_info:
                third_tag = _third_tag_info['obj']
                try:
                    wiki = third_tag.itemwiki
                except:
                    continue

                if not wiki.description_md or not wiki.is_online:
                    continue

                second_tag_info['sub_tags'].append({
                    'tag_name': third_tag.name,
                    'tag_id': third_tag.id,
                    'url': protocol.get_wiki_detail(id=third_tag.itemwiki.id, title=third_tag.name.encode('utf8')),
                })

            if not (second_tag_info['sub_tags']):
                # 如果二级下没有三级则不显示
                continue
            if second_tag in show_second_tags:
                # 如果二级tag有对应的wiki配置 需要生成url
                second_tag_info['url'] = protocol.get_wiki_detail(id=second_tag.itemwiki.id,
                                                                  title=second_tag.name.encode('utf8'))
            first_tag_info['sub_tags'].append(second_tag_info)

        if not first_tag_info['sub_tags']:
            # 如果一级下没有二级(肯定没有三级) 则不显示
            continue
        wiki_list.append(first_tag_info)

    return wiki_list


@bind('api/tag/advertise')
def get_tag_advertise():
    """
    changelog:
    v6.0.0: 创建 获取一级tag对应的广告配置用于展示在wiki列表(h5页面)
    """
    tag_advs = WikiAdver.objects.all()
    result = {}
    for tag_adv in tag_advs:
        data = tag_adv.data()
        url = data['url']
        url_type = data['url_type']
        # 增加协议跳转
        protocol = GmProtocol()

        if url == SLIDE_TYPE.TOPIC:  # 帖子详情页
            data['url'] = protocol.get_topic_detail(url_type)
        elif url == SLIDE_TYPE.URL:  # 网页
            data['url'] = protocol.get_webview(url_type)
        elif url == SLIDE_TYPE.SERVICE:  # 美购详情页
            data['url'] = protocol.get_service_detail(url_type)
        elif url == SLIDE_TYPE.DIARY:  # 日记本详情页
            data['url'] = protocol.get_diary_detail(url_type)
        elif url == SLIDE_TYPE.TAG:  # 圈子详情页
            url_type = int(url_type)
            tag = Tag.objects.filter(pk=url_type)[0]
            name = u''
            if tag:
                name = tag.name.encode('utf-8')

            data['url'] = protocol.get_zone_detail(url_type, name)
        elif url == SLIDE_TYPE.SPECIAL:  # 美购专题页
            data['url'] = protocol.get_service_special_list(url_type)
        elif url == SLIDE_TYPE.ACTIVITY:  # 免费活动页
            data['url'] = protocol.get_activity_detail(url_type)
        elif url == SLIDE_TYPE.SUOZHANG_COLUMN:
            if url_type == SEND_CHANNEL_TYPE.GMCXS:
                title = SEND_CHANNEL_TYPE.getDesc(SEND_CHANNEL_TYPE.GMCXS)
            elif url_type == SEND_CHANNEL_TYPE.YMXBK:
                title = SEND_CHANNEL_TYPE.getDesc(SEND_CHANNEL_TYPE.YMXBK)
            elif url_type == SEND_CHANNEL_TYPE.SZWD:
                title = SEND_CHANNEL_TYPE.getDesc(SEND_CHANNEL_TYPE.SZWD)
            elif url_type == SEND_CHANNEL_TYPE.OTHER:
                title = SEND_CHANNEL_TYPE.getDesc(SEND_CHANNEL_TYPE.OTHER)
            else:
                continue

            title = title.encode('utf-8')
            data['url'] = protocol.get_suozhang_column(title, url_type)

        result[data['tag_id']] = data

    return {'tag_advs': result}


@bind('api/wiki/list/v2')
def get_wiki_list_v2():
    """
    获取百科三级列表
    """
    wikis = itemwiki_cache.get(settings.ITEMWIKI_LIST_CACHE)
    if wikis:
        wikis = json.loads(wikis)
    else:
        wikis = cache_wiki_list()

    return wikis


@bind('api/wiki/detail')
@cache_page(120)
def get_wiki_detail(wiki_id, with_doctor_hospital=False,
                    with_top_services=False, with_related_topics=False,
                    current_city_id=None,
                    show_service_num=2, show_diary_num=4, show_zone_num=2,
                    show_topic_num=2, top_service_num=10,
                    show_doctor_hospital_num=4):
    """
    相关百科      单独配置    第一个
    简介         richtext
    档案         optimize
    手术原理      richtext
    效果示例      optimize
    优点         richtext
    缺点风险      richtext
    术前锦囊      richtext
    术后锦囊      richtext
    其他          richtext
    广告位        wikiadv   -|
    相关日记本     效果示例    |
    推荐美购      单独接口     |-> 最后四个
    相关圈子      单独接口    -|
    """
    try:
        wiki = ItemWiki.objects.get(pk=wiki_id)
    except ItemWiki.DoesNotExist:
        return gen(CODES.ITEMWIKI_NOT_EXIST)
    except:
        logging_exception()
        wiki = None

    wiki_info = {
        'wiki_name': wiki.item_name if wiki else '',
        'is_online': wiki.is_online if wiki else False,
        'image_data': wiki.get_wiki_image_data() if wiki else None,
        'image_head_data': wiki.get_wiki_image_head_data() if wiki else None,
        'tag_id': None,
        'templates': [],
    }

    # 关联百科
    related_wikis = ConnectWiki.get_related_wikis(wiki=wiki)
    if related_wikis:
        wiki_info['wikis'] = related_wikis

    optimize_info = OptimizeWiki.objects.filter(
        wiki=wiki, is_visible=True, is_delete=False
    ).order_by('ordering')
    if optimize_info:
        wiki_info['templates'].extend(
            [_optimize_info.data() for _optimize_info in optimize_info]
        )

    # 详情页广告位
    if wiki.wikidetailadver.filter(is_online=True):
        wiki_info['advertise'] = wiki.wikidetailadver.filter(is_online=True).first().data()

    related_tags = TagWiki.objects.filter(itemwiki=wiki)
    if related_tags:
        newest_tag = related_tags.order_by('-id').first().tag
        filter_tag_id = newest_tag.id
        wiki_info['tag_id'] = filter_tag_id
        filters = {'tag_ids': [filter_tag_id]}

        # 日记本列表
        if wiki.show_diary:
            # 20161010 修改排序类型 根据backend中的日记本默认排序规则修改
            wiki_info['diaries'] = get_diaries_by_tags(
                tag_ids=[filter_tag_id], offset=0, size=show_diary_num,
                sort_type=DIARY_ORDER_TYPE.HOT
            )

        # 美购列表
        if wiki.show_service:
            _, city_tag_id = get_location_tag_id_by_city_id(current_city_id)
            sort_params = {}
            if city_tag_id:
                sort_params['user_city_tag_id'] = city_tag_id

            services = get_service_by_tags(
                tag_ids=[filter_tag_id], offset=0, size=show_service_num,
                sort_type=SERVICE_ORDER_TYPE.DEFAULT,
                sort_params=sort_params
            )
            wiki_info['service'] = [
                service.get_service_detail() for service in services
            ]

        # 圈子列表
        if wiki.show_zone:
            wiki_info['zones'] = [
                _tag.tag.zone.zone_info()
                for _tag in related_tags[:show_zone_num]
                if hasattr(_tag.tag, 'zone')
            ]

        if with_doctor_hospital:
            wiki_info.update(get_doctors_hospitals_by_tags(
                tag_ids=[filter_tag_id], offset=0,
                size=show_doctor_hospital_num,
                sort_type=DOCTOR_ORDER_TYPE.DEFAULT2)
            )

        if with_top_services:
            for sort_type, dict_key in [
                (SERVICE_ORDER_TYPE.ORDER_HIGHEST_SALES,
                 'top_sale_service'),
                (SERVICE_ORDER_TYPE.DEFAULT, 'popular_service')
                # 人气美购取智能推荐的数据
                # http://wiki.gengmei.cc/pages/viewpage.action?pageId=3355316
            ]:
                services = get_service_by_tags(
                    tag_ids=[filter_tag_id], offset=0, size=top_service_num,
                    sort_type=sort_type
                )
                wiki_info[dict_key] = [
                    service.get_service_info() for service in services
                ]

        if with_related_topics:
            topics = filter_topic(
                offset=0, size=show_topic_num,
                sort_type=PROBLEM_ORDER_TYPE.DEFAULT, filters=filters
            )
            topic_ids = topics['topic_ids']
            topics = get_rpc_remote_invoker()['topic/get_topic_info_by_ids'](ids=topic_ids)
            topics = {t['id']: t['data'] for t in topics.unwrap()}
            wiki_info['topics'] = [
                topics[tid]
                for tid in topics.keys() if tid in topic_ids
            ]

        # V7.5.0 改版新百科
        r = get_gaia_local_invoker()
        tag_list = [filter_tag_id] if filter_tag_id else []

        related_rank_wrap = r['api/ranklist/get_tag_city_relatelist'](
            tag_ids=tag_list, count=7,
            current_city_id=current_city_id
        )
        # 相关榜单
        try:
            related_rank = related_rank_wrap.unwrap()
        except:
            logging_exception()
            related_rank = []
        wiki_info['rank'] = related_rank

        # 相关文章
        related_articles_wrap = get_rpc_remote_invoker()['topic/column/get_tags_related_articles'](
            tag_list=tag_list,
            article_type_list=[TOPIC_TYPE.COLUMN_ARTICLE, TOPIC_TYPE.USER_ARTICLE],
            count=7
        )
        try:
            related_articles = related_articles_wrap.unwrap()
        except:
            logging_exception()
            related_articles = []
        wiki_info['articles'] = related_articles

    return wiki_info


@bind('api/wiki/get_wiki')
def get_wiki(data):
    # data = {
    #     'card_type':[140,141],
    #     'card_type':[2,3],
    # }
    result = {}
    for card_type, card_id in data.items():
        query, content = Q(), []
        result.update({card_type: []})
        if card_type == INDEX_CARD_TYPE.ITEMWIKI:
            video_type = [VIDEO_LIBRARY_VIDEO_TYPE.ITEM]
            content = Item.objects.filter(pk__in=card_id).values("name", "id", "icon")
        elif card_type == INDEX_CARD_TYPE.MATERIALSWIKI:
            video_type = [VIDEO_LIBRARY_VIDEO_TYPE.MATERIALS, VIDEO_LIBRARY_VIDEO_TYPE.DRUG,
                          VIDEO_LIBRARY_VIDEO_TYPE.INSTRUMENT]
            content = Product.objects.filter(pk__in=card_id).values("name", "id", "icon")
        elif card_type == INDEX_CARD_TYPE.COLLECTWIKI:
            video_type = []  # 聚合百科没有视频
            content = Collect.objects.filter(pk__in=card_id).values("name", "id")
        elif card_type == INDEX_CARD_TYPE.BRANDWIKI:
            video_type = [VIDEO_LIBRARY_VIDEO_TYPE.BRAND]
            content = Brand.objects.filter(pk__in=card_id).annotate(icon=F('image_url')).values("name", "id", "icon")
        for video_id in card_id:
            query |= Q(video_type__in=video_type) & Q(source_id=video_id) & Q(is_online=True)
        video_data = VideoLibrary.objects.filter(query).values(
            "raw_image_url", "raw_video_url", "source_id", "webp_url", "persistent_clip_status")

        for item in content:
            video_info ={}
            for i in video_data:
                if i["source_id"] == item["id"]:
                    persistent_clip_status = i.pop("persistent_clip_status", VIDEO_CODE_STATUS.NOSTART)
                    if persistent_clip_status != VIDEO_CODE_STATUS.SUCCESS:
                        i["webp_url"] = ""
                    video_info = i
                    break
            result[card_type].append({
                "wiki_type": card_type,
                "card_id": item["id"],
                "content": item["name"],
                "icon": item.get("icon", ""),
                "video_cover_url": video_info.get("raw_image_url",""),
                "video_url": video_info.get("raw_video_url",""),
                "short_video_url": video_info.get("webp_url", "") ,
            })

    return result
