# coding=utf-8

import random
from urllib import request, parse
import re
import math

from django.db import models
from django.utils import timezone

from utils.exceptions import CustomError

from apps.wechat.models import Wechat


class XGJSMS:
    def __init__(self):
        self.SMS_URL = 'http://sms.zzliaoyuan.com:8088'
        self.SMS_PRODUCT_NOTIFY = 30 # 通知短信的代码
        self.success_result = {'Code': u'OK', 'Message': u'短信提交成功'}
        self.false_result = {'Code': u'FALSE', 'Message': u'短信提交失败'}

    def _do_request(self, req):
        try:
            resp = request.urlopen(req)
        except Exception as e:

            raise CustomError(u"短信平台错误")

        if resp.getcode() != 200:
            raise CustomError(u'短信平台错误')

        return resp.read()

    def send(self, sms_token, sms_sign, mobile, content):
        content = u"【%s】%s" % (sms_sign, content)

        url = '%s/balance/?token=%s' % (self.SMS_URL, sms_token)
        req = request.Request(url)

        try:
            resp = self._do_request(req)
        except CustomError as e:
            self.false_result['Message'] = e.get_error_msg()
            return self.false_result

        p = '<Product id="%s">([\d]+?)</Product>' % self.SMS_PRODUCT_NOTIFY
        r = re.search(p, resp.decode('utf-8'))
        if r == None:
            self.false_result['Message'] = u'短信平台账号余额不足'
            return self.false_result
        else:
            balance = int(r.groups()[0])
            fee_count = 1
            if len(content) > 70:
                fee_count = int(math.ceil(len(content) / 65.0))

            if balance < 1 or balance < 1 * fee_count:
                self.false_result['Message'] = u'短信平台账号余额不足'
                return self.false_result

        postDict = {'token': sms_token, 'product': self.SMS_PRODUCT_NOTIFY, 'numbers': mobile, 'content': content.encode('utf-8')}
        postData = parse.urlencode(postDict).encode('utf-8')
        url = self.SMS_URL + "/submit/"
        req = request.Request(url, postData)
        req.add_header('content-Type', "application/x-www-form-urlencoded; charset=UTF-8")

        try:
            resp = self._do_request(req)
        except CustomError as e:
            self.false_result['Message'] = e.get_error_msg()
            return self.false_result

        r = re.search("<Errors>([\s\S]+?)</Errors>", resp.decode('utf-8'))
        if r != None:
            self.false_result['Message'] = u'短信平台返回错误[%s]' % r.groups()[0]
            return self.false_result

        return self.success_result


class XGJVCode(models.Model):
    SUCCESSED = 0
    FAILED = 1
    STATUS_CHOICES = (
        (SUCCESSED, u'发送成功'),
        (FAILED, u'发送失败'),
    )

    vcode = models.CharField(verbose_name=u'验证码', max_length=4)
    mobile = models.CharField(verbose_name=u'手机号', max_length=11)
    create_time = models.DateTimeField(verbose_name=u'时间', auto_now_add=True)
    status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, verbose_name=u"状态", editable=False, default=SUCCESSED)
    error = models.CharField(verbose_name=u"错误原因", null=True, max_length=500)

    class Meta:
        db_table = "xgj_vcode"
        verbose_name = u"销管佳短信验证码"
        ordering = ['-id']
        default_permissions = ()

    @staticmethod
    def send(mobile, appid, type, captcha_key=None, captcha=None):
        # 参数说明：
        # token:
        # numbers: 手机号 以半角逗号分隔多个手机号码
        # content: 短信内容，中文使用utf-8编码
        # product：产品代码 只够买一个产品时可以省略该参数
        # schedule：定时发送时间  非必填

        if mobile == '' or not mobile:
            raise CustomError(u"无效的手机号！")
        app = Wechat.objects.filter(appid=appid).first()
        if not app:
            raise CustomError(u'参数无效')

        vcs = XGJVCode.objects.filter(mobile=mobile, type=type).order_by('-id')
        if vcs.count() > 0:
            vc = vcs[0]
            if (timezone.now() - vc.create_time).seconds < 60:
                raise CustomError(u'获取太频繁，请稍后再试！')

        code = str(random.randint(1234, 9999))
        str_code = u'短信验证码为：' + code + u'。为了保障您的账户安全，请勿泄露给他人，有效期为10分钟。'
        sms = XGJSMS()

        result = sms.send(app.sms_token, app.sms_sign, mobile, str_code)
        if result['Code'] == 'OK':
            XGJVCode.objects.create(mobile=mobile, vcode=code, type=type)
        else:
            XGJVCode.objects.create(mobile=mobile, vcode=code, type=type, status=XGJVCode.FAILED, error=result['Message'])
            raise CustomError(u"发送失败,请重试！")

    @staticmethod
    def verify(mobile, vcode, type):
        if mobile is None or vcode is None:
            raise CustomError(u'参数错误！')

        vc = XGJVCode.objects.filter(mobile=mobile, type=type).order_by('-id').first()
        if vc:
            if vc.vcode == vcode:
                if (timezone.now() - vc.create_time).seconds > 600:
                    raise CustomError(u'验证码已过期！')
            else:
                raise CustomError(u'验证码错误！')
        else:
            raise CustomError(u'该手机号未发送短信验证码！')
