#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.core.management.base import BaseCommand
import redis
import base64
import json
import hashlib
import datetime
import traceback
from rpc.cache import common_cache as redis_client
from api.models.hot_wiki_keyword import Wiki_Keyword
import logging
from search.utils.es import get_es, es_index_adapt
from django.conf import settings
from api.models.estypes import Hospitals, Doctors, Areas, Countrys, Products, Projects, Brands, Items, Collect
from api.models.tag import TagRelation
from api.models.collect import CollectWiki
from api.models.item import NewItemWiki
from api.models.search_hot_words import ALSearchRank
from wiki.models.collect import CollectItem
from rpc.tool.log_tool import smart_rank_logger
from api.models.hot_tractate_keyword import Tractate_Keyword
from api.models.wikitag import WordRel_wiki, Wiki_wordrelsynonym, Wiki_wordrelresemble
from api.tasks.smart_rank import update_smart_rank, update_smart_rank_v4

# from api.tool.log_tool import logging_exception

logger = logging.getLogger('async_debug')
redis_client = redis.StrictRedis.from_url(settings.DORIS_URL)


class SyncDataToRedis(object):

    @classmethod
    def sync_face_similar_data_to_redis(cls):
        try:
            logging.info("get into sync_face_similar_data_to_redis")
            now = datetime.datetime.now()
            yes_time = now - datetime.timedelta(days=1)
            yes_time_str = yes_time.strftime('%Y%m%d')
            result_items = Wiki_Keyword.objects.filter(visit_time=yes_time_str).values(
                "city_id").values_list("city_id", flat=True)
            redis_key_prefix = "gaia:hot_wiki_keyword:city_id:"
            for city_id in result_items:
                redis_key = redis_key_prefix + str(city_id)
                get_result_items = Wiki_Keyword.objects.filter(visit_time=yes_time_str,
                                                               city_id=city_id,
                                                               ).order_by(
                    "visit_num")
                logging.info("duan add,print get_result_items:%s" % get_result_items)

                wiki_id_list = list()
                wiki_id_visit_num = {}
                for item in get_result_items:
                    if item.wiki_id not in wiki_id_visit_num.keys():
                        wiki_id_visit_num[item.wiki_id] = item.visit_num
                    if item.wiki_type == 0:
                        wiki_id_list.append(item.wiki_id)
                    elif item.wiki_type == 1:
                        wiki_id_list.append(10000 + item.wiki_id)
                    elif item.wiki_type == 2:
                        wiki_id_list.append(20000 + item.wiki_id)
                    elif item.wiki_type == 3:
                        wiki_id_list.append(30000 + item.wiki_id)

                item_list = list()
                q = {
                    "_source": ["id", "name", "wikitype"],
                    "query": {
                        "function_score": {
                            "query": {
                                "bool": {
                                    "filter": [{
                                        "terms": {
                                            "_id": wiki_id_list
                                        }
                                    },
                                        {
                                            "term": {
                                                "is_online": True
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    }
                }

                es = get_es()
                index = es_index_adapt(
                    index_prefix=settings.ES_INDEX_PREFIX,
                    doc_type='newwiki',
                    rw='read'
                )
                res = es.search(
                    index=index,
                    doc_type='newwiki',
                    timeout=settings.ES_SEARCH_TIMEOUT,
                    body=q,
                    from_=0,
                    size=30)
                result_data = res['hits']['hits']
                logging.info("result_data:%s" % result_data)

                for item in result_data:
                    wiki_id = item['_source']['id']
                    wiki_name = item['_source']['name']
                    wiki_type = item['_source']['wikitype']

                    item_list.append(
                        {
                            "wiki_id": wiki_id,
                            "wiki_type": wiki_type,
                            "wiki_name": wiki_name,
                            "visit_num": wiki_id_visit_num[wiki_id]
                        }
                    )
                item_lists = sorted(item_list, key=lambda e: e.__getitem__('visit_num'), reverse=True)
                if len(item_lists) <= 10:
                    redis_client.set(redis_key, json.dumps(item_lists))
                else:
                    redis_client.set(redis_key, json.dumps(item_lists[:10]))
        except:
            logging.error("catch exception,err_msg:%s" % traceback.format_exc())

    @classmethod
    def es_type_data_to_redis(cls):

        logging.info("into es ")
        try:
            QUERY_KEY = "query:{}:set"
            names = Hospitals.objects.all().values_list("name", flat=True)
            for name in names:
                query_base64 = base64.b64encode(name.encode('utf8')).decode('utf8')
                key = QUERY_KEY.format(query_base64)
                value = 'hospital'
                redis_client.sadd(key, value)

            names = Doctors.objects.all().values_list("name", flat=True)
            for name in names:
                query_base64 = base64.b64encode(name.encode('utf8')).decode('utf8')
                key = QUERY_KEY.format(query_base64)
                # logging.info("get key:%s" % key)
                value = 'doctor'
                redis_client.sadd(key, value)

            names = list()
            country_names = Countrys.objects.all().values_list("name", flat=True)
            areas_names = Areas.objects.all().values_list("name", flat=True)
            names.append(country_names)
            names.append(areas_names)
            for name in names:
                if name != "china":
                    for item in name:
                        query_base64 = base64.b64encode(item.encode('utf8')).decode('utf8')
                        key = QUERY_KEY.format(query_base64)
                        value = 'area'
                        redis_client.sadd(key, value)
            #
            logging.info("set redis success wiki")

            pro_names = []
            proj_names = Products.objects.filter(product_type__in=[1, 2, 3])
            proje_names = Projects.objects.filter(tag_type__in=[1, 2, 0])
            item_names = Items.objects.all()
            collect_names = Collect.objects.all()
            bran_names = Brands.objects.all()
            pro_names.append(proje_names)
            pro_names.append(proj_names)
            pro_names.append(bran_names)
            pro_names.append(item_names)
            pro_names.append(collect_names)
            for name in pro_names:
                for item in name:
                    query_base64 = base64.b64encode(item.name.encode('utf8')).decode('utf8')
                    key = QUERY_KEY.format(query_base64)
                    value = 'project'
                    redis_client.sadd(key, value)

            logging.info("set redis success face")
            logging.info("get redis:%s" % redis_client)
            face_list = ['整形模拟器', '模拟器', '整容模拟器', '模拟整形', '模拟整容', '模拟',
                         '整容模拟', '整形模拟', '微整模拟器', '微整模拟', '模拟微整', '变美模拟器',
                         '整型模拟器', '模拟测试', '美容模拟器', '模拟器测试', '模拟变美', '变美模拟',
                         '美容模拟', '模拟美容', '魔镜', '更美魔镜', '变美魔镜', '测试颜值', '微整测试',
                         '整容测试', '整形测试']
            for i in face_list:
                logging.info("get list i:%s" % i)
                query_base64 = base64.b64encode(i).decode('utf8')
                key = QUERY_KEY.format(query_base64)
                logging.info("get key:%s" % key)
                value = 'face'
                redis_client.sadd(key, value)
                logging.info("set redis success")

            logging.info("set redis success free")
            logging.info("get redis:%s" % redis_client)
            face_list = ['免费', '免费招募', '免费整形', '免费模特', '免费整', '招募', '模特招募', '招募模特',
                         '案例招募', '0元', '0元整形', '0元变美', '免费整形招募', '免费整招募', '免费整容',
                         '0元整容', '免费模特招募', '免费体验', '免费项目', '免费招募模特']
            for i in face_list:
                logging.info("get list i:%s" % i)
                query_base64 = base64.b64encode(i).decode('utf8')
                key = QUERY_KEY.format(query_base64)
                logging.info("get key:%s" % key)
                value = 'free_face'
                redis_client.sadd(key, value)
                logging.info("set redis success")


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

    @classmethod
    def sync_tractate_data_to_redis(cls):
        try:

            logging.info("get into sync_face_similar_data_to_redis")
            now = datetime.datetime.now()
            yes_time = now - datetime.timedelta(days=1)
            yes_time_str = yes_time.strftime('%Y%m%d')
            result_items = Tractate_Keyword.objects.filter(search_time=yes_time_str).values(
                "city_id").values_list("city_id", flat=True)
            redis_key_prefix = "gaia:hot_tractate_keyword:city_id:"
            for city_id in result_items:
                redis_key = redis_key_prefix + str(city_id)
                get_result_items = Tractate_Keyword.objects.filter(search_time=yes_time_str, city_id=city_id).order_by(
                    "search_num")
                logging.info("print get_result_items:%s" % get_result_items)
                item_lists = list()
                # search_num_list = dict()
                for item in get_result_items:
                    item_lists.append(item.tractate_id)
                    # search_num_list.append({"tractate_id": item.tractate_id, "search_num": item.search_num})
                    # search_num_list[item.tractate_id] = item.search_num

                logging.info("get item_lists:%s" % item_lists)
                q = {
                    "_source": ["id", "tractate_tag_name"],
                    "query": {
                        "terms": {
                            "id": item_lists
                        }
                    }
                }
                es = get_es()
                index = es_index_adapt(
                    index_prefix=settings.ES_INDEX_PREFIX,
                    doc_type='tractate',
                    rw='read'
                )
                res = es.search(
                    index=index,
                    doc_type='tractate',
                    timeout=settings.ES_SEARCH_TIMEOUT,
                    body=q,
                    from_=0,
                    size=30)
                result_data = res['hits']['hits']
                logging.info("result_data:%s" % result_data)

                tractate_tag_name_list = list()
                for item in result_data:
                    tractate_id = item['_source']['id']
                    tractate_tag_name = item['_source']['tractate_tag_name']
                    tractate_tag_name_list.append({"id": tractate_id, "tractate_tag_name": tractate_tag_name})

                ###获取每个tag_name的赞的个数
                tag_name_list = dict()
                for i in tractate_tag_name_list:
                    id = i.get("id")
                    tractate_name = i.get("tractate_tag_name")
                    search = Tractate_Keyword.objects.filter(tractate_id=id).values_list("search_num", flat=True)
                    logging.info("get tractate_name")
                    for j in tractate_name:
                        if j in tag_name_list.keys():
                            tag_name_list[j] += int(search[0])
                        else:
                            tag_name_list[j] = int(search[0])

                item_lists = sorted(tag_name_list.items(), key=lambda x: x[1], reverse=True)
                logging.info("get item_lists:%s" % item_lists)
                if len(item_lists) <= 10:
                    redis_client.set(redis_key, json.dumps(item_lists))
                else:
                    redis_client.set(redis_key, json.dumps(item_lists[:10]))

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

    @classmethod
    def get_query_relation_search(cls):
        """
        存储用户相关搜索词
        :return:
        """
        try:
            redis_key_prefix = "doris_search:{}:relation_query_tag"
            # 先从获取tag的数据到获取tag的同义词近义词
            all_tag_data = list(Projects.objects.filter(tag_type__in=[1, 2, 3]).values("id", "name", "tag_type"))
            for item in all_tag_data:
                tag_id = item.get("id", None)
                tag_name = item.get("name", None)
                tag_type = item.get("tag_type", None)
                logging.info("get tag_type:%s" % tag_type)
                logging.info("get tag_type:%s" % type(tag_type))

                all_tag_name = set()
                query_base64 = base64.b64encode(tag_name.encode('utf8')).decode('utf8')
                key = redis_key_prefix.format(query_base64)
                logging.info("get tag_id:%s" % tag_id)
                if int(tag_type) == 1 or int(tag_type) == 2:
                    # 获取一二级标签的子标签  一级标签只有二级的子标签  二级只有三级
                    relation_tag_info = list(TagRelation.objects.filter(parent_id=tag_id, is_deleted=False).values_list(
                        "child_id", flat=True))
                    child_tag_info = list(
                        Projects.objects.filter(id__in=relation_tag_info).values("id", "name"))
                    for i in child_tag_info:
                        tag_id = i.get("id", None)
                        tag_name = i.get("name", None)
                        all_tag_name.add(tag_name)
                else:
                    # 三级只获取三级的标签
                    parent_id = list(TagRelation.objects.filter(child_id=tag_id, is_deleted=False).values_list(
                        "parent_id", flat=True))
                    child_id = list(TagRelation.objects.filter(parent_id__in=parent_id, is_deleted=False).values_list(
                        "child_id", flat=True))
                    child_tag_info = list(
                        Projects.objects.filter(id__in=child_id).values("id", "name"))
                    for i in child_tag_info:
                        tag_id = i.get("id", None)
                        tag_name = i.get("name", None)
                        all_tag_name.add(tag_name)

                ##再获取相关的同义词近义词
                word_info = WordRel_wiki.objects.filter(keyword=tag_name, category__in=(1, 9, 11, 12, 13)).values_list(
                    "id", flat=True).first()
                ##获得同义词
                word_synonym = list(
                    Wiki_wordrelsynonym.objects.filter(wordrel_id=word_info).values_list("word", flat=True))
                for synonym in word_synonym:
                    all_tag_name.add(synonym)
                ##获得近义词
                word_resemble = list(
                    Wiki_wordrelresemble.objects.filter(wordrel_id=word_info).values_list("word", flat=True))
                for resemble in word_resemble:
                    all_tag_name.add(resemble)

                logging.info("get tag data:%s" % all_tag_name)
                ##获取完之后去存到redis
                redis_client.set(key, json.dumps(list(all_tag_name)))

            # 获取所有关键词的同义词和近义词
            redis_key_prefix = "doris_search:{}:relation_query_word"
            word_info = list(WordRel_wiki.objects.filter(category__in=(1, 9, 11, 12, 13)).values("id", "keyword"))
            for word in word_info:
                logging.info("get word_id:%s" % word)
                word_id = word.get("id", None)
                keyword = word.get("keyword", None)
                all_tag_name = set()
                query_base64 = base64.b64encode(keyword.encode('utf8')).decode('utf8')
                key = redis_key_prefix.format(query_base64)
                logging.info("get key:%s" % key)
                # 获取该词的同义词和近义词
                ##获得同义词
                word_synonym = list(
                    Wiki_wordrelsynonym.objects.filter(wordrel_id=word_id).values_list("word", flat=True))
                for synonym in word_synonym:
                    logging.info("get synonym:%s" % synonym)
                    all_tag_name.add(synonym)
                ##获得近义词
                word_resemble = list(
                    Wiki_wordrelresemble.objects.filter(wordrel_id=word_id).values_list("word", flat=True))
                for resemble in word_resemble:
                    logging.info("get resemble:%s" % resemble)
                    all_tag_name.add(resemble)

                logging.info("get all_tag_name:%s" % all_tag_name)
                ##获取完之后去存到redis
                redis_client.set(key, json.dumps(list(all_tag_name)))

            # 获取单词的同义词
            redis_key_prefix = "doris_search:{}:relation_query_wordsynonym"
            word_synonym = list(Wiki_wordrelsynonym.objects.all().values_list("word", flat=True))
            for word in word_synonym:
                logging.info("get word:%s" % word)

                all_tag_name = set()
                query_base64 = base64.b64encode(word.encode('utf8')).decode('utf8')
                key = redis_key_prefix.format(query_base64)
                word_synonym_id = list(
                    Wiki_wordrelsynonym.objects.filter(word=word).values_list("wordrel_id", flat=True))
                word_info = list(
                    WordRel_wiki.objects.filter(category__in=(1, 9, 11, 12, 13), id__in=word_synonym_id).values_list(
                        "keyword", flat=True))
                logging.info("get word_info:%s" % word_info)

                for i in word_info:
                    all_tag_name.add(i)

                ##获取完之后去存到redis
                redis_client.set(key, json.dumps(list(all_tag_name)))

            # 获取单词的近义词
            redis_key_prefix = "doris_search:{}:relation_query_wordresemble"
            word_synonym = list(Wiki_wordrelresemble.objects.all().values_list("word", flat=True))
            for word in word_synonym:
                logging.info("get word:%s" % word)
                all_tag_name = set()
                query_base64 = base64.b64encode(word.encode('utf8')).decode('utf8')
                key = redis_key_prefix.format(query_base64)
                word_synonym_id = list(
                    Wiki_wordrelresemble.objects.filter(word=word).values_list("wordrel_id", flat=True))
                word_info = list(
                    WordRel_wiki.objects.filter(category__in=(1, 9, 11, 12, 13), id__in=word_synonym_id).values_list(
                        "keyword", flat=True))
                for i in word_info:
                    all_tag_name.add(i)

                ##获取完之后去存到redis
                redis_client.set(key, json.dumps(list(all_tag_name)))
        except:
            logging.error("catch exception,err_msg:%s" % traceback.format_exc())


class Command(BaseCommand):
    args = ''
    help = 'dump data to elasticsearch, parallel'

    from optparse import make_option

    option_list = BaseCommand.option_list + (
        make_option('-t', '--type', dest='type', help='type name to dump data to elasticsearch', metavar='TYPE',
                    default=''),
        make_option('-i', '--index-prefix', dest='index_prefix', help='index name to dump data to elasticsearch',
                    metavar='INDEX_PREFIX'),
        make_option('-p', '--parallel', dest='parallel', help='parallel process count', metavar='PARALLEL'),
        make_option('-s', '--pks', dest='pks', help='specify sync pks, comma separated', metavar='PKS', default=''),
        make_option('--streaming-slicing', dest='streaming_slicing', action='store_true', default=True),
        make_option('--no-streaming-slicing', dest='streaming_slicing', action='store_false', default=True),
        make_option('-S', '--sync_type', dest='sync_type', help='sync data to es', metavar='TYPE', default='')
    )

    def handle(self, *args, **options):
        try:
            if len(options["sync_type"]) and options["sync_type"] == "data_es":
                SyncDataToRedis.sync_face_similar_data_to_redis()
                logging.info("add a flag")

            if len(options["sync_type"]) and options["sync_type"] == "type_es":
                SyncDataToRedis.es_type_data_to_redis()
                logging.info("add a flag")

            if len(options["sync_type"]) and options["sync_type"] == "tractate_es":
                SyncDataToRedis.sync_tractate_data_to_redis()
                logging.info("add a flag")

            if len(options["sync_type"]) and options["sync_type"] == "relation_search":
                SyncDataToRedis.get_query_relation_search()
                logging.info("add a flag")

            if len(options["sync_type"]) and options["sync_type"] == "update_smart_rank":
                update_smart_rank()
                smart_rank_logger.info('[SMART_RANK] update finished!!!')

            if len(options["sync_type"]) and options["sync_type"] == "update_smart_rank_v4":
                update_smart_rank_v4()
                smart_rank_logger.info('[SMART_RANK] update finished!!!')
        except:
            logging.error("catch exception,err_msg:%s" % traceback.format_exc())
