# coding=utf-8
from django.conf import settings
from datetime import datetime

from .es import get_es, get_highlight, tzlc, es_index_adapt

from api.models.types import PROBLEM_FLAG_CHOICES, PROBLEM_ORDER_TYPE, PRIVATE_STATUS


def search_topic_admin(query='', user_city_tag_id=None, offset=0, size=5, filters={}, nfilters={}, sort=[]):
    '''
    医生后台帖子搜索
    '''
    # 参数验证
    size = min(size, settings.COUNT_LIMIT)

    # 搜索关键字部分
    # 搜索域
    if query:
        multi_fields = {
            'title': 3,
            'user.last_name':1
        }
        fields = ['^'.join((k, str(v))) for (k, v) in multi_fields.iteritems()]
        multi_match = {
            'query': query,
            'type': 'cross_fields',
            'operator': 'and',
            'fields': fields,
            'boost': 1,
        }
        q = {'multi_match':multi_match}
    else:
        q = {'match_all':{}}

    # 过滤器
    f = [{
        'range':{'created_time':{'gte':tzlc(datetime(2013,9,1))}} # 去除老数据
    }]

    for k, v in filters.iteritems():
        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=='flag':
            f.append({
                'term':{'flag':v}
            })
        elif k=='private_status':
            f.append({
                'term':{'private_status':v}
            })
        elif k=='is_online':
            f.append({
                'term':{'is_online':v}
            })
        elif k=='is_public':
            f.append({
                'term':{'is_public':v}
            })
        elif k=='topic_type':
            f.append({
                'term':{'topic_type':v}
            })
        elif k=='topic_score_user_id':
            f.append({
                'term':{'topic_score.user_id':v}
            })

    # 反向过滤器
    nf = []

    for k, v in nfilters.iteritems():
        if k=='private_status':
            nf.append({
                'term':{'private_status':v}
            })

    q = {
        'query': {'filtered': {
            'query': q,
        }}
    }
    if f or nf:
        q['query']['filtered']['filter'] = {
            'bool':{
                'must':f,
                'must_not':nf,
            }
        }

    # 排序
    if user_city_tag_id:
        q['sort'] = [
            {'_script':{
                'lang':settings.ES_SCRIPT_LANG,
                'script_file':'sort_topic-city',
                'type':'number',
                'params':{
                    'user_city_tag_id':user_city_tag_id,
                },
                'order':'desc',
            }}
        ]
    else:
        q['sort'] = []

    if sort:
        for s in sort:
            if s['key']=='doctor_num':
                q['sort'].append({
                    'doctor_num':{'order':s['order']}
                })
            elif s['key']=='last_modified':
                q['sort'].append({
                    'last_update_time':{'order':s['order']}
                })
            elif s['key']=='topic_score_score':
                q['sort'].append({
                    '_script':{
                        'lang':settings.ES_SCRIPT_LANG,
                        'script_file':'sort_topic-topic-score',
                        'type':'number',
                        'params':{
                            'topic_score_user_id':filters['topic_score_user_id'],
                        },
                        'order':s['order'],
                        '_cache':True,
                    }
                })

    es = get_es()
    index = es_index_adapt(
        index_prefix=settings.ES_INDEX_PREFIX,
        doc_type='problem',
        rw='read'
    )
    res = es.search(
        index=index,
        doc_type='problem',
        timeout=settings.ES_SEARCH_TIMEOUT,
        body=q,
        from_=offset,
        size=size)

    res = {
        'total_count':int(res['hits']['total']),
        'topic_ids':[int(topic['_id']) for topic in res['hits']['hits']],
    }
    return res


