#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import unicode_literals, absolute_import, print_function

from itertools import chain

from django.conf import settings
from django.db.models import Q

from gm_rpcd.all import bind
from gm_types.error import ERROR

from gm_types.mimas import TRACTATE_PLATFORM, ATTENTION_NOTIFY_TYPE

from communal.normal_manager import tag_manager
from qa.utils.decorator import listing
from social.models import UserFollow
from talos.logger import info_logger
from talos.models.tractate import TractateTagV3, TractateTag, TractateNewTag
from talos.services import UserService, TagV3Service, AgileTagService
from talos.services.tractate import (
    filter_ids,
    TractateService,
    TractateVoteService,
    TractateFavorService,
)
from talos.tasks.follow_msg_create import create_information_db
from utils.gevent_jobs import Tasks
from utils.rpc import get_current_user, gen


def update_tractate_special_info(tractate_list, tractate_ids, user_id):
    """
    更新新帖子交互数据
    :param tractate_list:
    :param tractate_ids:
    :param user_id:
    :return:
    """
    _tractate_ids = filter_ids(tractate_ids)
    voted_dic = user_id and TractateVoteService.get_tractate_voted_info_for_user(_tractate_ids, user_id) or {}
    favored_dic = user_id and TractateFavorService.get_tractate_favord_info_for_user(_tractate_ids, user_id) or {}

    for tractate_info in tractate_list:
        _tractate_id = tractate_info.get("tractate_id", 0)
        tractate_info.update({
            "is_voted": voted_dic.get(_tractate_id, False),
            "is_favored": favored_dic.get(_tractate_id, False),
        })

    return tractate_list


@bind('mimas/tractate/create')
def tractate_create(content="", video_info=None, image_urls=None, tag_ids=None, platform=TRACTATE_PLATFORM.GM,
                    new_tag_ids=None, service_ids=[], order_service_ids=[], tag_v3_ids=None):
    """
    新帖子创建
    :param content:
    :param video_info: dict like {"width": 200, "video_cover_url": "", "height": 400, 'raw_video_url': ''}
    :param image_urls: must list like
        '[{"width": 200, "image_url": "", "height": 400},
        {"width": 100, "image_url": "", "height": 350}]'
    :param tag_ids: must list like [1, 2, 3]
    :param platform: 创建来源
    :param new_tag_ids: must list like [1, 2, 3] 新标签列表
    :param tag_v3_ids: must list like [1, 2, 3] 标签3.0ID列表
    service_ids: 美购IDs
    :return:
    """
    user = get_current_user()
    if not user:
        return gen(ERROR.LOGIN_REQUIRED)

    # 数据类型校验
    if not image_urls:
        image_urls = []

    if not video_info:
        video_info = {}

    if not tag_ids:
        tag_ids = []

    if not new_tag_ids:
        new_tag_ids = []

    if not tag_v3_ids:
        tag_v3_ids = []

    if not content or (not any([video_info, image_urls])):
        return gen(ERROR.PARAMS_INCOMPLETE)

    if len(content.strip()) > settings.TRACTATE_CONTENT_MAX_LEN or len(content.strip()) < settings.TRACTATE_CONTENT_MIN_LEN:
        return gen(ERROR.TRACTATE_CREATE_CONTENT_ERROR)

    tractate_id = TractateService.create(
        user_id=user.id,
        content=content,
        video_info=video_info,
        image_urls=image_urls,
        tag_ids=tag_ids,
        platform=platform,
        new_tag_ids=new_tag_ids
    )

    # 用户帖创建，关联3.0标签
    TractateService.tractate_create_rel_tag_v3_ids(tractate_id, tag_v3_ids)

    # 粉丝消息页面通知数据保存到db
    result = create_information_db.delay(
        user_id=user.id, source_type=ATTENTION_NOTIFY_TYPE.TRACTATE, business_id=tractate_id,
    )
    info_logger.info('开始保存给粉丝的消息:{},帖子id:{}'.format(result.task_id, tractate_id))

    TractateService.create_relation_service(tractate_id=tractate_id, service_ids=service_ids, order_service_ids=order_service_ids)

    # 点赞灌水统一 http://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=27102037
    # special_user = is_special_user(user_id=user.id)
    # fake_vote_v1(task_type=VOTE_TASK_TYPE.TRACTATE, business_id=tractate_id, special_user=special_user)

    return {
        "tractate_id": tractate_id
    }


