# coding=utf8

from api.models.message import Conversation

from django.conf import settings
from .common import limited_size
from gm_types.msg import CONVERSATION_ORDER, CONVERSATION_TYPE


def doctor_search_conversation(offset=0, size=50, filters={}, query={}, sort_type=CONVERSATION_ORDER.UNREAD):
    res = search_conversation_es_compatable(offset, size, filters, query, sort_type)
    return res


def search_conversation_db(offset=0, size=50, filters={}, query={}, sort_type=None):
    # TODO: 整体迁移至搜索引擎
    conversations = Conversation.objects.all()

    for k, v in filters.iteritems():
        if k == 'user_id':
            user_id = v
            conversations = conversations.exclude(is_empty=True) \
                .filter(user_status_set__user_id=user_id)

    for k, v in query.iteritems():
        if k == 'content':
            if v:
                conversations = conversations.filter(message__content__contains=v)
        elif k == 'user_last_name':
            if v:
                conversations = conversations.filter(user__last_name__contains=v)

    conversations = conversations.order_by('user_status_set__status', '-last_reply_time')
    total_count = conversations.count()
    conversations = conversations[offset:offset + size]

    # only return a object manager to search view
    return {
        'total_count': total_count,
        'conversations': conversations,
    }


def search_conversation_es_compatable(offset=0, size=50, filters={}, query={}, sort_type=CONVERSATION_ORDER.UNREAD):
    res = search_conversation_es(offset, size, filters, query, sort_type)
    conversation_ids = [int(s['_id']) for s in res['hits']['hits']]
    total_count = res['hits']['total']

    conversation_map = {
        conversation.id: conversation
        for conversation in Conversation.objects.filter(pk__in=conversation_ids)
    }
    conversation_list = [conversation_map[x] for x in conversation_ids if x in conversation_map]

    return {
        'total_count': total_count,
        'conversations': conversation_list
    }


def search_conversation_from_es(offset=0, size=50, filters={}, query={}, sort_type=CONVERSATION_ORDER.LAST_REPLY_TIME):
    res = search_conversation_es(offset, size, filters, query, sort_type)
    conversation_ids = [int(s['_id']) for s in res['hits']['hits']]
    total_count = res['hits']['total']
    return {
        'total_count': total_count,
        'conversation_ids': conversation_ids,
    }


def search_conversation_es(offset=0, size=50, filters={}, query={}, sort_type=CONVERSATION_ORDER.LAST_REPLY_TIME):
    size = limited_size(size)

    filter_element_list = []
    query_element_list = []

    for k, v in filters.items():
        if k == 'user_ids':
            filter_element_list.append({
                'nested': {
                    'path': 'users',
                    'query': {
                        'terms': {'users.id': v}
                    }
                }
            })
        elif k == 'multi_filter':
            filter_element_list.append({
                'nested': {
                    'path': 'users',
                    'query': {
                        'bool': {
                            'must': [
                                {'match': {'users.is_unread': v['is_unread']}},
                                {'terms': {'users.id': v['user_ids']}}
                            ]
                        }
                    }
                }
            })
        elif k ==  'multi_filter_status':
            filter_element_list.append({
                'nested': {
                    'path': 'users',
                    'query': {
                        'bool': {
                            'must': [
                                {'match': {'users.status': v['status']}},
                                {'terms': {'users.id': v['user_ids']}}
                            ]
                        }
                    }
                }
            })
        elif k == 'conversation_type':
            v = int(v)
            local_filters = []
            local_filters.append({
                'term': {'conversation_type': v}
            })
            if v == CONVERSATION_TYPE.MESSAGE:
                local_filters.append({
                    'bool': {
                        'must_not': {
                            'exists': {'field': 'conversation_type'}
                        }
                    }
                })
            filter_element_list.append({
                'bool': {
                    'should': local_filters
                }
            })
        elif k == 'is_star':
            filter_element_list.append({
                'bool': {
                    'must': {
                        'term': {'is_star_by_doctor': v}
                    }
                }
            })
        elif k == 'last_reply_time_start_gte':
            filter_element_list.append({
                'bool': {
                    'must': {
                        'range': {'last_reply_time': {
                            "gte": v
                        }
                        }
                    }
                }
            })
        elif k == 'last_reply_time_end_lte':
            filter_element_list.append({
                'bool': {
                    'must': {
                        'range': {'last_reply_time': {
                            "lte": v
                        }
                        }
                    }
                }
            })
        elif k == 'status':
            filter_element_list.append({
                'bool': {
                    'must': {
                        'term': {'status': v}
                    }
                }
            })

    for k, v in query.items():
        if k == 'content' and v:
            query_element_list.append({
                'nested': {
                    'path': 'messages',
                    'score_mode': 'max',
                    'query': {
                        'match_phrase': {'messages.content.text': v}
                    }
                }
            })
        if k == 'comment' and v:
            query_element_list.append({
                'nested': {
                    'path': 'users',
                    'score_mode': 'max',
                    'query': {
                        'match_phrase': {'users.comment': v}
                    }
                }
            })

        if k == 'user_last_name' and v:
            query_element_list.append({
                'nested': {
                    'path': 'users',
                    'score_mode': 'max',
                    'query': {
                        'match_phrase': {'users.last_name': v}
                    }
                }
            })
        if k == 'user_id' and v:
            query_element_list.append({
                'nested': {
                    'path': 'users',
                    'score_mode': 'max',
                    'query': {
                        'match_phrase': {'users.id': v}
                    }
                }
            })

    es_query = {
        'query': {
            'filtered': {
                'filter': {
                    'bool': {
                        'must': filter_element_list,
                    },
                },
                'query': {
                    'bool': {
                        'should': query_element_list,
                    }
                }
            },
        },
    }

    if sort_type == CONVERSATION_ORDER.UNREAD:
        es_query['sort'] = [
            {'_script': {
                'lang': settings.ES_SCRIPT_LANG,
                'script_file': 'sort_conversation-default',
                'type': 'number',
                'params': {
                    'context_user_id': filters['user_id'] if 'user_id' in filters else -1,
                },
                'order': 'desc',
            }},
            {'last_reply_time': {'order': 'desc'}},
        ]
    elif sort_type == CONVERSATION_ORDER.LAST_REPLY_TIME:
        es_query['sort'] = [
            {'last_reply_time': {'order': 'desc'}},
        ]

    from message.utils.es_abstract import get_esop
    from message.utils.es_abstract import table_conversation
    res = get_esop().search(
        table=table_conversation,
        timeout=settings.ES_SEARCH_TIMEOUT,
        body=es_query,
        from_=offset,
        size=size,
    )

    return res


def filter_conversation_es(offset=0, size=50, filters={}, sort_type=None):
    filter_element_list = []
    sort_element_list = []
    size = limited_size(size)

    for k, v in filters.items():
        if k == 'user_id':
            filter_element_list.append({
                'nested': {
                    'path': 'users',
                    'query': {
                        'term': {'users.id': v}
                    }
                }
            })

    es_query = {
        'query': {
            'filtered': {
                'query': {'match_all': {}},
                'filter': {'bool': {'must': filter_element_list}}
            }
        },
        'sort': sort_element_list,
    }

    from message.utils.es_abstract import get_esop
    from message.utils.es_abstract import table_conversation
    res = get_esop().search(
        table=table_conversation,
        timeout=settings.ES_SEARCH_TIMEOUT,
        body=es_query,
        from_=offset,
        size=size,
    )

    converted = {
        'conversation_ids': [int(s['_id']) for s in res['hits']['hits']],
        'total_count': res['hits']['total'],
    }

    return converted
