# coding=utf-8
from __future__ import absolute_import, unicode_literals

import elasticsearch

from api.models.types import MESSAGE_TYPE
from gm_types.msg import CONVERSATION_TYPE, MessageTraceEventType
from message.utils.es_abstract import get_esop, table_conversation, table_message, get_migrate_esop
from rpc.tool.log_tool import logging_exception, conversation_logger
from rpc.tool.log_tool import log_message_trace
from .conversation import get_conversation_add_one_message_bulk_action
from gm_types.msg import CONVERSATION_TYPE
from .es import tzlc, detzlc


def write_msg_to_es(msg_id, user_id, conversation_id, send_time, msg, conversation_extra):
    """
    :description 消息存储至es
    :param msg_id:
    :param user_id:
    :param conversation_id:
    :param send_time:
    :param msg:
    :param conversation_extra: 会话附加信息
    :return:
    """
    msg_es = msg2es(msg_id, user_id, conversation_id, send_time, msg)

    conversation_head = conversation_extra
    conversation_head['id'] = conversation_id

    try:
        from message.utils.es_abstract import get_esop
        from message.utils.es_abstract import table_message
        get_esop().index(
            table=table_message,
            id=msg_id,
            body=msg_es
        )
        get_esop().bulk_single(
            get_conversation_add_one_message_bulk_action(
                msg_es,
                conversation_head=conversation_head,
            )
        )
        log_message_trace(MessageTraceEventType.TRACE_GAIA_WRITE_TO_ES, {"succ": True})
        return {
            'succ': True,
        }
    except elasticsearch.TransportError as e:
        logging_exception()
        conversation_logger.warning(
            "save msg to es error. msg[%s] status_code[%s] es_error[%s] es_info[%s]",
            unicode(msg),
            unicode(e.status_code),
            unicode(e.error),
            unicode(e.info)
        )
        log_message_trace(MessageTraceEventType.TRACE_GAIA_WRITE_TO_ES, {"succ": False, "error": e.error, "info": e.info})
        return {
            'succ': False,
        }


def message_info(msg_es):
    try:
        res = {
            'id': msg_es['id'],
            'user_id': msg_es['send_user']['id'],
            'conversation_id': msg_es['conversation_id'],
            'send_time': detzlc(msg_es['send_time']),
            'type': msg_es['type'],
            'content': msg_es['content'],
        }
        return res
    except KeyError:  # invalid data
        return None


def build_conversation_extra(**kwargs):
    result = {}
    for k, v in kwargs.items():
        if k == 'conversation_type':
            result[k] = v
    return result


def read_conversation_extra_from_es(conversation_ids=()):
    def _extract(conversation_info):
        if 'conversation_type' not in conversation_info:
            conversation_info['conversation_type'] = CONVERSATION_TYPE.MESSAGE
        return conversation_info

    if not conversation_ids:
        return []

    try:
        conversations = get_esop().mget(
            table=table_conversation,
            body={'ids': [str(conversation_id) for conversation_id in conversation_ids]},
            _source=['id', 'conversation_type', 'is_star_by_doctor'],
        )
        conversations = conversations['docs']
    except elasticsearch.TransportError as e:
        logging_exception()
        conversation_logger.warning(
            "mget conversations from es error. conversation_ids[%s] status_code[%s] es_error[%s] es_info[%s]",
            unicode(conversation_ids),
            unicode(e.status_code),
            unicode(e.error),
            unicode(e.info)
        )
        conversations = []

    results = {}
    for c in conversations:
        if not c['found']:
            continue
        c = _extract(c['_source'])
        results[c['id']] = c
    return results


def read_msg_from_es(msg_ids=()):
    if not msg_ids:
        return []

    try:
        msgs = get_esop().mget(
            table=table_message,
            body={'ids': [str(msg_id) for msg_id in msg_ids]}
        )
        msgs = msgs['docs']
    except elasticsearch.TransportError as e:
        logging_exception()
        conversation_logger.warning(
            "mget msgs from es error. msg_ids[%s] status_code[%s] es_error[%s] es_info[%s]",
            unicode(msg_ids),
            unicode(e.status_code),
            unicode(e.error),
            unicode(e.info)
        )
        msgs = []

    results = [message_info(m['_source']) for m in msgs if m['found']]
    results = [m for m in results if m is not None]
    return results


def msg2es(msg_id, user_id, conversation_id, send_time, msg):
    msg_es = {
        'id': msg_id,
        'send_user': {
            'id': user_id,
        },
        'conversation_id': conversation_id,
        'send_time': tzlc(send_time),
    }

    if msg['type']:
        msg_es['type'] = msg['type']
        if msg['type'] == MESSAGE_TYPE.TEXT:
            msg_es['content'] = {
                'text': msg['content']['text']
            }
        elif msg['type'] == MESSAGE_TYPE.AUDIO:
            msg_es['content'] = {
                'audio': msg['content']['audio']
            }
        elif msg['type'] == MESSAGE_TYPE.IMAGE:
            msg_es['content'] = {
                'image': msg['content']['image']
            }
        else:
            msg_es['content'] = msg['content']

    else:
        msg_es['type'] = MESSAGE_TYPE.TEXT
        msg_es['content'] = {
            'text': msg['content']
        }

    return msg_es
