# coding=utf-8
from celery import shared_task
from django.conf import settings
from gm_jmessage import common

from gm_types.gaia import MESSAGE_TYPE
from gm_types.msg import CONVERSATION_TYPE
from gm_upload.utils.image_utils import Picture
from urlparse import urljoin
from wechat_sdk.wx import WechatPubAPI

from api.models import User, Message, Conversation, get_doctor_by_user_id, ConversationUserStatus
from hippo.tool.chain_hospital_tools import get_master_merchant
from hippo.utils import get_merchant
from message import JIM_USER_NOT_FOUND
from message.utils.common import get_jim_login_info, register_jim
from message.utils.push_service import UserPushService, DoctorPushService
from rpc.cache import wechatpub_cache
from rpc.tool.log_tool import info_logger, conversation_logger
from services.unread.noti_unread import noti_poll

@shared_task
def send_wechatpub_message(target_user_id, msg_type, content):
    wechat_api = WechatPubAPI(settings.WECHATPUB_APPID, settings.WECHATPUB_APPSECRET)

    at = wechatpub_cache.get('access_token')
    if not at:
        # get wx access token
        at_json = wechat_api.get_access_token()
        at = at_json['access_token']
        expires_in = at_json['expires_in'] - 120
        wechatpub_cache.setex('access_token', expires_in, at)

    user = User.objects.get(id=target_user_id)
    wechat_openid = user.username[6:]  # get openid

    if msg_type == MESSAGE_TYPE.TEXT:
        error_code = wechat_api.send_kefu_text_msg(at, wechat_openid, content['text'])
        info_logger.info(
            u'send to wechatpub: status: %s, openid: %s, content: %s',
            error_code, wechat_openid, content['text']
        )

    elif msg_type == MESSAGE_TYPE.SERVICE:
        service_id = content['service_id']
        link = urljoin(settings.M_HOST, '/promotion/%s/' % service_id)
        error_code = wechat_api.send_kefu_text_msg(at, wechat_openid, u'美购: %s' % link)
        info_logger.info(
            u'send to wechatpub: status: %s, openid: %s, content: %s',
            error_code, wechat_openid, link
        )

    elif msg_type == MESSAGE_TYPE.IMAGE:
        link = content['image']
        link = Picture.get_full_path(link, '-w')
        error_code = wechat_api.send_kefu_text_msg(at, wechat_openid, u'图片: %s' % link)
        info_logger.info(
            u'send to wechatpub: status: %s, openid: %s, content: %s',
            error_code, wechat_openid, link
        )

    elif msg_type == MESSAGE_TYPE.DIARY:
        link = urljoin(settings.M_HOST, '/diary_book/%s/' % content['diary_id'])
        error_code = wechat_api.send_kefu_text_msg(at, wechat_openid, u'案例: %s' % link)
        info_logger.info(
            u'send to wechatpub: status: %s, openid: %s, content: %s',
            error_code, wechat_openid, link
        )


@shared_task
def send_jim_message(receiver_uid, extras, msg_type='text', text=''):
    """Send message to jim server.
    reference doc:
        https://docs.jiguang.cn/jmessage/server/rest_api_im/#_17
    """
    from rpc.tool.log_tool import info_logger
    info_logger.info({"send_jim_message": True, "receiver_uid": receiver_uid})
    # currenttly, msg_type just supports text
    assert msg_type in ('text',)
    username, password = get_jim_login_info(receiver_uid)
    jmessage = common.JMessage(settings.JIM_APPKEY, settings.JIM_SECRET)
    jmsg_obj = jmessage.create_messages()

    msg = jmsg_obj.build_message(1, 'single', 'admin', msg_type,
                                 username, settings.JIM_ADMIN, text, extras=extras)

    msg['no_notification'] = True
    # 如果序列化不成功， 大部分情况是极光服务器出了问题
    body = jmsg_obj.send_messages(msg).json()

    # handle with user not exist case.
    if 'error' in body and body['error']['code'] == JIM_USER_NOT_FOUND:
        register_jim(username, password)
        # try send message again, we retry only once.
        body = jmsg_obj.send_messages(msg).json()

    return body