@bind('mimas/tractate/list_by_ids')
def tractate_list_by_ids(tractate_ids, need_special_info=False, use_new_query=False, tractate_from=''):
    """
    新帖子列表，仅有帖子相关数据。
    :param tractate_ids:
    :param need_special_info: 是否需要交互信息
    :param use_new_query: 7.12.0 帖子删除展示逻辑 版本兼容
    :param tractate_from:  7.12.0 帖子入口
    :return:
    """
    result = {
        "tractate_list": [],
    }

    if tractate_ids:
        assert len(tractate_ids) <= settings.COUNT_LIMIT, 'too many tractate_ids'

        user = get_current_user()
        _user_id = user and user.id or None
        tractates_info_dic = TractateService.get_tractate_infos_by_ids(
            tractate_ids=tractate_ids,
            user_id=_user_id,
            need_special_info=need_special_info,
            use_new_query=use_new_query,
            tractate_from=tractate_from
        )
        tractates_info_list = tractates_info_dic.get("tractate_list", [])
        valid_tractate_ids = tractates_info_dic.get("valid_tractate_ids", [])

        if need_special_info:
            tractates_info_list = update_tractate_special_info(tractates_info_list, valid_tractate_ids, _user_id)

        # 增加帖子浏览量
        TractateService.tractate_view_increase_num(valid_tractate_ids)

        result["tractate_list"] = tractates_info_list

    return result


@bind('mimas/tractate/list_for_my')
@listing()
def tractate_my_list(offset=0, count=10, tractate_from='', use_new_query=False):
    """
    我发布的帖子列表
    :param offset:
    :param count:
    :param use_new_query:
    :param tractate_from: 7.12.0 我发布的帖子列表需要展示被下线的帖子，需要使用新的 query filter， 根据帖子来区分
    :return:
    """
    result = {
        "data": [],
    }

    user = get_current_user()
    if not user:
        return gen(ERROR.LOGIN_REQUIRED)

    _tractate_ids = TractateService.get_tractate_ids_by_query_and_order(
        query=Q(user_id=user.id),
        order_by=["-id"],
        offset=offset,
        size=count,
        tractate_from=tractate_from,
        use_new_query=use_new_query,
    )
    if _tractate_ids:
        tractates_info_dic = TractateService.get_tractate_infos_by_ids(
            tractate_ids=_tractate_ids,
            tractate_from=tractate_from,
            use_new_query=use_new_query,
        )
        tractate_info_list = tractates_info_dic.get("tractate_list", [])
        tractates_info_list = update_tractate_special_info(tractate_info_list, _tractate_ids, user.id)
        result["data"] = tractates_info_list

        TractateService.tractate_view_increase_num(tractates_info_dic.get("valid_tractate_ids", []))

    return result


@bind('mimas/tractate/count')
def get_user_tractates_info():

    user = get_current_user()
    if not user:
        return gen(ERROR.LOGIN_REQUIRED)

    tractate_count = TractateService.get_user_tractate_count(user.id)

    return {
        "tractate_count": tractate_count,
    }


@bind('mimas/tractate/get')
def get_tractate_by_id(tractate_id, return_user_info=False):
    tractate = TractateService.get_by_id(pk=tractate_id)
    if not tractate:
        return gen(ERROR.TRACTATE_NOT_FOUND)

    view_amounts = TractateService.get_tractates_view_amount_by_ids([tractate_id])
    favor_amounts = TractateService.get_tractates_favor_amount_by_ids([tractate_id])
    vote_amounts = TractateService.get_tractates_vote_amount_by_ids([tractate_id])
    reply_amounts = TractateService.get_tractates_reply_amount_by_ids([tractate_id])
    data = TractateService.get_tractate_base_info(tractate=tractate)
    if return_user_info:
        user_dict = TractateService.get_user_info_by_user_ids([tractate.user_id])
        user = user_dict.get(tractate.user_id, {})
        data.update({
            'user': user,
            'view_amount': view_amounts.get(tractate_id, 0),
            'favor_amount': favor_amounts.get(tractate_id, 0),
            'vote_amount': vote_amounts.get(tractate_id, 0),
            'reply_amount': reply_amounts.get(tractate_id, 0),
        })
    return data