def search_topic(query='', offset=0, size=5, filters=None, nfilters=None, sort_type=PROBLEM_ORDER_TYPE.SEARCH_DEFAULT):
    """
    @param query: 搜索词
    @param offset: 偏移量
    @param size: 返回个数

    帖子搜索
    搜索域:[
        1.tag
        2.主帖内容
        ]
    默认排序:[
        精华
        匹配度
        热度(点赞数+回复数)
        最后更新时间(编辑/回复时间)
        ]
    """
    # 参数验证
    size = min(size, settings.COUNT_LIMIT)
    filters = filters or {}
    nfilters = nfilters or {}

    # 搜索关键字部分
    # 搜索域
    multi_fields = {
        'tags': 2,
        'title': 1,
        'content': 1,
    }
    fields = ['^'.join((k, str(v))) for (k, v) in multi_fields.items()]
    multi_match = {
        'query': query,
        'type': 'cross_fields',
        'operator': 'and',
        'fields': fields,
        'boost': 2,
    }

    q = {
        'bool': {
            'should': [
                {'multi_match': multi_match},
            ]
        }
    }

    # 5.3版 去掉搜索域: 帖子回复内容
    nested_fields = {}

    # 过滤器部分
    f = [  # 只返回上线且未被标记删除的帖子
        {'term': {'is_online': True}},
        {'term': {'flag': 'n'}},
    ]
    for k, v in filters.items():
        if k=='topic_type':
            f.append({
                'term':{'topic_type':v}
            })
        elif k == 'topic_types' and isinstance(v, list):
            f.append({
                'terms': {'topic_type': v}
            })
        elif k == 'pgc_category' and isinstance(v, (int, long)):
            f.append({
                'term': {'pgc_category': v}
            })
        elif k == 'is_pgc' and v==True:
            f.append({
                'exists':{'field':'pgc_category'}
            })

    nf = []
    for k, v in nfilters.items():
        if k=='user_id':
            nf.append({
                'term':{'user.id':v}
            })

    q = {
        'query': {'filtered': {
            'query': q,
            'filter': {'bool': {
                'must': f,
                'must_not': nf,
            }}
        }}
    }

    # 排序规则部分
    q['sort'] = [{'is_sink':{'order':'asc'}}]
    if sort_type == PROBLEM_ORDER_TYPE.PGC:
        q['sort'] += [
            '_score',
            {'last_update_time':{'order':'desc'}},
        ]
    elif sort_type == PROBLEM_ORDER_TYPE.SEARCH_DEFAULT:
        q['sort'] += [
            {'is_sink':{'order':'asc'}},
            {'is_elite':{'order':'desc'}},
            '_score',
            {'popularity': {'order': 'desc'}},
            {'last_update_time': {'order': 'desc'}},
        ]

    # 高亮部分
    q['highlight'] = get_highlight(multi_fields.keys() + nested_fields.keys())

    es = get_es()
    index = es_index_adapt(
        index_prefix=settings.ES_INDEX_PREFIX,
        doc_type='problem',
        rw='read'
    )
    res = es.search(
        index=index,
        doc_type='problem',
        timeout=settings.ES_SEARCH_TIMEOUT,
        body=q,
        from_=offset,
        size=size)

    '''
    {
      "hits":{
        "hits":[
          {
            "sort":[...], //排序用数值
            "_source":{...} //帖子文档，参见mapping/problem.json
            "highlight":{ //高亮字段
              "content":[...],
              "replys.content":[...]
            },
            "_id":"512820" //帖子id(请自行转数字)
          }
        ],
        "total":9, //结果总数
      },
    }
    '''
    res['topic_ids'] = [int(topic['_id']) for topic in res['hits']['hits']]
    res['total_count'] = res['hits']['total']

    return res

def process_filters(filters):
    # 过滤器部分
    f = [
        {'term': {'is_online': True}},
        {'term': {'flag':'n'}},
        {'term': {'private_status':PRIVATE_STATUS.NORMAL}},
    ]  # 只返回上线且未被标记删除的帖子

    for k, v in filters.iteritems():
        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=='is_elite' and v: # 此处不再使用selected_qa字段，改为过滤出标记"所长精选"or"热门推荐"tag的帖子
            f.append({
                'terms':{'closure_tag_ids':[
                    settings.ES_CONSTS['TAG_ID_DIRECTOR_RECOMMEND'],
                    settings.ES_CONSTS['TAG_ID_POPULAR_RECOMMEND'],
                ]}
            })
        elif k=='topic_type':
            f.append({
                'term':{'topic_type':v}
            })
        elif k=='topic_types' and isinstance(v, (list, tuple)):
            f.append({
                'terms':{'topic_type':v}
            })
        elif k=='province_tag_id':
            f.append({
                'term':{'user.city_province_tag_id':v}
            })
        elif k=='topic_vote_count_gte':
            f.append({
                'range':{'topic_vote_count':{
                    'gte':v
                }}
            })
        elif k=='is_topic':
            f.append({
                'term':{'is_topic':True}
            })
        elif k=='is_public':
            f.append({
                'term':{'is_public':True}
            })
        elif k == 'user_is_doctor':
            f.append({
                'term': {'user.is_doctor': v}
            })
        elif k == 'topic_types' and isinstance(v, list):
            f.append({
                'terms': {'topic_type': v}
            })
        elif k == 'has_video' and isinstance(v, bool):
            f.append({
                'term': {'has_video': v}
            })
        elif k == 'created_time':
            f.append({'range': {'created_time': {'gte': tzlc(v)}}})
    return f

