# -*- coding: utf8 -*-
from __future__ import absolute_import, unicode_literals
import six
import json
import re
from django.conf import settings
from helios.rpc import RPCFaultException

from rpc.context import get_rpc_remote_invoker
from ..models import SMSTemplate, SMSTemplateItem
from gm_types.user_communication.sms.enum import PlatformDirective
from sms.utils.platforms import UCPaas, ALiDayu, Md, YunPian
from .dict_tool import ListDict
from .exception import PlatformNotFound, TemplateNotFound, InvalidPhoneNumber, SMSException
from rpc.tool.log_tool import sms_logger, logging_exception, info_logger


class SMSFactory:
    platforms = {
        PlatformDirective.UCPAAS: UCPaas(),
        PlatformDirective.ALI_DAYU: ALiDayu(),
        PlatformDirective.MD: Md(),
        PlatformDirective.YUNPIAN: YunPian(),
    }
    default_platform = settings.DEFAULT_SMS_PLATFORM

    def __init__(self):
        pass

    def log(self, platform, phone, template_id, params, msg):
        kwargs = {
            'platform': platform,
            'phone': phone,
            'template_id': template_id,
            'msg': msg,
        }
        sms_logger.info(json.dumps(kwargs, indent=2))

    def dispatch(self, platform=default_platform):
        cls = self.platforms.get(platform)
        if cls:
            return cls.send
        else:
            raise PlatformNotFound

    def send(self, phone, template_id, params, msg='', platform=default_platform, debug=settings.DEBUG):
        try:
            self._send(phone, template_id, params, msg, platform, debug)
        except SMSException as e:
            self.log(platform, phone, template_id, params, e.message)
        except:
            logging_exception()

    def _send(self, phone, template_id, params, msg, platform=default_platform, debug=settings.DEBUG):
        if platform == 'ucpass':
            platform = PlatformDirective.UCPAAS
        if not isinstance(phone, list):
            phone = [phone, ]
        temp = []
        for p in phone:
            try:
                self.check_cellphone_num(p)
                temp.append(p)
            except InvalidPhoneNumber:
                sms_logger.info('InvalidPhoneNumber:{}'.format(p))
        phone = temp

        try:
            gm_template = SMSTemplate.objects.get(id=template_id)
            msg = gm_template.content.format(**ListDict(params).to_dict())
            platform_template_id = gm_template.platform_template_id(platform)
        except SMSTemplateItem.DoesNotExist:
            # 非模版短信不存在SMSTemplateItem 是否考虑统一都添加
            platform_template_id = ''

        if debug:
            # 判断手机号是否在test的list中 如果在该list中 发送短信
            in_test_phone_list = set(phone) & set(settings.TEST_PHONE_LIST)
            if in_test_phone_list:
                phone = list(in_test_phone_list)
            else:
                self.send_email_for_test(phone, msg)
                return

        func = self.dispatch(platform)
        return func(phone, platform_template_id, params, msg)

    def send_email_for_test(self, phone, content):

        sms_logger.info(json.dumps(phone))
        email_list = settings.TEST_EMAIL_LIST
        phone_email_map = settings.TEST_PHONE_EMAIL_MAP
        target_email_list = list(email_list)

        if isinstance(phone, list):
            email_for_phone = []
            for i in phone:
                if phone_email_map.get(i):
                    email_for_phone.append(phone_email_map.get(i))
        else:
            email_for_phone = phone_email_map.get(phone)

        if email_for_phone:
            if isinstance(email_for_phone, six.string_types):
                target_email_list.append(email_for_phone)
            elif isinstance(email_for_phone, list):
                target_email_list.extend(email_for_phone)
            else:
                raise TypeError('unexpected type in TEST_PHONE_EMAIL_MAP: {}'.format(
                    type(email_for_phone).__name__))

        if not target_email_list:
            return

        subject = u'[开发测试]短信 to {}'.format(phone)

        from rpc.tool.internal_email_tool import send_internal_email
        send_internal_email(
            target_email_list,
            subject=subject,
            content=content,
        )

    @classmethod
    def check_cellphone_num(self, cellphone_num):
        """
            判断是否手机号码
        """
        regex = re.compile('^(1\d{10}$|\+\d+)')
        if not regex.match(str(cellphone_num)):
            raise InvalidPhoneNumber


def _gaia_send_sms(phone, template_id, params, platform, msg, debug):
    SMSFactory().send(phone, template_id, params, msg, platform, debug)


def _seperated_send_sms(phone, template_id, params, platform, msg, debug):
    try:
        # hack alidayu sms
        if platform == 'alidayu' and template_id in (43, '43'):
            params = filter(lambda x: 'code' in x, params)

        rpc_invoker = get_rpc_remote_invoker()
        future = rpc_invoker['sms_intermediate_endpoint/template/send'](
            phone=phone,
            template_id=template_id,
            params=params,
            platform=platform,
            msg=msg,
            debug=debug,
        )
        future.unwrap()
    except RPCFaultException:
        pass
    except:
        logging_exception()


_use_seperated_send_sms = False
try:
    _use_seperated_send_sms = bool(settings.SMS_USE_SEPERATED_SERVICE)
except AttributeError:
    logging_exception()
info_logger.info('SMS_USE_SEPERATED_SERVICE = {}'.format(_use_seperated_send_sms))


def send_sms(phone, template_id, params, platform=settings.DEFAULT_SMS_PLATFORM, msg='', debug=settings.DEBUG):
    if _use_seperated_send_sms:
        _seperated_send_sms(
            phone=phone,
            template_id=template_id,
            params=params,
            platform=platform,
            msg=msg,
            debug=debug
        )
    else:
        _gaia_send_sms(
            phone=phone,
            template_id=template_id,
            params=params,
            platform=platform,
            msg=msg,
            debug=debug
        )
