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

from __future__ import unicode_literals, absolute_import, print_function
from gm_rpcd.all import bind
import logging
import traceback
import json
from search.utils.topic import TopicUtils
from trans2es.models.topic import TopicHomeRecommend
from libs.es import ESPerform
from libs.cache import redis_client
from search.utils.common import *
from libs.es import ESPerform
from django.conf import settings

def get_discover_page_topic_ids(user_id, device_id, size, query_type=TopicPageType.FIND_PAGE):
    try:
        if user_id == -1:
            redis_key = "physical:discover_page" + ":user_id:" + str(user_id) + ":device_id:" + device_id
        else:
            redis_key = "physical:discover_page" + ":user_id:" + str(user_id)

        redis_field_list = [b'have_read_topic_id']
        redis_field_val_list = redis_client.hmget(redis_key, redis_field_list)

        have_read_topic_id_list = json.loads(redis_field_val_list[0]) if redis_field_val_list[0] else []
        if have_read_topic_id_list == None:
            have_read_topic_id_list = list()

        recommend_topic_ids = TopicUtils.get_recommend_topic_ids(user_id=user_id, tag_id=0, offset=0, size=size,single_size=size,
                                                           query_type=query_type,
                                                           filter_topic_id_list=have_read_topic_id_list,index_type="topic",routing="4,5,6")


        have_read_topic_id_list.extend(recommend_topic_ids)
        redis_dict = {
            "have_read_topic_id": json.dumps(have_read_topic_id_list)
        }
        redis_client.hmset(redis_key, redis_dict)

        return recommend_topic_ids
    except:
        logging.error("catch exception,err_msg:%s" % traceback.format_exc())
        return []


