#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.core.management.base import BaseCommand
import redis
import base64
import json
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 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 rpc.all import get_rpc_remote_invoker

# 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("es_type_data_to_redis ")
        try:
            query_old_key = "query_type_set:{}"
            query_plan_key = "query_type_set:plan:"
            ##医院
            names = Hospitals.objects.filter(is_online=1).values_list("name", flat=True)
            for name in names:
                key = query_old_key.format(str(name))
                value = 'hospital'
                redis_client.sadd(key, value)

            ##医生
            names = Doctors.objects.filter(doctor_type=0, is_online=1).values_list("name", flat=True)
            for name in names:
                key = query_old_key.format(str(name))
                value = 'doctor'
                redis_client.sadd(key, value)

            ##项目
            pro_names = []
            proj_names = Products.objects.filter(product_type__in=[1, 2, 3], is_online=1)
            proje_names = Projects.objects.filter(tag_type__in=[1, 2, 0], is_online=1)
            item_names = Items.objects.filter(is_online=1)
            collect_names = Collect.objects.filter(is_online=1)
            bran_names = Brands.objects.filter(is_online=1)
            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:
                    key = query_old_key.format(item)
                    value = 'project'
                    redis_client.sadd(key, value)

            ##整形
            logging.info("set redis success face")
            all_face_query_list = []
            all_face_data = redis_client.get("all_face_query")
            if all_face_data:
                all_face_query_list = json.loads(all_face_data)
            for item in all_face_query_list:
                key = query_old_key.format(item)
                value = 'face'
                redis_client.sadd(key, value)

            ##免费整
            # logging.info("set redis success free")
            # face_list = ['免费', '免费招募', '免费整形', '免费模特', '免费整', '招募', '模特招募', '招募模特',
            #              '案例招募', '0元', '0元整形', '0元变美', '免费整形招募', '免费整招募', '免费整容',
            #              '0元整容', '免费模特招募', '免费体验', '免费项目', '免费招募模特']
            # for item in face_list:
            #     key = query_old_key.format(item)
            #     new_key = query_new_key.format(str(item))
            #     value = 'free_face'
            #     redis_client.sadd(key, value)
            #     redis_client.sadd(new_key, value)

        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(json.dumps({
                    "version": "SMART_RANK",
                    "status": "update finished"
                }))

            if len(options["sync_type"]) and options["sync_type"] == "update_smart_rank_v4":
                update_smart_rank_v4()
                smart_rank_logger.info(json.dumps({
                    "version": "SMART_RANK_V4",
                    "status": "update finished"
                }))
        except:
            logging.error("catch exception,err_msg:%s" % traceback.format_exc())
