package services

import (
	"encoding/json"
	"eta/eta_mobile/models"
	"eta/eta_mobile/services/alarm_msg"
	"eta/eta_mobile/utils"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

// SendSmsCode 发送国内短信
func SendSmsCode(mobile, vCode, tplId string) (flag bool) {
	if mobile == "" || vCode == "" || tplId == "" {
		return
	}

	var (
		err error
		res string
	)
	defer func() {
		if err != nil {
			tips := fmt.Sprintf("短信验证码发送失败, Err: %s; Result: %s", err.Error(), res)
			utils.FileLog.Info("%s", tips)
			go alarm_msg.SendAlarmMsg(tips, 2)
		}
	}()
	// 获取配置好的短信模版
	smsCond := ` AND conf_key = ? `
	smsPars := make([]interface{}, 0)
	smsPars = append(smsPars, "SmsJhgnAppKey")
	conf := new(models.BusinessConf)
	conf, e := conf.GetItemByCondition(smsCond, smsPars)
	if e != nil {
		if e.Error() == utils.ErrNoRow() {
			err = fmt.Errorf("请先配置聚合短信Appkey")
			return
		}
		err = fmt.Errorf("获取聚合短信配置信息失败, Err: %s", e.Error())
		return
	}
	if conf.ConfVal == "" {
		err = fmt.Errorf("请先配置聚合短信Appkey")
		return
	}
	result, e := sendSms(conf.ConfVal, mobile, tplId, vCode)
	if e != nil {
		err = fmt.Errorf("send sms err: %s", e.Error())
		return
	}
	res = string(result)

	var netReturn map[string]interface{}
	if e = json.Unmarshal(result, &netReturn); e != nil {
		err = fmt.Errorf("json unmarshal err: %s", e.Error())
		return
	}
	errCode, ok := netReturn["error_code"].(float64)
	if !ok {
		err = fmt.Errorf("result code err")
		return
	}
	// 忽略错误的手机号码这种错误
	if errCode != 0 && errCode != 205401 {
		err = fmt.Errorf("err code %f", errCode)
		return
	}
	// 发送成功
	if errCode == 0 {
		flag = true
	}
	return
}

// sendSms 发送国内短信
func sendSms(jhGnAppKey, mobile, tplId, code string) (rs []byte, err error) {
	var Url *url.URL
	apiURL := "http://v.juhe.cn/sms/send"
	//初始化参数
	param := url.Values{}
	//配置请求参数,方法内部已处理urlencode问题,中文参数可以直接传参
	param.Set("mobile", mobile) //接受短信的用户手机号码
	param.Set("tpl_id", tplId)  //您申请的短信模板ID，根据实际情况修改
	tplVal := fmt.Sprintf(`#code#=%s&#m#=%d`, code, utils.VerifyCodeExpireMinute)
	param.Set("tpl_value", tplVal) //您设置的模板变量，根据实际情况
	param.Set("key", jhGnAppKey)   //应用APPKEY(应用详细页查询)

	Url, err = url.Parse(apiURL)
	if err != nil {
		fmt.Printf("解析url错误:\r\n%v", err)
		return nil, err
	}
	//如果参数中有中文参数,这个方法会进行URLEncode
	Url.RawQuery = param.Encode()
	resp, err := http.Get(Url.String())
	if err != nil {
		fmt.Println("err:", err)
		return nil, err
	}
	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}

// SendSmsCodeGj 发送国际短信
//func SendSmsCodeGj(mobile, vCode, areaNum, tplId string) bool {
//	var err error
//	defer func() {
//		if err != nil {
//			tips := fmt.Sprintf("短信验证码发送失败, Err: %s", err.Error())
//			utils.FileLog.Info("%s", tips)
//			go alarm_msg.SendAlarmMsg(tips, 2)
//		}
//	}()
//	// 获取配置好的短信模版
//	smsCond := ` AND conf_key = ? `
//	smsPars := make([]interface{}, 0)
//	smsPars = append(smsPars, "SmsJhgjAppKey")
//	conf := new(models.BusinessConf)
//	conf, e := conf.GetItemByCondition(smsCond, smsPars)
//	if e != nil {
//		if e.Error() == utils.ErrNoRow() {
//			err = fmt.Errorf("请先配置聚合短信Appkey")
//			return false
//		}
//		err = fmt.Errorf("获取聚合短信配置信息失败, Err: %s", e.Error())
//		return false
//	}
//	if conf.ConfVal == "" {
//		err = fmt.Errorf("请先配置聚合短信Appkey")
//		return false
//	}
//	result, err := sendSmsGj(conf.ConfVal, mobile, vCode, areaNum, tplId)
//	if err != nil {
//		fmt.Println("发送短信失败")
//		return false
//	}
//	fmt.Println("result", string(result))
//	var netReturn map[string]interface{}
//	err = json.Unmarshal(result, &netReturn)
//	if err != nil {
//		err = fmt.Errorf("短信验证码发送失败, Err:" + err.Error() + ";Result:" + string(result))
//		return false
//	}
//	if netReturn["error_code"].(float64) == 0 {
//		fmt.Printf("接口返回result字段是:\r\n%v", netReturn["result"])
//		return true
//	} else {
//		// 忽略错误的手机号码这种错误
//		if netReturn["error_code"].(float64) != 205401 {
//			err = fmt.Errorf("短信验证码发送失败, Result:" + string(result))
//		}
//		return false
//	}
//}

// sendSmsGj 发送国际短信
func sendSmsGj(jhGjAppKey, mobile, code, areaNum, tplId, tplValue string) (rs []byte, err error) {
	var Url *url.URL
	apiURL := "http://v.juhe.cn/smsInternational/send.php"
	//初始化参数
	param := url.Values{}
	//配置请求参数,方法内部已处理urlencode问题,中文参数可以直接传参
	param.Set("mobile", mobile) //接受短信的用户手机号码
	//param.Set("tplId", "10054")           //您申请的短信模板ID，根据实际情况修改
	param.Set("tplId", tplId) //您申请的短信模板ID，根据实际情况修改
	if strings.Contains(tplValue, "#code#=%s") {
		tplValue = strings.Replace(tplValue, "#code#=%s", "#code#="+code, 1)
	}
	if strings.Contains(tplValue, "#m#=%d") {
		tplValue = strings.Replace(tplValue, "#m#=%d", fmt.Sprintf("#m#=%d", utils.VerifyCodeExpireMinute), 1)
	}
	//param.Set("tplValue", "#code#="+code) //您设置的模板变量，根据实际情况
	param.Set("tplValue", tplValue) //您设置的模板变量，根据实际情况
	param.Set("key", jhGjAppKey)    //应用APPKEY(应用详细页查询)
	param.Set("areaNum", areaNum)   //应用APPKEY(应用详细页查询)

	Url, err = url.Parse(apiURL)
	if err != nil {
		fmt.Printf("解析url错误:\r\n%v", err)
		return nil, err
	}
	//如果参数中有中文参数,这个方法会进行URLEncode
	Url.RawQuery = param.Encode()
	resp, err := http.Get(Url.String())
	if err != nil {
		fmt.Println("err:", err)
		return nil, err
	}
	utils.FileLog.Info("sendSmsGj:param:" + Url.String())
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	utils.FileLog.Info("sendSmsGj:result:" + string(body))
	return body, err
}

type SmsClient interface {
	SendUserLoginCode(UserLoginSmsCodeReq) (UserLoginSmsCodeResult, error)
}

func NewSmsClient() (cli SmsClient, err error) {
	confMap, e := models.GetBusinessConf()
	if e != nil {
		err = fmt.Errorf("GetBusinessConf err: %s", e.Error())
		return
	}
	if confMap[models.BusinessConfSmsClient] == models.BusinessConfClientFlagNanHua {
		return new(NanHuaSms), nil
	}
	return new(HzSms), nil
}

type HzSms struct{}

type UserLoginSmsCodeReq struct {
	TelAreaCode string `description:"区号"`
	Mobile      string `description:"手机号"`
	VerifyCode  string `description:"短信验证码"`
}

type UserLoginSmsCodeResult struct {
	Success   bool   `description:"发送是否成功"`
	Message   string `description:"提示信息"`
	RequestId string `description:"发送ID，用于回查发送状态"`
}

// SendUserLoginCode 发送用户登录验证码
func (cli *HzSms) SendUserLoginCode(req UserLoginSmsCodeReq) (result UserLoginSmsCodeResult, err error) {
	if req.Mobile == "" || req.VerifyCode == "" {
		err = fmt.Errorf("参数有误, Mobile: %s, VerifyCode: %s", req.Mobile, req.VerifyCode)
		return
	}
	confMap, e := models.GetBusinessConf()
	if e != nil {
		err = fmt.Errorf("GetBusinessConf err: %s", e.Error())
		return
	}

	// 国内短信
	var netReturn map[string]interface{}
	if req.TelAreaCode == utils.TelAreaCodeHome {
		tplId := confMap[models.BusinessConfLoginSmsTpId]
		if tplId == "" {
			err = fmt.Errorf("请先配置短信模板")
			return
		}
		appKey := confMap[models.BusinessConfSmsJhgnAppKey]
		if appKey == "" {
			err = fmt.Errorf("请先配置聚合短信AppKey")
			return
		}

		smsRes, e := sendSms(appKey, req.Mobile, tplId, req.VerifyCode)
		if e != nil {
			err = fmt.Errorf("send sms err: %s", e.Error())
			return
		}
		if e = json.Unmarshal(smsRes, &netReturn); e != nil {
			err = fmt.Errorf("json unmarshal err: %s", e.Error())
			return
		}
	}

	// 国际短信
	if req.TelAreaCode != utils.TelAreaCodeHome {
		tplId := confMap[models.BusinessConfLoginSmsGjTpId]
		if tplId == "" {
			err = fmt.Errorf("请先配置短信模板")
			return
		}
		appKey := confMap[models.BusinessConfSmsJhgjAppKey]
		if appKey == "" {
			err = fmt.Errorf("请先配置聚合短信AppKey")
			return
		}
		tplValue := confMap[models.BusinessConfSmsJhgjVariable]
		if tplValue == "" {
			// 默认初版变量
			tplValue = "#code#=%s"
		}

		smsRes, e := sendSmsGj(appKey, req.Mobile, req.VerifyCode, req.TelAreaCode, tplId, tplValue)
		if e != nil {
			err = fmt.Errorf("send gj sms err: %s", e.Error())
			return
		}
		if e = json.Unmarshal(smsRes, &netReturn); e != nil {
			err = fmt.Errorf("json unmarshal err: %s", e.Error())
			return
		}
	}

	errCode, ok := netReturn["error_code"].(float64)
	if !ok {
		err = fmt.Errorf("result code err")
		return
	}
	// 忽略错误的手机号码这种错误
	if errCode != 0 && errCode != 205401 {
		err = fmt.Errorf("err code %f", errCode)
		return
	}
	// 发送成功
	if errCode == 0 {
		result.Success = true
	}
	return
}