def get_home_recommend_topic_ids(user_id, device_id, tag_id, offset, size, query=None,
                                 query_type=TopicPageType.HOME_RECOMMEND,promote_topic_list = [],disable_collpase=False,usefulrecall = -1,useful_tag_list =[]):
    try:
        topic_star_routing = "6"
        index_type = "topic-high-star"

        device_redis_key = ""
        if query is None:
            if user_id>0:
                redis_key = "physical:home_recommend" + ":user_id:" + str(user_id) + ":query_type:" + str(query_type)
                device_redis_key = "physical:home_recommend" + ":device_id:" + device_id + ":query_type:" + str(query_type)
            else:
                redis_key = "physical:home_recommend" + ":device_id:" + device_id + ":query_type:" + str(query_type)
        else:
            topic_star_routing = "3,4,5,6"
            index_type = "topic"
            if user_id>0:
                redis_key = "physical:home_query" + ":user_id:" + str(user_id) + ":query:" + str(query) + ":query_type:" + str(query_type)
                device_redis_key = "physical:home_query" + ":device_id:" + device_id + ":query:" + str(query) + ":query_type:" + str(query_type)
            else:
                redis_key = "physical:home_query" + ":device_id:" + device_id + ":query:" + str(query) + ":query_type:" + str(query_type)


        redis_field_list = [b'have_read_topic_list']
        redis_field_val_list = redis_client.hmget(redis_key, redis_field_list)

        # 获取已读帖子
        have_read_topic_id_list = list()

        if redis_field_val_list[0]:
            if query is None:
                have_read_topic_id_list = list(json.loads(redis_field_val_list[0]))
            else:
                if offset>0: # 首次搜索时不需要过滤已读
                    have_read_topic_id_list = list(json.loads(redis_field_val_list[0]))
        elif len(device_redis_key)>0:
            redis_field_val_list = redis_client.hmget(device_redis_key, redis_field_list)
            if redis_field_val_list[0]:
                if query is None:
                    have_read_topic_id_list = list(json.loads(redis_field_val_list[0]))
                else:
                    if offset>0: # 首次搜索时不需要过滤已读
                        have_read_topic_id_list = list(json.loads(redis_field_val_list[0]))


        if have_read_topic_id_list == None:
            have_read_topic_id_list = list()
        have_read_topic_id_list.extend(promote_topic_list)
        useful_topic_id_list = list()
        recommend_topic_user_list = list()
        attention_tag_list = list()
        recommend_topic_list = list()
        if query is None:
          if user_id != -1:
            # 有用标签召回
            if usefulrecall != -1:
                useful_topic_id_list = TopicUtils.userful_tag_topic_list(user_id, have_read_topic_id_list, 4,
                                                                         "topic-high-star", "6",useful_tag_list=useful_tag_list)
                # user_similar_score_redis_key = "physical:user_similar_score:user_id:" + str(user_id)
                # redis_user_similar_score_redis_val = redis_client.get(user_similar_score_redis_key)
                # user_similar_score_redis_list = json.loads(
                #     redis_user_similar_score_redis_val) if redis_user_similar_score_redis_val else []
                size = size - len(useful_topic_id_list)
                have_read_topic_id_list.extend(useful_topic_id_list)

            # linucb 推荐帖子
            topic_recommend_redis_key = "physical:linucb:topic_recommend:device_id:" + str(device_id)

            recommend_topic_dict = redis_client.hgetall(topic_recommend_redis_key)
            linucb_recommend_topic_id_list = list()
            recommend_topic_list = list()
            if b"data" in recommend_topic_dict:
                linucb_recommend_topic_id_list = json.loads(recommend_topic_dict[b"data"])
                if linucb_recommend_topic_id_list == None:
                    linucb_recommend_topic_id_list = list()
                # 推荐帖子是强插的,要保证推荐帖子不在已读里

                logging.warning("type1:%s,type2:%s"%(type(linucb_recommend_topic_id_list),type(have_read_topic_id_list)))
                recommend_topic_id_list = list(set(linucb_recommend_topic_id_list) - set(have_read_topic_id_list))
                recommend_topic_id_list.sort(key=linucb_recommend_topic_id_list.index)
                # cursor = int(str(recommend_topic_dict[b"cursor"], encoding="utf-8"))
                # newcursor = cursor + 6
                if len(recommend_topic_id_list) > 0:
                      recommend_topic_list = recommend_topic_id_list[0:size]
                    # redis_client.hset(topic_recommend_redis_key, "cursor", newcursor)

            if b"datadict" in recommend_topic_dict:
                linucb_recommend_topic_id_dict = json.loads(recommend_topic_dict[b"datadict"])
                if linucb_recommend_topic_id_dict is not None and len(recommend_topic_list) >0:
                  for i in recommend_topic_list:
                    recommend_topic_user_list.append(linucb_recommend_topic_id_dict[str(i)])
            # if have_read_topic_id_list == None:
            #     have_read_topic_id_list = list()
            # 用户关注标签
            redis_tag_data = redis_client.hget("physical:linucb:register_user_tag_info", user_id)
            attention_tag_list = json.loads(redis_tag_data) if redis_tag_data else []
            if len(recommend_topic_list)>0:
                size = size-len(recommend_topic_list)
                have_read_topic_id_list.extend(recommend_topic_list)

            # have_read_topic_id_list_add_promote = list()
            # have_read_topic_id_list_add_promote.extend(have_read_topic_id_list)
            # promote_recommend_topic_id_list = TopicHomeRecommend.objects.using(settings.SLAVE_DB_NAME).filter(
            #     is_online=1).values_list("topic_id",flat=True)
            #
            # for topic_id in promote_recommend_topic_id_list:
            #     have_read_topic_id_list_add_promote.append(topic_id)
        rank_topic_id_list = list()
        if size>0:
            rank_topic_id_list = TopicUtils.get_recommend_topic_ids(user_id=user_id, tag_id=tag_id, offset=0, size=size,
                                                               single_size=size,query=query, query_type=query_type,
                                                               filter_topic_id_list=have_read_topic_id_list,
                                                               index_type=index_type,routing=topic_star_routing,attention_tag_list=attention_tag_list,linucb_user_id_list=recommend_topic_user_list,disable_collpase=disable_collpase)

        # if len(recommend_topic_list) == 6 and query is None:
        #     if (size < 11):
        #         topic_id_list.extend(rank_topic_id_list[0:3])
        #         topic_id_list.extend(recommend_topic_list[0:3])
        #         topic_id_list.extend(rank_topic_id_list[3:size])
        #         topic_id_list.extend(recommend_topic_list[3:6])
        #     else:
        #         topic_id_list.extend(rank_topic_id_list[0:size - 7])
        #         topic_id_list.extend(recommend_topic_list[0:3])
        #         topic_id_list.extend(rank_topic_id_list[size - 7:size])
        #         topic_id_list.extend(recommend_topic_list[3:6])
        # else:
        #     topic_id_list.extend(rank_topic_id_list)
        have_read_topic_id_list.extend(rank_topic_id_list)
        if len(have_read_topic_id_list) > 30000:
            cut_len = len(have_read_topic_id_list)-30000
            have_read_topic_id_list = have_read_topic_id_list[cut_len:]
        redis_dict = {
            "have_read_topic_list": json.dumps(have_read_topic_id_list),
        }
        redis_client.hmset(redis_key, redis_dict)
        # 每个session key保存60天
        redis_client.expire(redis_key, 60 * 60 * 24 * 60)
        if usefulrecall != -1:
            return recommend_topic_list,rank_topic_id_list,useful_topic_id_list
        else:
            return recommend_topic_list, rank_topic_id_list
    except:
        logging.error("catch exception,err_msg:%s" % traceback.format_exc())
        if usefulrecall != -1:
            return [],[],[]
        else:
            return [], []


