import functools
import json
from gm_rpcd.all import bind, context
from gm_types.doris import ANSWER_SORT_TYPE
from libs.es import es_query
from libs.algorithms import variousness, drop_dup2
import traceback
import logging
from libs.cache import redis_client
from search.utils.answer import recall_ans

MAX_LOAD = 200
GROUP_SIZE = 10
variousness_per_10 = functools.partial(variousness, variety_size=GROUP_SIZE)


@bind("doris/query/answer")
def filter_answer(query="", offset=0, size=10, filters={}, sort_type=ANSWER_SORT_TYPE.DEFAULT, sort_params={},
                  have_read_answer_list=[]):
    logging.info("get context:%s" % context)
    tail = offset + size
    answer_ids = []
    items = []
    answer_extra = []

    try:
        if tail < MAX_LOAD:
            answers = recall_ans(query, 0, MAX_LOAD, filters, sort_type, fields=["id", "user_id", "question_id"],
                                 have_read_answer_list=have_read_answer_list)
            items = [{"id": answer["_source"]['id'], "group": answer["_source"]["user_id"],
                      "dup": answer["_source"]["question_id"], "score": answer["sort"],
                      "highlight": answer.get("highlight", {})} for answer in answers]
            items = drop_dup2(items)
            items = variousness_per_10(items)
            answer_ids = [item['id'] for item in items[offset:tail]]
            for item in items[offset:tail]:
                answer_id = item['id']
                answer_score = item['score']
                answer_highlight = item["highlight"]
                answer_extra.append({"id": answer_id, "score": answer_score, "highlight": answer_highlight})

        if len(answer_ids) < size:
            answers = recall_ans(query, offset, size, filters, sort_type, fields=["id"], recall_again=True,
                                 have_read_answer_list=have_read_answer_list)
            answer_ids = [item["_source"]['id'] for item in answers]
            for item in answers:
                answer_id = item["_source"]['id']
                answer_score = [item['_score']]
                answer_highlight = item["highlight"] if "highlight" in item else {}
                answer_extra.append({"id": answer_id, "score": answer_score, "highlight": answer_highlight})

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


@bind('doris/search/qa_sort')
def answer_sort(filters=None, offset=0, size=10, use_fresh_tag=False, device_id='', source_type=-1):
    try:
        """
        source_type 代表首页feed横划tab  0 代表不是  1代表是
        """
        redis_key = ""
        have_read_answer_id_list_redis = []
        if source_type == 1:
            if not isinstance(device_id, str):
                device_id = ""
            if device_id:
                redis_key = "doris_feed:home_recommend_question" + ":device_id:" + str(device_id)
                redis_question_val_list = redis_client.hmget(redis_key, source_type)
                # 获取已读question
                if redis_question_val_list[0]:
                    have_read_answer_id_list_redis = list(json.loads(redis_question_val_list[0]))

        filters = filters or {}
        tag_ids = []
        for k, v in filters.items():
            if k == "tag_ids":
                tag_ids = v
        q = {}
        if len(tag_ids) > 0:
            q["query"] = {
                "bool": {
                    "must": [
                        {"term": {"is_online": True}},
                        {"exists": {"field": "best_answer"}}
                    ]
                }
            }
            if use_fresh_tag:
                q["query"]["bool"]["must"] += [{"terms": {"fresh_tag_ids": tag_ids}}]
            else:
                q["query"]["bool"]["must"] += [{"terms": {"tag_ids": tag_ids}}]

            if have_read_answer_id_list_redis:
                q["query"]["bool"]["must_not"] = [{"terms": {"best_answer": have_read_answer_id_list_redis}}]

        else:
            q["query"] = {
                "bool": {
                    "must": {"term": {"is_online": True}}

                }
            }
            if have_read_answer_id_list_redis:
                q["query"]["bool"]["must_not"] = [{"terms": {"id": have_read_answer_id_list_redis}}]

        q["sort"] = {"create_time": {"order": "desc"}}

        answer_id_list = []
        have_read_question_data = []

        logging.info('test query es :%s' % str(q).encode('utf-8'))
        res = es_query('question', q, offset, size)
        res_hit = res["hits"]["hits"]
        for item in res_hit:
            if '_source' in item:
                id = item['_source']['best_answer']
                have_read_answer_id_list_redis.append(id)
                answer_id_list.append(id)

        if source_type == 1:
            if len(answer_id_list) == 0:
                if len(have_read_answer_id_list_redis) >= size:
                    redis_client.delete(redis_key)
                    redis_client.hset(redis_key, source_type, json.dumps(have_read_answer_id_list_redis[0:size]))
                    redis_client.expire(redis_key, 60 * 60 * 24 * 15)
                    answer_id_list = have_read_answer_id_list_redis[0:size]
                else:
                    redis_client.hset(redis_key, source_type, json.dumps(have_read_answer_id_list_redis))
                    redis_client.expire(redis_key, 60 * 60 * 24 * 15)
                    answer_id_list = have_read_answer_id_list_redis
            else:
                """
                    保存已读的问答数据
                """
                if redis_key:
                    redis_client.hset(redis_key, source_type, json.dumps(answer_id_list))
                    redis_client.expire(redis_key, 60 * 60 * 24 * 15)

        return {'answer_id_list': answer_id_list}

    except:

        logging.error("catch exception,logins:%s" % traceback.format_exc())

        return {'answer_id_list': []}


@bind('doris/search/qa_check_in')
def qa_check_in(device_id,size):
    try:
       key = 'device_register_qa_queue:'+str(device_id)
       if redis_client.exists(key):
          qa_dict = redis_client.hgetall(key)
          cursor = int(str(qa_dict[b'cursor'],encoding='utf-8'))
          qa_queue = json.loads(qa_dict[b'qa_queue'].decode())
          if cursor>=len(qa_queue):
              cursor = 0
          data = qa_queue[cursor:cursor+size]
          redis_client.hset(key,'cursor',cursor+size)
          if len(data) > 0:
             read_qa_key = "TS:recommend_answer_set:device_id:" + str(device_id)
             redis_client.sadd(read_qa_key,*data)
             read_register_qa_key = "device_register_qa_read_set:"+str(device_id)
             redis_client.sadd(read_register_qa_key,*data)
             redis_client.expire(read_qa_key,time = 15*24*60*60)
          return {'answer_id_list': data}
       else:
          return {'answer_id_list': []}
    except:

        logging.error("catch exception,logins:%s" % traceback.format_exc())

        return {'answer_id_list': []}