@shared_task
def change_message_is_read_status_and_notify(msg_ids, read_user_id):
    """修改对应message的已读状态， 并且通知对应用户
    对于医生web版 通过poll服务推送消息
    对于用户版 通过JPush Message进行推送消息
    其余的暂时不支持
    :param msg_ids List: 已读消息ID
    :param read_user_id:
    :return:
    """
    # 每次的msg_id 要属于同一个conversation_id, 并且发送人不是自己
    messages = Message.objects.filter(id__in=msg_ids)
    conversation_ids = list(set([item.conversation_id for item in messages]))
    user_ids = [item.user_id for item in messages]
    if len(conversation_ids) != 1:
        conversation_logger.info('MessageRead: msg_ids: {} not the same conversation'.format(msg_ids))
        return
    if read_user_id in user_ids:
        conversation_logger.info('MessageRead: read_user_id: {} is the sender of the message, message_send_user_ids: {}'.
                                 format(read_user_id, user_ids))
        return

    conversation_id = conversation_ids[0]
    conversation_object = Conversation.objects.filter(id=conversation_id).first()
    if not conversation_object:
        conversation_logger.info('MessageRead: conversation_id: {} not exist'.format(conversation_id))
        return

    # 如果不是自己的对话 也不能设置
    conversation__user_ids = conversation_object.user_ids()
    if read_user_id not in conversation__user_ids:
        conversation_logger.info('MessageRead: read_user_id: {} does not belong in this conversation_id: {}'.
                                 format(read_user_id, conversation_id))
        return

    # 更新部分
    need_update_msg_ids = [item.id for item in messages if item.is_read is False]
    if not need_update_msg_ids:
        conversation_logger.info('MessageRead: No read messages need to be updated')
        return
    update_rows = Message.objects.filter(id__in=need_update_msg_ids).update(is_read=True)
    assert update_rows > 0

    # 发送通知部分
    target_user_id = list(set(conversation__user_ids) - set([read_user_id]))[0]
    doctor = get_doctor_by_user_id(target_user_id)

    user_key = '_'.join(map(str, sorted(conversation__user_ids)))
    push_data = {'msg_ids': msg_ids, 'user_key': user_key}

    if doctor:
        noti_poll(doctor.id, 'message', 'read', push_data)

    from message.utils.push_service import UserPushService
    UserPushService.send_msg_read_message_push(user_ids=[target_user_id], data=push_data)
    conversation_logger.info('MessageRead: msg_ids: {} update read status successful'.format(need_update_msg_ids))

@shared_task
def update_conversation_refer(user_id, conversation_id, from_user_refer=None, business_id=None):
    """

    :param from_user_refer:
    :param business_id:
    :return:
    """
    # update refer
    # TODO: 如果来源是美购详情页的话， 要判断当前business_id 是否属于该医生， 不然就会错乱, 没时间改， 留给后人了
    cus = ConversationUserStatus.objects.filter(conversation_id=conversation_id, user_id=user_id).first()
    if not cus:
        return
    if cus.refer != from_user_refer or cus.business_id != business_id:
        cus.refer = from_user_refer
        cus.business_id = business_id
        cus.save(update_fields=['refer', 'business_id'])


@shared_task
def send_new_message_push(target_user_id, msg_id, alert, silent):
    # 如果message_id 不存在 就报错， 或者打点记录
    message = Message.objects.get(id=msg_id)
    UserPushService.send_new_msg_push(user_ids=[target_user_id], alert=alert, data=message, silent=silent)

    # 医生推送 Jpush 医生版暂时还没有接入极光JMessage(JIM)
    recv_doctor = get_doctor_by_user_id(target_user_id)
    if recv_doctor:
        doctor_uids = [target_user_id]
        # 给多个用户发私信
        merchant_doctor = get_merchant(recv_doctor.id)
        master_merchant = None
        if merchant_doctor:
            master_merchant = get_master_merchant(merchant_doctor.id)
        if merchant_doctor and recv_doctor != merchant_doctor.doctor:
            doctor_uids.append(merchant_doctor.doctor.user.id)
        if master_merchant and master_merchant.doctor not in [recv_doctor, merchant_doctor.doctor]:
            doctor_uids.append(master_merchant.doctor.user.id)
        DoctorPushService.send_new_msg_push(user_ids=doctor_uids, alert=alert, data=message)


@shared_task
def auto_reply_message(conversation_id, target_user_id, send_user_id):
    """ 目前支持用户首次发送消息给医生时，自动回复消息

    相关链接: http://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=28921473
    """
    from rpc.tool.log_tool import info_logger
    info_logger.info({"auto_reply_message": conversation_id, "target_user_id": target_user_id, "send_user_id": send_user_id})
    from message.views.message import internal_message_send
    from message.utils.message import get_last_send_time
    if not get_last_send_time(target_user_id, send_user_id):
        res = internal_message_send(
            sender_user_id=target_user_id,
            target_user_id=send_user_id,
            conversation_type=CONVERSATION_TYPE.MESSAGE,
            msg_type=MESSAGE_TYPE.TEXT,
            content=settings.AUTO_REPLY_MESSAGE,
            push_stat_labels={'event_type': 'push', 'event': 'received_private_msg'},
            is_system=True,
        )