@bind("physical/search/query_tag_id_by_topic")
def query_tag_id_by_topic(offset=0, size=10, topic_id_list=[], user_id=-1):
    try:
        return TopicUtils.get_topic_tag_info(offset, size, topic_id_list, user_id)
    except:
        logging.error("catch exception,err_msg:%s" % traceback.format_exc())
        return {}


@bind("physical/search/home_recommend")
def home_recommend(device_id="", user_id=-1, offset=0, size=10, query_type=TopicPageType.HOME_RECOMMEND,promote_topic_list=[],usefulrecall = -1,useful_tag_list=[]):
    """
    :remark:首页推荐,目前只推荐日记
    :param session_id:
    :param user_id:
    :param offset:
    :param size:
    :return:
    """
    try:
        if not user_id:
            user_id = -1
        if not isinstance(device_id, str):
            device_id = ""

        recommend_topic_ids = list()
        rank_topic_ids = list()
        useful_topic_ids = list()
        es_node_load_high_flag = False
        # try:
        #     es_node_load_high_flag = ESPerform.if_es_node_load_high(ESPerform.get_cli())
        # except:
        #     logging.error("catch exception,err_msg:%s" % traceback.format_exc())
        #     es_node_load_high_flag = True

        if es_node_load_high_flag:
            temp_downgrading_key = "physical:home_recommend:user_id:241407656:query_type:1"
            redis_field_list = [b'have_read_topic_list']
            redis_field_val_list = redis_client.hmget(temp_downgrading_key, redis_field_list)
            if redis_field_val_list[0]:
                have_read_topic_id_list = list(json.loads(redis_field_val_list[0]))

                if len(have_read_topic_id_list) > offset:
                    recommend_topic_ids = have_read_topic_id_list[offset:offset+size]
                else:
                    recommend_topic_ids = have_read_topic_id_list[0:size]

        else:
          if usefulrecall != -1 and len(useful_tag_list)>0:
            recommend_topic_ids,rank_topic_ids,useful_topic_ids = get_home_recommend_topic_ids(user_id, device_id, tag_id=0, offset=0, size=size,
                                                           query_type=query_type,promote_topic_list=promote_topic_list,usefulrecall=usefulrecall,useful_tag_list=useful_tag_list)
            return {"linucb_topic_ids": recommend_topic_ids,"rank_topic_ids":rank_topic_ids,"useful_topic_ids":useful_topic_ids}
          else:
            recommend_topic_ids,rank_topic_ids = get_home_recommend_topic_ids(user_id, device_id, tag_id=0, offset=0, size=size,
                                                           query_type=query_type,promote_topic_list=promote_topic_list)

            return {"linucb_topic_ids": recommend_topic_ids,"rank_topic_ids":rank_topic_ids}
    except:
        logging.error("catch exception,err_msg:%s" % traceback.format_exc())
        if usefulrecall != -1:
          return {"linucb_topic_ids": [],"rank_topic_ids":[],"useful_topic_ids":[]}
        else:
          return {"linucb_topic_ids": [], "rank_topic_ids": []}


@bind("physical/search/discover_page")
def discover_page(device_id="", user_id=-1, size=10):
    """
    :remark:首页推荐,目前只推荐日记
    :param session_id:
    :param user_id:
    :param offset:
    :param size:
    :return:
    """
    try:
        if not user_id:
            user_id = -1
        if not isinstance(device_id, str):
            device_id = ""

        recommend_topic_ids = get_discover_page_topic_ids(user_id, device_id, size, query_type=TopicPageType.FIND_PAGE)

        return {"recommend_topic_ids": recommend_topic_ids}
    except:
        logging.error("catch exception,err_msg:%s" % traceback.format_exc())
        return {"recommend_topic_ids": []}


