package service

import (
	"errors"
	"fmt"
	"math/rand"
	"strings"
	"time"
	"xiaoniaokuaiyan.com/xiaoniao/config"

	"xiaoniaokuaiyan.com/xiaoniao/dal"
	"xiaoniaokuaiyan.com/xiaoniao/entity"
	"xiaoniaokuaiyan.com/xiaoniao/util"
)

type SMSService struct {
	dal.ISMSCode
}

func generateValidateCode(length int) string {
	var (
		chars = "0123456789"
		rnum  int
		vcode string
	)
	for i := 0; i < length; i++ {
		rnum = rand.Intn(10)
		vcode += chars[rnum : rnum+1]
	}
	return vcode
}

/*func (srv *SMSService) SendSMS(mobile string, smsType int, params map[string]string) (rel interface{}, err error) {
	if ok := util.IsMobile(mobile); !ok {
		return nil, errors.New("手机号错误")
	}
	ctype := constants.SMSType(smsType)
	var (
		smsContent string
		codeType   int
		hasCode    bool
	)
	switch ctype {
	case constants.SMS_LOGIN:
		smsContent = constants.SMSCONTENT_LOGIN
		codeType = int(constants.SMSCODE_LOGIN)
		hasCode = true
	case constants.SMS_CHECKMOBILE:
		smsContent = constants.SMSCONTENT_CHECKMOBILE
		codeType = int(constants.SMSCODE_CHECKMOBILE)
		hasCode = true
	case constants.SMS_REGIST:
		smsContent = constants.SMSCONTENT_REGIST
		codeType = int(constants.SMSCODE_REGIST)
		hasCode = true
	case constants.SMS_FORGOT_PASSWORD:
		smsContent = constants.SMSCONTENT_FORGOT_PASSWORD
		codeType = int(constants.SMSCODE_FORGOT_PASSWORD)
		hasCode = true
	case constants.SMS_CHECK_RESULT:
		smsContent = constants.SMSCONTENT_CHECKRESULT
		codeType = int(constants.SMSCODE_CHECK_RESULT)
		hasCode = true
	case constants.SMS_ORDER_PAID_INFORM, constants.SMS_ORDER_PAID_INFORM_MBH:
		smsContent = constants.SMSCONTENT_PAYSUCCESS
		if ctype == constants.SMS_ORDER_PAID_INFORM_MBH {
			smsContent = constants.SMSCONTENT_MBH_PAYSUCCESS
		}
	case constants.SMS_JDBOOK:
		smsContent = constants.SMSCONTENT_JDBOOK_SUCCESS
	case constants.SMS_ORDER_PAID_INFORM_JIYIN:
		smsContent = constants.SMSCONTENT_JIYIN_PAYSUCCESS
	case constants.SMS_RESULT_TURNOUT:
		smsContent = constants.SMSCONTENT_RESULT_TURNOUT
		codeType = int(constants.SMSCODE_CHECK_RESULT)
		hasCode = true
	case constants.SMS_HOUSEKEEPING_QUERY:
		smsContent = constants.SMSCONTENT_HOUSEKEEPING
		codeType = int(constants.SMSCODE_HOUSEKEEPING_QUERY)
		hasCode = true
	case constants.SMS_ACT_YOUKE_LOGIN:
		smsContent = constants.SMSCONTENT_ACT_YOUKE_LOGIN
		codeType = int(constants.SMSCODE_ACT_YOUKE_LOGIN)
		hasCode = true
	default:
		return nil, errors.New("wrong code type")
	}
	if params == nil {
		params = map[string]string{}
	}
	if hasCode {
		vcode := generateValidateCode(6)
		params["code"] = vcode
		//smsContent = strings.Replace(smsContent, "{code}", vcode, 1)
		codeItem := &entity.SMSCode{
			Code:      vcode,
			Mobile:    mobile,
			CodeType:  codeType,
			CreatedAt: time.Now().Format("2006-01-02 15:04:05"),
		}
		_, err = srv.ISMSCode.Add(codeItem)
		if err != nil {
			return
		}
	}
	for k, v := range params {
		smsContent = strings.Replace(smsContent, "{"+k+"}", v, 1)
	}
	err = util.SendSMS(mobile, smsContent)
	return rel, err
}*/

