# -*- coding: UTF-8 -*-
import functools
import logging
import traceback
import base64
import redis
import random
import json
from kafka import KafkaConsumer
from gm_rpcd.all import bind
from django.conf import settings
from libs.cache import redis_client
from libs.error import logging_exception
from django.db import models
from gm_types.gaia import SEARCH_KEYWORDS_TYPE, SEARCH_KEYWORDS_POSITION, HOT_SEARCH_JUMP_TYPE
from libs.neo4j import Neo4jManager


class SearchKeyword(models.Model):
    class Meta:
        verbose_name = u'搜索关键字'
        db_table = 'api_searchkeyword'
        app_label = 'gaia'

    keyword = models.CharField(max_length=20, help_text=u'关键字')
    is_online = models.BooleanField(default=True, help_text=u'是否上线')
    rank = models.IntegerField(max_length=10, help_text=u'排序')
    type = models.CharField(max_length=8, choices=SEARCH_KEYWORDS_TYPE, default=SEARCH_KEYWORDS_TYPE.DEFAULT)
    position = models.IntegerField(max_length=10, choices=SEARCH_KEYWORDS_POSITION,
                                   default=SEARCH_KEYWORDS_POSITION.DEFAULT)


class SearchHotWords(models.Model):
    """
    master database
    """

    class Meta:
        verbose_name = u'外显搜索词'
        db_table = 'api_hot_search_words'
        app_label = 'gaia'

    keywords = models.CharField(verbose_name=u'搜索词', max_length=128)
    create_time = models.DateTimeField(verbose_name=u'创建时间', auto_now_add=True)
    is_delete = models.BooleanField(verbose_name=u'是否删除', auto_created=False)


class Tag(models.Model):
    """
    master database
    """

    class Meta:
        verbose_name = u'标签'
        db_table = 'api_tag'
        app_label = 'gaia'

    name = models.CharField(verbose_name=u'标签名称', max_length=128)
    tag_type = models.CharField(verbose_name=u'标签类型', max_length=128)


@bind('doris/search/get_relation_query')
def get_relation_query(query="", size=6, offset=0, device_id=""):
    """
    搜索相关
    先取标签的如果标签的数据有了就不取其他的
    没有在去判断其他的
    再取同义词近义词
    :param query:
    :param size:
    :return:
    """
    try:
        tag_info_tag_set = list()
        tag_info_word = list()
        tag_info_synonym = list()
        tag_info_resemble = list()
        have_read_name_set = list()
        return_tag_name = list()
        """
        需要过滤已读
        """
        have_readkey = "relation_query_have_read:device_id:" + str(device_id) + ":query:" + str(query)
        if offset != 0:
            data = redis_client.get(str(have_readkey))
            if data is not None and data != "null":
                have_read_name_set = json.loads(str(data, encoding="utf-8"))

        tag_info_tag_set = get_data(query=query)
        return_tag_name = tag_info_tag_set[offset:offset + size]

        if len(return_tag_name) >= size:
            for item in return_tag_name:
                have_read_name_set.append(item)
            redis_client.set(str(have_readkey), json.dumps(have_read_name_set))

        else:
            tag_info = Neo4jManager.neo4j_get_related_word_by_graph(
                graph_obj=Neo4jManager.neo4j_get_graph_obj(), query_word=query,
                graph_related_word_set=set(return_tag_name), have_read_name_set=set(have_read_name_set),
                need_size=size - len(return_tag_name), redis_client=redis_client)

            if len(tag_info) >= size:
                return_tag_name = list(tag_info)[0:size]
                for item in return_tag_name:
                    have_read_name_set.append(item)
                redis_client.set(str(have_readkey), json.dumps(have_read_name_set))
            else:
                have_read_data = have_read_name_set[0:size - len(tag_info)]
                for item in have_read_data:
                    return_tag_name.append(item)
                redis_client.set(str(have_readkey), json.dumps(return_tag_name))

        redis_client.expire(str(have_readkey), 60 * 60)

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


