#!/usr/bin/env python
# coding=utf-8

from __future__ import unicode_literals, absolute_import

from gm_types.doctor import DOCTOR_MESSAGE_TYPE, DOCTOR_ORDER_MESSAGE_TYPE
from gm_types.trade import STATEMENT_OPERATION_TYPE

from api.models import ServiceRegister
from hippo.models import Doctor
from pay.models import StatementAll, ServiceSnapshot
from pay.models import StatementAllOperation
from rpc.decorators import bind_context, bind
from ..models.doctormessage import DoctorMessage, OrderMessage
from api.models.order import Order, RefundOrder
from ..utils import get_merchant


def add_order_message(type, info_ids):
    """
    :param type: 取自gm_types.doctor DOCTOR_ORDER_MESSAGE_TYPE，0为订单、1为退款单
    :param info_id: 订单 or 退款单的ID
    :return:
    """

    if type == DOCTOR_ORDER_MESSAGE_TYPE.ORDER:
        iid2did = {o[0]: o[1] for o in Order.objects.filter(
            id__in=info_ids).values_list('id', 'service__doctor_id')}
    else:
        iid2did = {o[0]: o[1] for o in RefundOrder.objects.filter(
            id__in=info_ids).values_list('id', 'order__service__doctor_id')}

    dids = set(iid2did.values())

    did2mid = {}
    for did in dids:
        merchant = get_merchant(did)
        if merchant:
            did2mid[did] = merchant.id

    to_insert_message = []

    for iid in info_ids:
        if iid in iid2did:
            did = iid2did[iid]
            m = OrderMessage(type=type, info_id=iid, doctor_id=did)
            if did and did in did2mid:
                m.merchant_id = did2mid[did]
            to_insert_message.append(m)

    OrderMessage.objects.bulk_create(to_insert_message)
    for item in to_insert_message:
        try:
            from services.notify import notify
            notify('deal/add', doctor_id=item.doctor.id, data={})
        except:
            continue


@bind_context('doctor/message/system', login_required=True)
def get_message_system(ctx, doctor_id, start_num=0, count=10):
    """
    系统消息列表（除公告和协议）
    :param ctx:
    :param doctor_id:
    :param start_num:
    :param count:
    :return:
    """
    messages = DoctorMessage.objects.filter(doctor_id=doctor_id).order_by('-created_time')
    message_list = list()
    for message in messages[start_num: start_num + count]:
        message_data = {
            'id': message.id,
            'content': message.content,
            'type': message.type,
            'time': message.created_time.strftime('%Y-%m-%d %H:%M:%S'),
            'info_id': message.info_id,
            'is_read': message.is_read,
            'can_view': True
        }
        message_list.append(message_data)

    data = {
        'total': messages.count(),
        'message_list': message_list
    }
    return data


@bind_context('doctor/message/not_read', login_required=True)
def get_message_no_read(ctx, doctor_id, start_num=0, count=10):
    """
    未读消息列表（除协议）
    :param ctx:
    :param doctor_id:
    :param start_num:
    :param count:
    :return:
    """

    messages = DoctorMessage.objects.filter(doctor_id=doctor_id, is_read=False) \
        .order_by('-created_time')
    message_list = list()
    for message in messages[start_num: start_num + count]:
        message_data = {
            'id': message.id,
            'content': message.content,
            'type': message.type,
            'time': message.created_time.strftime('%Y-%m-%d %H:%M:%S'),
            'info_id': message.info_id,
            'can_view': True
        }
        message_list.append(message_data)

    data = {
        'total': messages.count(),
        'message_list': message_list
    }
    return data


@bind_context('doctor/message/index', login_required=True)
def get_message_index(ctx, doctor_id):
    """
    首页未读消息列表（除公告和协议）
    :param ctx:
    :param doctor_id:
    :return:
    """
    messages = DoctorMessage.objects.filter(doctor_id=doctor_id, is_read=False) \
        .order_by('-created_time')
    message_list = list()
    for message in messages[0: 3]:
        message_data = {
            'id': message.id,
            'content': message.content,
            'type': message.type,
            'time': message.created_time.strftime('%Y-%m-%d %H:%M:%S'),
            'info_id': message.info_id,
            'can_view': True
        }
        message_list.append(message_data)

    data = {
        'total': messages.count(),
        'message_list': message_list
    }
    return data


@bind_context('doctor/message/read', login_required=True)
def record_message_is_read(ctx, message_id):
    """
    消息已读调用
    :param ctx:
    :param message_id:
    :return:
    """
    try:
        message = DoctorMessage.objects.get(id=message_id)
        message.is_read = True
        message.save(update_fields=['is_read'])
        return message.id
    except DoctorMessage.DoesNotExist:
        return 0


@bind_context('doctor/message/order_refund', login_required=True)
def get_order_refund_message(ctx, doctor_id):
    order_messages = OrderMessage.objects.filter(
        doctor_id=doctor_id, is_push=False
    ).order_by('-created_time')
    message_list = list()

    order_messages_count = 0
    order_message_ids = []
    for order_message in order_messages:
        if order_message.type == DOCTOR_ORDER_MESSAGE_TYPE.ORDER:
            order_id = order_message.info_id
        else:
            order_id = RefundOrder.objects.get(id=order_message.info_id).order_id

        title = ServiceSnapshot.objects.filter(order_id=order_id).values_list('name', flat=True)[0]

        data = {
            'info_id': order_message.info_id,
            'title': title,
            'type': order_message.type
        }
        message_list.append(data)

    for message in order_messages:
        message.is_push = True
        message.save()
    result = {
        'total': order_messages_count,
        'info_list': message_list,
    }

    return result


