package sms_providers

import (
	"context"
	"encoding/json"
	"fmt"

	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	dysmsapi20170525 "github.com/alibabacloud-go/dysmsapi-20170525/v5/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	credential "github.com/aliyun/credentials-go/credentials"
	"github.com/veypi/vbase/cfg"
	"github.com/veypi/vigo"
	"github.com/veypi/vigo/logv"
)

// AliyunProvider 阿里云短信服务
type AliyunProvider struct {
	accessKeyID     string
	accessKeySecret string
	signName        string
	endpoint        string
	templateID      string
}

// NewAliyunProvider 创建阿里云短信服务
func NewAliyunProvider(config cfg.RegionConfig) (SMSProvider, error) {

	if config.Endpoint == "" {
		config.Endpoint = "dysmsapi.aliyuncs.com"
	}

	return &AliyunProvider{
		accessKeyID:     config.Key,
		accessKeySecret: config.Secret,
		signName:        config.SignName,
		endpoint:        config.Endpoint,
		templateID:      config.TemplateID,
	}, nil
}

// SendSMS 发送短信
func (p *AliyunProvider) SendSMS(ctx context.Context, req *SendSMSRequest) (string, error) {
	if req.Phone == "" {
		return "", fmt.Errorf("phone is required")
	}

	// 工程代码建议使用更安全的无AK方式，凭据配置方式请参见：https://help.aliyun.com/document_detail/378661.html。
	credential, err := credential.NewCredential(new(credential.Config).SetType("access_key").SetAccessKeyId(p.accessKeyID).SetAccessKeySecret(p.accessKeySecret))
	// credential, err := credential.NewCredential(nil)
	if err != nil {
		return "", err
	}

	config := &openapi.Config{
		Credential: credential,
	}
	// Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi
	config.Endpoint = tea.String(p.endpoint)
	client, err := dysmsapi20170525.NewClient(config)
	if err != nil {
		return "", err
	}
	templateID := req.TemplateID
	if templateID == "" {
		templateID = p.templateID
	}

	paramsBytes, _ := json.Marshal(req.Params)
	logv.Warn().Msgf("Send SMS to %s, %s, templateID: %s, params: %s", req.Phone, p.signName, templateID, string(paramsBytes))
	sendSmsRequest := &dysmsapi20170525.SendSmsRequest{
		SignName:      tea.String(p.signName),
		TemplateCode:  tea.String(templateID),
		PhoneNumbers:  tea.String(req.Phone),
		TemplateParam: tea.String(string(paramsBytes)),
	}
	runtime := &util.RuntimeOptions{}
	msgID := ""
	tryErr := func() (_e error) {
		defer func() {
			if r := tea.Recover(recover()); r != nil {
				_e = r
			}
		}()
		// 复制代码运行请自行打印 API 的返回值
		res, _err := client.SendSmsWithOptions(sendSmsRequest, runtime)
		if _err != nil {
			return _err
		}
		if res != nil && res.Body != nil && res.Body.BizId != nil {
			msgID = *res.Body.BizId
		}
		if msgID == "" && res != nil && res.Body != nil && res.Body.Message != nil {
			logv.Warn().Msgf("%+v", res)
			return vigo.NewError(*res.Body.Message)
		}

		return nil
	}()
	if tryErr != nil {
		return "", tryErr
	}
	return msgID, nil
}

// GetName 获取服务商名称
func (p *AliyunProvider) GetName() string {
	return "aliyun"
}