@bind('doris/search/get_default_word')
def get_default_word(device_id=""):
    """
    个性化展示数据限制为9个，热门词4-5个，运营配置词1-2个，总数保证为15个
    个性化：选词不足9个时，通过热门词进行补充
    运营配置词：最多展示2个，如后台运营配置词多于2个，则展示最新配置的运营词。
    :param device_id:
    :return:
    """
    try:
        all_data = list()
        tag_name_key = "user_click_search_query:device_id:" + str(device_id)
        data = redis_client.get(tag_name_key)
        list_tag_name = list()
        if data is not None:
            list_tag_name = json.loads(data)

        if len(list_tag_name) >= 9:
            all_data = list_tag_name[:9]

        else:
            all_data = list_tag_name

        # 取运营配置的query词
        all_ids = SearchKeyword.objects.filter(is_online=True, position=SEARCH_KEYWORDS_POSITION.DEFAULT).exclude(
            keyword__in=list(all_data)).values_list("id", flat=True)
        selected_ids = random.sample(list(all_ids), 2)
        conetnt_data = list(
            SearchKeyword.objects.filter(is_online=True, id__in=selected_ids).values_list("keyword", flat=True))
        all_data.extend(conetnt_data)

        # 取热搜词
        content_data = SearchHotWords.objects.filter(is_delete=False).exclude(keywords__in=list(all_data)).values_list(
            "keywords", flat=True).order_by(
            "-create_time")[:15 - len(all_data)]
        all_data.extend(content_data)

        return {"default_word_list": all_data}

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


#
@bind('doris/search/feed_other_watch')
def feed_other_watch(device_id="", tag_ids=[], size=4):
    """
    个性化展示数据限制为9个，热门词4-5个，运营配置词1-2个，总数保证为15个
    个性化：选词不足9个时，通过热门词进行补充
    运营配置词：最多展示2个，如后台运营配置词多于2个，则展示最新配置的运营词。
    :param device_id:
    :return:
    """
    try:

        all_tag_query = list()
        query = list(set(Tag.objects.filter(id__in=tag_ids, tag_type__in=[1, 2, 3]).values_list("name", flat=True)))
        all_tag_query.extend(query)
        for item in query:
            return_tag_querys = get_data(query=item)
            all_tag_query.extend(return_tag_querys)

        if len(all_tag_query) > 4:
            other_watch_list = random.sample(all_tag_query, size)
            return {"other_watch_list": other_watch_list}
        else:
            return {"other_watch_list": all_tag_query}

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


def get_data(query=""):
    ##获得标签
    try:
        tag_info_tag_set = list()
        redis_key_prefix = "doris_search:{}:relation_query_tag"
        query_base64 = base64.b64encode(query.encode('utf8')).decode('utf8')
        key = redis_key_prefix.format(query_base64)
        data = redis_client.get(key)
        tag_info_word = list()
        tag_info_synonym = list()
        tag_info_resemble = list()
        if data is not None:
            tag_info_tag_set = json.loads(str(data, encoding="utf-8"))
        else:
            redis_key_prefix = "doris_search:{}:relation_query_word"
            query_base64 = base64.b64encode(query.encode('utf8')).decode('utf8')
            key = redis_key_prefix.format(query_base64)
            data = redis_client.get(key)
            if data is not None:
                tag_info_word = json.loads(str(data, encoding="utf-8"))
            for item in tag_info_word:
                if item != query:
                    tag_info_tag_set.append(item)

            redis_key_prefix = "doris_search:{}:relation_query_wordsynonym"
            query_base64 = base64.b64encode(query.encode('utf8')).decode('utf8')
            key = redis_key_prefix.format(query_base64)
            data = redis_client.get(key)
            if data is not None:
                tag_info_synonym = json.loads(str(data, encoding="utf-8"))
            for item in tag_info_synonym:
                if item != query:
                    tag_info_tag_set.append(item)

            redis_key_prefix = "doris_search:{}:relation_query_wordresemble"
            query_base64 = base64.b64encode(query.encode('utf8')).decode('utf8')
            key = redis_key_prefix.format(query_base64)
            data = redis_client.get(key)
            if data is not None:
                tag_info_resemble = json.loads(str(data, encoding="utf-8"))
            for item in tag_info_resemble:
                if item != query:
                    tag_info_tag_set.append(item)

        return tag_info_tag_set

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