@bind_context('doctor/message/add_message')
def add_message(ctx, info, message_info):
    merchant = get_merchant(info['doctor_id'])
    if merchant:
        info['merchant_id'] = merchant.id
    DoctorMessage.add_message(info, *message_info)


@bind_context('doctor/message/audit_statement')
def audit_statement_message(ctx, statement_ids):
    """
    对账单通过发消息
    :param ctx:
    :param statement_ids:
    :return:
    """
    statements = StatementAll.objects.filter(id__in=statement_ids)
    for statement in statements:
        merchant = get_merchant(statement.doctor.id)
        info = {
            'type': DOCTOR_MESSAGE_TYPE.STATEMENT_CONFIRM,
            'info_id': statement.id,
            'doctor_id': statement.doctor.id,
        }
        if merchant:
            info['merchant_id'] = merchant.id
        message_info = str(statement.statement_date)[4:]
        DoctorMessage.add_message(info, message_info)


@bind_context('doctor/message/settle_statement')
def settle_statement_message(ctx, statement_id):
    """
    对账单结算发消息
    :param statement_id:
    :param ctx:
    :return:
    """
    statement = StatementAll.objects.get(id=statement_id)
    merchant = get_merchant(statement.doctor.id)
    info = {
        'type': DOCTOR_MESSAGE_TYPE.STATEMENT_SETTLE,
        'info_id': statement.id,
        'doctor_id': statement.doctor.id,
    }
    if merchant:
        info['merchant_id'] = merchant.id
    message_info = str(statement.statement_date)[4:]
    DoctorMessage.add_message(info, message_info)


@bind_context('doctor/message/statement_fail')
def fail_statement_message(ctx, statement_id):
    """
    对账单打款失败发消息
    :param statement_id:
    :param ctx:
    :return:
    """
    statement = StatementAll.objects.get(id=statement_id)
    merchant = get_merchant(statement.doctor.id)
    info = {
        'type': DOCTOR_MESSAGE_TYPE.STATEMENT_FAIL,
        'info_id': statement.id,
        'doctor_id': statement.doctor.id,
    }
    if merchant:
        info['merchant_id'] = merchant.id
    message_info = str(statement.statement_date)[4:]
    record = StatementAllOperation.objects.filter(statementall_id=statement_id,
                                                  optype__in=[STATEMENT_OPERATION_TYPE.BANK_DEFEAT,
                                                              STATEMENT_OPERATION_TYPE.NAME_DEFEAT]
                                                  ).order_by('id').last()
    DoctorMessage.add_message(info, message_info, STATEMENT_OPERATION_TYPE.getDesc(record.optype))


@bind_context('doctor/message/service_review')
def service_review(ctx, serviceregister_id, is_pass, reason=None):
    """
    美购审核审核提醒
    :param serviceregister_id:
    :param is_pass:
    :param ctx:
    :return:
    """
    serviceregister = ServiceRegister.objects.get(id=serviceregister_id)
    merchant = get_merchant(serviceregister.doctor.id)
    info = {
        'type': DOCTOR_MESSAGE_TYPE.SERVICE_ONLINE if is_pass else DOCTOR_MESSAGE_TYPE.SERVICE_REFUSE,
        'info_id': serviceregister.id,
        'doctor_id': serviceregister.doctor.id,
    }
    if merchant:
        info['merchant_id'] = merchant.id
    message_info = serviceregister.name
    if is_pass:
        DoctorMessage.add_message(info, message_info)
    else:
        DoctorMessage.add_message(info, message_info, reason)


@bind_context('doctor/message/service_offline')
def service_offline(ctx, serviceregister_id, is_pass, reason=None):
    """
    美购审核审核提醒
    :param serviceregister_id:
    :param is_pass:
    :param ctx:
    :return:
    """
    serviceregister = ServiceRegister.objects.get(id=serviceregister_id)
    merchant = get_merchant(serviceregister.doctor.id)
    info = {
        'type': DOCTOR_MESSAGE_TYPE.SERVICE_OFFLINE if is_pass else DOCTOR_MESSAGE_TYPE.SERVICE_OFFLINE_REFUSE,
        'info_id': serviceregister.id,
        'doctor_id': serviceregister.doctor.id,
    }
    if merchant:
        info['merchant_id'] = merchant.id
    message_info = serviceregister.name
    if is_pass:
        DoctorMessage.add_message(info, message_info)
    else:
        DoctorMessage.add_message(info, message_info, reason)


@bind_context('doctor/message/doctor_edit')
def doctor_edit(ctx, doctor_id, is_pass, reason=None):
    """
    医生资料审核提醒
    :param reason:
    :param is_pass:
    :param ctx:
    :param doctor_id:
    :return:
    """
    doctor = Doctor.objects.get(id=doctor_id)
    merchant = get_merchant(doctor_id)
    info = {
        'type': DOCTOR_MESSAGE_TYPE.DOCTOR_EXAMINE_PASS if is_pass else DOCTOR_MESSAGE_TYPE.DOCTOR_EXAMINE_REJECT,
        'info_id': doctor.id,
        'doctor_id': doctor.id,
    }
    if merchant:
        info['merchant_id'] = merchant.id
        info['doctor_id'] = merchant.doctor.id

    message_info = doctor.name
    if is_pass:
        DoctorMessage.add_message(info, message_info)
    else:
        DoctorMessage.add_message(info,message_info,reason)