func (srv *SMSService) ValidateCode(mobile string, code string, codeType int) (interface{}, error) {
	if v := util.IsMobile(mobile); !v {
		return nil, errors.New("wrong mobile")
	}
	codeItem, err := srv.ISMSCode.Get(mobile, code, codeType)
	if err != nil {
		return nil, err
	}
	if codeItem.Code == "" {
		return nil, errors.New("can not find code")
	}
	go func() {
		db := util.GetWriteSqlDB()
		db.Exec("update t_sms_code set is_used = 1 where mobile=? and code_type = ? and code=?", mobile, codeType, code)
		if codeType == 3 {
			usrv := &UserService{
				IUser: dal.DefaultUserDal,
			}
			usrv._registUser(mobile, false)
		}
	}()
	return codeItem, nil
}

func (srv *SMSService) SendSMS(mobile string, smsType int, params map[string]string) (interface{}, error) {
	var limit, _ = config.IniConf.Section("server").Key("black_limit").Int64()
	db := util.GetSqlDB()
	var count int
	db.Get(&count, "select count(1) from t_black_mobile where mobile = ?", mobile)
	if count > 0 {
		return false, nil
	}
	c := util.GetRedis()
	c.Select(14)
	key := "BLACK:" + mobile
	value := c.Get(key)
	if value.Val() == "" {
		t := time.Now()
		midnight := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()).AddDate(0, 0, 1)
		set := c.SetEx(key, midnight.Sub(t), "1")
		_ = set
	} else {
		incrBy := c.Incr(key)
		if incrBy.Val() >= limit {
			db.Exec("insert into  t_black_mobile (mobile) values(?)", mobile)
			return false, nil
		}
	}

	strSql := "select * from t_sms_tpl where id = ?;"
	//db := util.GetSqlDB()

	var smsTpl = struct {
		Content  string `db:"content"`
		Id       int    `db:"id"`
		HasCode  uint8  `db:"has_code"`
		CodeType int    `db:"code_type"`
	}{}
	db.Get(&smsTpl, strSql, smsType)
	if smsTpl.Content == "" {
		return false, nil
	}

	if params == nil {
		params = map[string]string{}
	}
	if smsTpl.HasCode > 0 {
		vcode := generateValidateCode(6)
		params["code"] = vcode
		//smsContent = strings.Replace(smsContent, "{code}", vcode, 1)
		codeItem := &entity.SMSCode{
			Code:      vcode,
			Mobile:    mobile,
			CodeType:  smsTpl.CodeType,
			CreatedAt: time.Now().Format("2006-01-02 15:04:05"),
		}
		_, err := srv.ISMSCode.Add(codeItem)
		if err != nil {
			return nil, err
		}
	}
	fmt.Println(smsTpl.Content, params)
	var smsContent string = smsTpl.Content
	for k, v := range params {
		smsContent = strings.Replace(smsContent, "{"+k+"}", v, -1)
	}
	err := util.SendSMS(mobile, smsContent)
	if err != nil {
		return false, err
	}
	strSql = "select is_accept_up from t_custom where mobile  = ?;"
	var isAcceptUP string
	db.Get(&isAcceptUP, strSql, mobile)
	return map[string]interface{}{
		"sms_result":      true,
		"is_accept_proto": isAcceptUP,
	}, nil
}

func (srv *SMSService) SendWorldSMS(mobile string, smsType int, params map[string]string) (interface{}, error) {
	strSql := "select * from t_sms_tpl where id = ?;"
	db := util.GetSqlDB()

	var smsTpl = struct {
		Content  string `db:"content"`
		Id       int    `db:"id"`
		HasCode  uint8  `db:"has_code"`
		CodeType int    `db:"code_type"`
	}{}
	db.Get(&smsTpl, strSql, smsType)
	if smsTpl.Content == "" {
		return false, nil
	}

	if params == nil {
		params = map[string]string{}
	}
	if smsTpl.HasCode > 0 {
		vcode := generateValidateCode(6)
		params["code"] = vcode
		//smsContent = strings.Replace(smsContent, "{code}", vcode, 1)
		codeItem := &entity.SMSCode{
			Code:      vcode,
			Mobile:    mobile,
			CodeType:  smsTpl.CodeType,
			CreatedAt: time.Now().Format("2006-01-02 15:04:05"),
		}
		_, err := srv.ISMSCode.Add(codeItem)
		if err != nil {
			return nil, err
		}
	}
	fmt.Println(smsTpl.Content, params)
	var smsContent string = smsTpl.Content
	for k, v := range params {
		smsContent = strings.Replace(smsContent, "{"+k+"}", v, -1)
	}
	err := util.SendWorldSMS(mobile, smsContent)
	if err != nil {
		return false, err
	}
	return true, nil
}