@bind("physical/search/home_query")
def home_query(device_id="", tag_id=-1, user_id=-1, query="", offset=0, size=10):
    """
    :remark:首页搜索,目前只推荐日记
    :param session_id:
    :param user_id:
    :param query:
    :param offset:
    :param size:
    :return:
    """
    try:
        if not user_id:
            user_id = -1
        if not isinstance(device_id, str):
            device_id = ""

        recommend_topic_list, rank_topic_id_list = get_home_recommend_topic_ids(user_id, device_id, tag_id, offset=offset, size=size, query=query)
        if len(rank_topic_id_list)>0 and len(rank_topic_id_list)<size:
            recommend_topic_list, rank_topic_id_list = get_home_recommend_topic_ids(user_id, device_id, tag_id,
                                                                                    offset=offset, size=size,
                                                                                    query=query,disable_collpase=True)
        return {"recommend_topic_ids": rank_topic_id_list}
    except:
        logging.error("catch exception,err_msg:%s" % traceback.format_exc())
        return {"recommend_topic_ids": []}


@bind("physical/search/topic_detail_page_recommend")
def topic_detail_page_recommend(device_id="", user_id=-1, topic_id=-1, topic_pictorial_id=-1, topic_user_id=-1,
                                filter_topic_user_id=False, offset=0, size=10, topic_tag_list=[]):
    """
    :remark:帖子详情页推荐策略,缺少第一个卡片策略
    :param user_id:
    :param topic_id:
    :param topic_group_id:
    :param topic_user_id:
    :return:
    """
    try:
        if not isinstance(user_id, int):
            user_id = -1
        if user_id > 0:
                redis_key = "physical:topic_detail_recommend" + ":user_id:" + str(user_id) + "topic_id:"+str(topic_id)
        else:
                redis_key = "physical:topic_detail_recommend" + ":device_id:" + device_id + "topic_id:"+str(topic_id)
        if int(offset) == 0:
            have_read_topic_list = list()
            # redis_dict = {
            #     "have_read_topic_id": json.dumps(have_read_topic_list)
            # }
            redis_client.delete(redis_key)
            # redis_client.expire(redis_key, 60 * 60 * 24)

        else:
            have_read_topic_list = list()
            redis_field_list = [b'have_read_topic_list']

            have_read_topic_redis_data = redis_client.hmget(redis_key,redis_field_list)
            have_read_topic_list = json.loads(have_read_topic_redis_data[0]) if have_read_topic_redis_data[0] else []
        es_cli_obj = ESPerform.get_cli()
        have_read_topic_list.append(topic_id)
        topic_user_result = list()
        topic_tag_result = list()
        result = list()
        if len(topic_tag_list) != 0:
             topic_tag_result = TopicUtils.top_get_topic_detail_recommend_list(user_id,topic_id,have_read_topic_list,size,es_cli_obj,
                                                                               index_type="topic",routing="3,4,5,6",topic_tag_list = topic_tag_list)
             topic_tag_size = len(topic_tag_result)
             have_read_topic_list.extend(topic_tag_result)
        else:
             topic_tag_size = 0
        if topic_tag_size <size:
           size = size - topic_tag_size
           if topic_user_id != -1:
              topic_user_result = TopicUtils.top_get_topic_detail_recommend_list(user_id, topic_id, have_read_topic_list,
                                                                              size, es_cli_obj,
                                                                              index_type="topic", routing="3,4,5,6",topic_user_id = topic_user_id
                                                                              )
              topic_user_size = len(topic_user_result)
              have_read_topic_list.extend(topic_user_result)
              if topic_user_size < size:
                 size = size - topic_user_size
                 result = TopicUtils.top_get_topic_detail_recommend_list(user_id, topic_id,
                                                                                  have_read_topic_list,
                                                                                  size, es_cli_obj,
                                                                                  index_type="topic", routing="4,5,6")
                 have_read_topic_list.extend(result)

        # have_read_topic_redis_data = redis_client.get(redis_key)
        # have_read_topic_list = json.loads(have_read_topic_redis_data) if have_read_topic_redis_data else []
        #
        # redis_key = "physical:topic_detail_page_recommend" + ":user_id:" + str(user_id) + ":device_id:" + str(device_id)
        # have_read_topic_redis_data = redis_client.get(redis_key)
        # have_read_topic_list = json.loads(have_read_topic_redis_data) if have_read_topic_redis_data else []
        #
        # # 获取es链接对象
        # es_cli_obj = ESPerform.get_cli()
        #
        # # 获取帖子标签列表
        # topic_tag_list = TopicUtils.get_topic_tag_id_list(topic_id, es_cli_obj)

        # result_list = TopicUtils.get_topic_detail_recommend_list(user_id, topic_id, topic_tag_list, topic_pictorial_id,
        #                                                          topic_user_id, filter_topic_user_id,
        #                                                          have_read_topic_list, offset, size, es_cli_obj,index_type="topic",routing="4,5,6")
        # result_list = TopicUtils.get_recommend_topic_ids(user_id, tag_id=-1, single_size=size, offset=offset, size=size,
        #                                                  topic_user_id=topic_user_id, current_topic_id=topic_id,
        #                                                  topic_tag_list=topic_tag_list)
        #
        # user_recommend_list = TopicUtils.get_recommend_topic_ids(user_id, tag_id=-1, single_size=size, offset=offset, size=size,
        #                                                  topic_user_id=topic_user_id, current_topic_id=topic_id,
        #                                                  topic_tag_list=topic_tag_list)
        redis_dict = {
            "have_read_topic_list": json.dumps(have_read_topic_list),
        }
        redis_client.hmset(redis_key, redis_dict)
        redis_client.expire(redis_key, 60 * 60 * 24)

        result_list = []
        logging.warning("topic_tag_result:%s" % str(topic_tag_result))
        logging.warning("topic_user_result:%s" % str(topic_user_result))
        logging.warning("result:%s" % str(result))
        recommend_topic_ids_list = list()
        recommend_topic_ids_list.extend(topic_tag_result)
        recommend_topic_ids_list.extend(topic_user_result)
        recommend_topic_ids_list.extend(result)
        return {"recommend_topic_ids": recommend_topic_ids_list}
    except:
        logging.error("catch exception,err_msg:%s" % traceback.format_exc())
        return {"recommend_topic_ids": []}