def filter_topic(offset=0, size=5, user_city_tag_id=None, sort_type=PROBLEM_ORDER_TYPE.DEFAULT,
        filters={}, nfilters={}):
    # 参数验证
    size = min(size, settings.COUNT_LIMIT)
    if 'created_time' not in filters:
        filters['created_time'] = datetime(2013, 9, 1)

    f = process_filters(filters)

    # 反向过滤器
    nf = []

    for k, v in nfilters.iteritems():
        if k=='user_id':
            nf.append({
                'term':{'user.id':v}
            })

    sort_rule_list = []

    q = {
        'query': {'filtered': {
            'query': {'match_all':{}},
        }},
        'sort': sort_rule_list,
    }


    if f or nf:
        q['query']['filtered']['filter'] = {
            'bool':{
                'must':f,
                'must_not':nf,
            }
        }

    sort_rule_list.append(
        {'is_sink':{'order':'asc'}},
        #{'is_diary_sink_or_topic_sink': {'order': 'asc'}}
    )

    # 排序规则部分
    if sort_type == PROBLEM_ORDER_TYPE.DEFAULT:
        sort_rule_list += [
            {'last_update_time':{'order':'desc'}},
        ]
    elif sort_type == PROBLEM_ORDER_TYPE.CITY:
        sort_rule_list += [
            {'_script':{
                'lang':settings.ES_SCRIPT_LANG,
                'script_file':'sort_topic-city',
                'type':'number',
                'order':'desc',
                'params':{
                    'user_city_tag_id':user_city_tag_id or -1,
                }
            }},
            {'last_update_time':{'order':'desc'}},
        ]
    elif sort_type == PROBLEM_ORDER_TYPE.CHANNEL_HEADLINE:
        sort_rule_list += [
            {'channel_headline': {'order': 'desc'}},
            {'last_update_time':{'order':'desc'}},
        ]
    elif sort_type == PROBLEM_ORDER_TYPE.TO_BE_ANSWERED:
        sort_rule_list += [
            {'has_doctor_reply':{'order':'asc'}},
            {'created_time':{'order':'desc'}},
        ]
    elif sort_type == PROBLEM_ORDER_TYPE.LATEST_CREATED:
        sort_rule_list += [
            {'created_time':{'order':'desc'}},
        ]
    elif sort_type == PROBLEM_ORDER_TYPE.HAS_IMAGE:
        sort_rule_list += [
            {'has_image':{'order':'desc'}},
            {'created_time':{'order':'desc'}},
        ]
    elif sort_type == PROBLEM_ORDER_TYPE.RANKING_POPULARITY:
        sort_rule_list += [
            {'ranking_popularity':{'order':'desc'}}
        ]
    elif sort_type == PROBLEM_ORDER_TYPE.ZONE_SUGGEST:
        sort_rule_list += [
            {'replys_num': {'order': 'desc'}},
            {'created_time': {'order': 'desc'}},
        ]

    es = get_es()
    index = es_index_adapt(
        index_prefix=settings.ES_INDEX_PREFIX,
        doc_type='problem',
        rw='read'
    )
    res = es.search(
        index=index,
        doc_type='problem',
        timeout=settings.ES_SEARCH_TIMEOUT,
        body=q,
        from_=offset,
        size=size)

    res = {
        'topic_ids':[int(topic['_id']) for topic in res['hits']['hits']]
    }
    return res
