import time
from django.conf import settings
from gm_types.gaia import (
    QUESTION_ORDER_TYPE,
    TOP_QUESTION_ORDER_TYPE,
)
from libs.es import es_query
from libs.es import tzlc
from libs.filters import area_tag_id_filter
from .diary import generate_diary_note_filter
from search.utils.service import recall_sku, recall_sku_by_new_search_analyze



def gen_query(query,use_fresh_tag=False):
    multi_fields = {
        # 'tags': 4,
        'title': 2,
        'content': 1
    }
    if use_fresh_tag:
        multi_fields["fresh_tags"] = 4
    else:
        multi_fields["tags"] = 4
    fields = ['^'.join((k, str(v))) for (k, v) in multi_fields.items()]
    m = {
        'query': query,
        'type': 'cross_fields',
        'operator': 'and',
        'fields': fields,
    }
    return {"multi_match": m}


# filters is dic, parse it to get es need format
def parse_filter(filters):
    f = []
    if not filters:
        return f

    for k, v in filters.items():
        if k == 'raw_tag_ids' and isinstance(v, list) and v:
            f.append({
                'terms': {'tag_ids': v}
            })
        elif k == 'tag_ids' and isinstance(v, list) and v:
            f.append({
                'terms': {'closure_tag_ids': v}
            })
        elif k == 'area_tag_id':
            f.append(area_tag_id_filter([''], v))
        elif k == 'has_recommended_answer':
            f.append({
                'term': {'has_recommended_answer': v}
            })
        elif k == 'created_time':
            f.append({
                'range': {'create_time': {'gte': tzlc(v)}}
            })
        elif k == 'answer_num_range':  # 新增回答数据的筛选过滤，传入是字典类型{"gte": xx,}
            f.append({
                'range': {'answers_num': v}
            })
        elif k == "question_types" and v:
            f.append({
                "terms": {"question_type": v}
            })
        elif k == "is_recommend":
            f.append({
                "term": {"is_recommend": v}
            })
        elif k == "content_type" and v:
            f.append({
                "terms": {"content_type": v}
            })

    return f


def get_problem_sorting(sort_type, sort_params={}):
    f = [
        #{'last_update_time': {'order': 'desc'}},
        {'latest_reply_time': {'order': 'desc'}},
        {'last_update_time': {'order': 'desc'}}
    ]


    return f

def get_problem_filter(filters):
    f = [
        {'term': {'is_online': True}},
        {"exists": {"field": "diary_id"}},
        {
            "range":{
                "content_level":{"gte":3}
            }
        }
    ]

    if not filters:
        return f

    res = generate_diary_note_filter(filters)
    if res:
        f.extend(res)

    # should_filter 对应的val也是dic,里面的item执行OR操作
    if "should_filter" in filters and filters["should_filter"]:
        res = generate_diary_note_filter(filters["should_filter"])
        if res:
            f.append({
                'bool': {
                    'should': res
                }
            })

    return f

def gen_filter(filters):

    f = [
        {'term': {'is_online': True}}
    ]

    if not filters:
        return f

    res = parse_filter(filters)
    if res:
        f.extend(res)

    # should_filter 对应的val也是dic,里面的item执行OR操作
    if "should_filter" in filters and filters["should_filter"]:
        res = parse_filter(filters["should_filter"])
        if res:
            f.append({
                'bool': {
                    'should': res
                }
            })

    return f


# def gen_filter(filters):
#     f = [
#         {'term': {'is_online': True}},
#     ]
#     if not filters:
#         return f
#
#     for k, v in filters.items():
#         if k == 'raw_tag_ids' and isinstance(v, list) and v:
#             f.append({
#                 'terms': {'tag_ids': v}
#             })
#         elif k == 'tag_ids' and isinstance(v, list) and v:
#             f.append({
#                 'terms': {'closure_tag_ids': v}
#             })
#         elif k == 'area_tag_id':
#             f.append(area_tag_id_filter([''], v))
#         elif k == 'has_recommended_answer':
#             f.append({
#                 'term': {'has_recommended_answer': v}
#             })
#         elif k == 'created_time':
#             f.append({'range': {'create_time': {'gte': tzlc(v)}}})
#
#         elif k == 'answer_num_range':  # 新增回答数据的筛选过滤，传入是字典类型{"gte": xx,}
#             f.append({'range': {'answers_num': v}})
#         elif k == "question_types":
#             f.append({
#                 "terms":{"question_type":v}
#             })
#
#     return f

def gen_sorting(sort_type, sort_params={}):
    sort = [
        {
            '_script': {
                'lang': settings.ES_SCRIPT_LANG,
                'script_file': 'sort_question-sink-by-org',
                'type': 'number',
                'order': 'asc',
            }
        }
    ]

    if sort_type == QUESTION_ORDER_TYPE.DEFAULT:
        sort += [
            {'score': {'order': 'desc'}}
        ]

    elif sort_type == QUESTION_ORDER_TYPE.DROPDOWN_REFRESH:
        sort += [
            {'recommended_answer_create_time': {'order': 'desc'}}
        ]

    elif sort_type == QUESTION_ORDER_TYPE.DOCTOR_COVER:
        sort += [
            {'has_cover': {'order': 'desc'}}
        ]

    elif sort_type == QUESTION_ORDER_TYPE.DOCTOR_RECOMMEND:
        sort += [
            {'is_recommend': {'order': 'desc'}},
            {'answers_num': {'order': 'desc'}},
            {'create_time': {'order': 'desc'}},
        ]

    elif sort_type == QUESTION_ORDER_TYPE.DOCTOR_LASTEST:
        sort += [
            {'create_time': {'order': 'desc'}}
        ]

    elif sort_type == QUESTION_ORDER_TYPE.ANSWER_NUM:
        sort += [
            {'answers_num': {'order': 'desc'}},
            {'create_time': {'order': 'desc'}},
        ]

    elif sort_type == QUESTION_ORDER_TYPE.MOUTHGUN_RECOMMEND:
        sort += [
            {'score': {'order': 'desc'}}
        ]
    elif sort_type == QUESTION_ORDER_TYPE.UPDATE:
        sort += [
            {'last_update_time': {'order': 'desc'}},
            {'create_time': {'order': 'desc'}},
        ]

    elif sort_type == QUESTION_ORDER_TYPE.HOT:
        sort += [
            {'answers_num': {'order': 'desc'}},
        ]

    elif sort_type == QUESTION_ORDER_TYPE.PC_LASTEST_ANSWER:
        sort += [
            {'question_lastest_answer_time': {'order': 'desc'}},
            {'answers_num': {'order': 'desc'}},
            {'create_time': {'order': 'desc'}},
        ]

    return sort