@bind('mimas/tractate/verification')
def verification_tractate_by_id(tractate_id):
    tractate = TractateService.get_by_id(pk=tractate_id)
    if tractate:
        return True
    return False


@bind("mimas/tractate/only_get_tag_ids_by_tractate_ids")
def only_get_tag_ids_by_tractate_ids(tractate_ids):
    """
    仅为了获取tag_id，用于在backend层查询更多数据
    :param tractate_ids:
    :return:
    """
    return TractateService.only_get_tag_ids_by_tractate_ids(tractate_ids)


@bind("mimas/tractate/only_get_new_tag_ids_by_tractate_ids")
def only_get_new_tag_ids_by_tractate_ids(tractate_ids):
    """
    仅为了获取new_tag_id，用于在backend层查询更多数据
    :param tractate_ids:
    :return:
    """
    return TractateService.only_get_new_tag_ids_by_tractate_ids(tractate_ids)


@bind("mimas/tractate/user_del")
def user_del_tractate(tractate_id):
    """
    用户删除自己的帖子
    :param tractate_id:
    :return:
    """
    user = get_current_user()
    if not user:
        return gen(ERROR.LOGIN_REQUIRED)
    return TractateService.user_del_tractate(tractate_id, user.id)


@bind('mimas/follow_tractate/list')
def get_follow_tractate_list(offset=0, count=10):
    """
    关注用户的帖子列表
    :param offset:
    :param count:
    :return:
    """
    user = get_current_user()
    if not user:
        return gen(ERROR.LOGIN_REQUIRED)
    result = {
        "data": [],
    }
    user_follow_ids = list(UserFollow.objects.filter(
        user_id=user.id, bond=True).order_by('-id').values_list('follow_id', flat=True))

    _tractate_ids = TractateService.get_tractate_ids_by_query_and_order(
        query=Q(user_id__in=user_follow_ids),
        order_by=["-id"],
        offset=offset,
        size=count
    )
    if _tractate_ids:
        tractates_info_dic = TractateService.get_tractate_infos_by_ids(
            tractate_ids=_tractate_ids
        )
        tractate_info_list = tractates_info_dic.get("tractate_list", [])
        tractates_info_list = update_tractate_special_info(tractate_info_list, _tractate_ids, user.id)
        result["data"] = tractates_info_list

    return result


@bind('mimas/tractate/list_for_user')
def get_tractate_ids_by_user_id(user_id, offset=0, count=10):
    """用户主页获取用户帖子"""
    result = {
        "tractate_list": [],
    }
    tractate_ids = TractateService.get_tractate_ids_by_query_and_order(query=Q(user_id=user_id, is_online=True),
                                                                       order_by=["-id"], offset=offset, size=count)

    user = get_current_user()
    _user_id = user and user.id or None
    tractates_info_dic = TractateService.get_tractate_infos_by_ids(
        tractate_ids=tractate_ids,
        user_id=_user_id,
        need_special_info=True
    )
    tractates_info_list = tractates_info_dic.get("tractate_list", [])
    valid_tractate_ids = tractates_info_dic.get("valid_tractate_ids", [])
    tractates_info_list = update_tractate_special_info(tractates_info_list, valid_tractate_ids, _user_id)
    # 增加帖子浏览量
    TractateService.tractate_view_increase_num(valid_tractate_ids)
    result["tractate_list"] = tractates_info_list

    return result


@bind('mimas/tractate_check/message')
def get_check_message_by_tractate_ids(tractate_id):
    """
    根据帖子id获取审核 内容
    :param tractate_id:
    :return:
    """
    message = TractateService.get_check_message(tractate_id)

    return message


