
# coding=utf-8
from datetime import datetime, timedelta
from django.conf import settings
from celery import shared_task
from gm_types.error import ERROR
from gm_types.gaia import DOCTOR_TYPE
from gm_types.msg import CONVERSATION_TYPE
from gm_types.merchant.sales_lead import USER_ACTION_TYPE
from gm_types.whisper import MESSAGE_SOURCE

from rpc.context import ContextManager
from rpc.tool.log_tool import info_logger
from api.models.types import MESSAGE_TYPE
from api.models import MessageBlackUser
from api.bridge import internal_message_send
from api.models import MerchantRelevance, Doctor, Merchant, Hospital
from rpc.tool.log_tool import logging_exception, info_logger
from helios.rpc.internal.default_invoker import create_default_invoker


def get_merchant_by_doctor_id(doctor_id):
    """ 根据医生ID获取对应的商户ID """

    merchant = Merchant.objects.filter(doctor_id=doctor_id).first()

    if merchant:
        return merchant.id

    try:
        doctor = Doctor.objects.filter(id=doctor_id).first()
        if not doctor:
            return None

        merchant_id = get_merchant_by_hospitla_id(doctor.hospital_id)

        if merchant_id:
            return merchant_id
    except Exception as e:
        logging_exception()
        raise


def get_merchant_by_user_id(user_id):
    """ 根据用户ID获取对应医生 对应的商户ID """

    doctor = Doctor.objects.filter(user_id=user_id).first()

    if not doctor:
        return None

    merchant = Merchant.objects.filter(doctor_id=doctor.id).first()

    if merchant:
        return merchant.id

    merchant_id = get_merchant_by_hospitla_id(doctor.hospital_id)
    return merchant_id


def get_merchant_by_hospitla_id(hospital_id):
    """ 根据 机构ID 获取对应的商户ID """

    try:
        hospital = Hospital.objects.get(id=hospital_id)
        if not hospital:
            return None

        doctor = hospital.doctor_hospital.get(doctor_type=DOCTOR_TYPE.OFFICER)
        if not doctor:
            return None

        merchant = Merchant.objects.filter(doctor_id=doctor.id).first()

        if merchant:
            return merchant.id
    except Exception as e:
        logging_exception()
        raise

    return None



def try_get_device_id():
    """ 尝试从 Context 中获取 cl_id. """
    context = ContextManager.get_active_context()

    if context:
        client_info = context._request.client_info

        device_id = client_info.get("cl_id", "")
        return device_id
    return ""


def send_message_triggle_lead(send_user_id, target_user_id=None, user_ids=[]):
    """ 发送私信触发 线索任务, 尝试从 Context 获取 cl_id """
    try:
        if not target_user_id and len(user_ids) != 2:
            info_logger.info("send_message_triggle_lead error, bad params: {0}, {1}".format(target_user_id, user_ids))

        if not target_user_id:
            user_id_1, user_id_2 = [int(uid) for uid in user_ids]
            target_user_id = user_id_2 if user_id_1 == send_user_id else user_id_1

        device_id = try_get_device_id()
        info_logger.info("send_message_triggle_lead_task called, {0}, {1} ".format(send_user_id, target_user_id))
        send_message_triggle_lead_task.delay(send_user_id, target_user_id, device_id=device_id)
    except Exception as err:
        logging_exception()
        info_logger.info("send_message_triggle_lead error, exception: {}".format(err))


@shared_task
def send_message_triggle_lead_task(send_user_id, target_user_id, device_id=""):
    """ 发送私信触发 线索任务
    找到对应的接收用户 merchant_id， 然后尝试触发
    """

    merchant_id = get_merchant_by_user_id(target_user_id)

    info_logger.info("send_message_triggle_lead_task:send: {0}, target: {1}, merchant_id: {2}".format(
        send_user_id, target_user_id, merchant_id
    ))

    if not merchant_id:
        return

    try:
        rpc_invoker = create_default_invoker(debug=settings.DEBUG)
        reps = rpc_invoker["gm_merchant/sales_lead/action_triggle"](
            user_id=send_user_id,
            user_action_type=USER_ACTION_TYPE.USER_FIRST_MESSAGE,
            merchant_id=merchant_id,
            device_id=device_id
        ).unwrap()
    except Exception as e:
        logging_exception()
        info_logger.info("send_message_triggle_lead_task error: {0}, send: {1}, target: {2}".format(
            e, send_user_id, target_user_id
        ))


@shared_task
def send_quesiton_message_task(sender_user_id, target_user_id, content, question_id="", merchant_id="", is_system=1):
    """ 线索通场景下，私信提问/方案机构咨询 触发线索任务生成发送私信

    相关链接:
    1. http://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=36559771
    2. http://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=36562088
    """
    info_logger.info({
        "send_question_message": question_id,
        "target_user_id": target_user_id,
        "send_user_id": sender_user_id,
        "content": content,
        "question_id": question_id,
        "merchant_id": merchant_id
    })
    from message.views.message import internal_message_send

    if not sender_user_id or not target_user_id or not content:
        info_logger.info("send_quesiton_message failed: parameter empty!")
        return

    before24hour = datetime.now() - timedelta(days=1)
    if MessageBlackUser.objects.filter(user_id=sender_user_id,
                                       created_time__gte=before24hour):
        info_logger.info("send_quesiton_message failed: send_user is bolocked!")
        return

    res = internal_message_send(
        sender_user_id=sender_user_id,
        target_user_id=target_user_id,
        conversation_type=CONVERSATION_TYPE.MESSAGE,
        msg_type=MESSAGE_TYPE.TEXT,
        content=content,
        push_stat_labels={'event_type': 'push', 'event': 'received_private_msg'},
        is_system=0,  # 线索通场景下统一改为系统发送
        source=MESSAGE_SOURCE.SALES_LEAD
    )

    if res['error'] == ERROR.MESSAGE_INVALID_USER:
        info_logger.info("send_quesiton_message failed: MESSAGE_INVALID_USER!")
        return

    if res['error'] != ERROR.SUCCESS:
        info_logger.info("send_quesiton_message failed: NOT SUCCESS!")
        return

    info_logger.info({
        "send_question_message_success": question_id,
        "msg": res["msg"]
    })
    return