@bind("physical/search/query_topic_by_tag_aggregation")
def query_topic_by_tag_aggregation(user_id, tag_id, offset, size):
    """
    :remark 按标签聚合召回帖子
    :param tag_id:
    :param offset:
    :param size:
    :return:
    """
    try:
        if not user_id:
            user_id = -1
        if not tag_id:
            tag_id = -1

        result_list = TopicUtils.get_tag_aggregation_topic_id_list(user_id, tag_id, offset, size)
        recommend_topic_ids_list = list()
        if len(result_list) > 0:
            recommend_topic_ids_list = [item["_source"]["id"] for item in result_list]

        return {"recommend_topic_id": recommend_topic_ids_list}
    except:
        logging.error("catch exception,err_msg:%s" % traceback.format_exc())
        return {"recommend_topic_id": []}


@bind("physical/search/topic")
def topic_search(filters, nfilters=None, sorts_by=None, offset=0, size=10):
    """帖子搜索。"""

    try:
        (topic_id_list,total_count) = TopicUtils.list_topic_ids(filters=filters, nfilters=nfilters,
                                                sorts_by=sorts_by, offset=offset, size=size)

        return {
            "topic_ids": topic_id_list,
            "total_count": total_count
        }
    except:
        logging.error("catch exception, err_msg:%s" % traceback.format_exc())
        return {"topic_ids": [], "total_count": 0}


@bind("physical/search/query_topic_by_user_similarity")
def query_topic_by_user_similarity(topic_similarity_score_dict, offset=0, size=10):
    """
    :remark 按帖子所属用户相似度召回帖子
    :param tag_id:
    :param offset:
    :param size:
    :return:
    """
    try:

        must_topic_id_list = list(topic_similarity_score_dict.keys())
        topic_id_list = TopicUtils.get_recommend_topic_ids(tag_id=0, user_id=-1, offset=offset, size=size,single_size=size,
                                                           must_topic_id_list=must_topic_id_list,index_type="topic",routing="4,5,6")

        return {"recommend_topic_ids": topic_id_list}
    except:
        logging.error("catch exception,err_msg:%s" % traceback.format_exc())
        return {"recommend_topic_id": []}