def recall_recommend_question_and_sku(query, offset, size, filters={}, sort_type=QUESTION_ORDER_TYPE.DEFAULT, fields=[]):
    res = {}
    q = {}

    filtered = {}
    if query:
        filtered['query'] = gen_query(query)
    f = gen_filter(filters)
    filtered['filter'] = {
        "bool":{
             "must":f
        }
    }

    q = {
        "_source":{
          "include":["id","create_time","last_update_time"]
        },
        "query":{
            "filtered":filtered
        },
        "sort" : [
            {
                '_script': {
                    'lang': settings.ES_SCRIPT_LANG,
                    'script_file': 'sort_question-sink-by-org',
                    'type': 'number',
                    'order': 'asc',
                }
            },
            {'last_update_time':{'order': 'desc'}},
            {'score': {'order': 'desc'}}
        ]
    }

    question_res = es_query('question', q, offset, size)
    hits = question_res["hits"]["hits"]
    question_hit_ids = [hit["_source"] for hit in hits]
    res["question"] = question_hit_ids

    sku_res = recall_sku(
        query=query,
        offset=offset,
        size=size,
        filters=filters
    )
    if len(sku_res["hits"]["hits"]) > 0:
        res["service_id"] = sku_res["hits"]["hits"][0]["_source"]["id"]

    return res

def recall_question(query, offset, size, filters={}, sort_type=QUESTION_ORDER_TYPE.DEFAULT, sort_params={}, fields=[],use_fresh_tag=False):
    size = min(size, settings.COUNT_LIMIT)

    filtered = {}

    if query:
        filtered['query'] = gen_query(query,use_fresh_tag)

    s = gen_sorting(sort_type, sort_params)
    f = gen_filter(filters)
    filtered['filter'] = {
        "bool":{
             "must":f
        }
    }

    if "id" not in fields:
        fields.append("id")
    fields.extend(["create_time","last_update_time"])

    q = {
        "_source": {
            "include": fields
        },
        "query":{
            "filtered":filtered
        },
        "sort":s
    }

    res = es_query('question', q, offset, size)
    hits = res["hits"]["hits"]
    hit_ids = [hit["_source"] for hit in hits]
    return hit_ids

def recall_problem(query, offset, size, filters={}, sort_type=QUESTION_ORDER_TYPE.DEFAULT, sort_params={}):
    size = min(size, settings.COUNT_LIMIT)

    filtered = {}
    if query:
        filtered["query"] = gen_query(query)

    f = get_problem_filter(filters)
    s = get_problem_sorting(sort_type, sort_params)

    filtered["filter"] = {
        "bool":{
            "must": f
        }
    }
    fields = ["closure_tag_ids","tag_ids","diary_id","id","created_time","last_update_time","latest_reply_time"]

    q = {
        "_source":{
            "include": fields
        },
        "query":{
            "filtered": filtered,
        },
        "sort": s
    }

    res = es_query('problem', q, offset, size)
    hits = res["hits"]["hits"]
    hit_ids = [hit["_source"] for hit in hits]
    return hit_ids


def get_top_question_filters(filters):
    _timestamp = int(time.time())
    f = [
        {'term': {'enable': True}},
        {"exists": {"field": "question_id"}},
        {'range': {"start_time_epoch": {"lte": _timestamp}}},
        {'range': {"end_time_epoch": {"gte": _timestamp}}},
    ]

    if not filters:
        return f

    for k, v in filters.items():
        if k == 'raw_tag_ids' and isinstance(v, list) and v:
            f.append({'terms': {'tag_ids': v}})

        elif k == 'tag_ids' and isinstance(v, list) and v:
            f.append({'terms': {'closure_tag_ids': v}})

        elif k == "top_type":
            f.append({"term": {"top_type": v}})

    return f


def recall_top_question(sort_type, filters={}, offset=0, size=10):
    """
    召回置顶回答
    :param sort_type:
    :param filters:
    :param offset:
    :param size:
    :return:
    """
    size = min(size, settings.COUNT_LIMIT)

    f = get_top_question_filters(filters)
    filtered = {
        "filter": {
            "bool": {
                "must": f,
            }
        }
    }

    sorting = []

    if sort_type == TOP_QUESTION_ORDER_TYPE.DEFAULT:
        sorting += [{'create_time': {'order': 'desc'}}]

    q = {
        "_source": {
            "include": ["id", "question_id"],
        },
        "query": {
            "filtered": filtered
        },
        "sort": sorting
    }

    res = es_query('qa_top', q, offset, size)
    hits = res["hits"]["hits"]
    hit_ids = [hit["_source"] for hit in hits]

    return hit_ids