@bind('mimas/tractate/get_relation_service')
def get_relation_service_by_tractate_ids(tractate_ids):
    """
    根据帖子 list 获取关联美购ID
    :param tractate_ids:
    :return:
    """
    if not tractate_ids:
        return []

    all_service_ids, order_service_ids = TractateService.get_relation_service_by_tractate_ids(tractate_ids=tractate_ids)
    return {"all_service_ids": all_service_ids, "order_service_ids": order_service_ids}


@bind('mimas/tractate/get_tags')
def get_new_tag(tractate_id):
    tag_v3_id_list = list(TractateTagV3.objects.filter(tractate_id=tractate_id).values_list('tag_v3_id', flat=True))
    # if tag_v3_id_list:  ## 获取帖子新标签
    tags = TagV3Service.get_tags_by_tag_v3_ids(tag_v3_id_list)
    tags_info = [
        TagV3Service.format_tag_v3(tag)
        for tag in tags.values()
    ]
    return {
        'tags_v3_id': tag_v3_id_list,
        'tag_v3_info': tags_info
    }
    # else:
    #     #获取帖子老标签2.0
    #     agile_tags_id = list(TractateNewTag.objects.filter(tractate_id=tractate_id).values_list("tag_id", flat=True))
    #     return {'agile_tags_id': agile_tags_id}


@bind('mimas/mark_detail/tractates')
def get_tractates_mark_detail(tractate_ids):
    """
    打卡聚合详情页
    根据内容ID召回作者所有打卡贴/kyc回答  mmp 这玩意...
    :param tractate_ids: 内容ID
    :return:
    """

    result = {
        "tractate_list": [],
    }
    if not tractate_ids:
        return result
    tractate_ids = list(map(int, tractate_ids))
    user = get_current_user()
    _user_id = user and user.id or None
    # _user_id = None
    t_dict = TractateService.get_tractate_infos_by_ids(
        tractate_ids=tractate_ids,
        user_id=_user_id,
        need_special_info=True,
    )
    tractates_info_list = t_dict.get("tractate_list", [])
    valid_tractate_ids = t_dict.get("valid_tractate_ids", [])

    tractates_info_list = update_tractate_special_info(tractates_info_list, valid_tractate_ids, _user_id)

    result["tractate_list"] = tractates_info_list

    return result


@bind('mimas/tractate/tags/by_tractate_ids')
def get_tractate_tags_by_ids(tractate_ids):
    """
    通过ids获取标签信息
    """
    result = {
        'tag_v3': [],
        'tag_v1': [],
    }
    if not tractate_ids:
        return result

    tag_v3 = TractateService.get_tag_v3_info_by_tractate_ids(tractate_ids)
    tag_v3 = chain(*tag_v3.values())
    # tag_v3_ids = [item['id'] for item in tag_v3]
    result['tag_v3'] = list(tag_v3)

    tags = TractateService.get_tag_info_by_tractate_ids(tractate_ids)
    tags = chain(*tags.values())
    result['tag_v1'] = list(tags)

    return result


@bind("mimas/tractate/get_tractate_rel_infos")
def get_tractate_rel_infos(tractate_id):
    """
    获取用户帖关联的数据
    :param tractate_id:
    :return:
    """
    result = {}
    if not tractate_id:
        return result

    tractate_tags = TractateService.get_tags_by_tractate_ids([tractate_id])
    tractate_new_tags = TractateService.get_new_tags_by_tractate_ids([tractate_id])
    tractate_tags_v3 = TractateService.get_tags_v3_by_tractate_ids([tractate_id])
    _map_list = [
        ("v1_rel_tags_info", TractateService.get_tag_info_by_tractate_ids, tractate_tags),
        ("v2_rel_tags_info", TractateService.get_new_tag_info_by_tractate_ids, tractate_new_tags),
        ("v3_rel_tags_info", TractateService.get_tag_v3_info_by_tractate_ids, tractate_tags_v3),
    ]

    tasks = Tasks()
    for key, func, arg in _map_list:
        tasks.add(key, func, arg)
    tasks.joinall()

    results = tasks.jobs
    for key, _, _ in _map_list:
        _data = results.get(key, {})
        result.update({
            key: _data.get(tractate_id, [])
        })

    return result
