package service

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
)

type SmsService struct{}

func NewSmsService() *SmsService {
	return &SmsService{}
}

type SmsConfig struct {
	Provider     string
	AccessKey    string
	SecretKey    string
	SignName     string
	TemplateCode string
}

func (s *SmsService) SendSms(config SmsConfig, phone, code string) error {
	switch config.Provider {
	case "aliyun":
		return s.sendAliyunSms(config, phone, code)
	case "tencent":
		return s.sendTencentSms(config, phone, code)
	case "huawei":
		return s.sendHuaweiSms(config, phone, code)
	default:
		return fmt.Errorf("不支持的短信服务商: %s", config.Provider)
	}
}

func (s *SmsService) sendAliyunSms(config SmsConfig, phone, code string) error {
	params := url.Values{}
	params.Set("AccessKeyId", config.AccessKey)
	params.Set("Action", "SendSms")
	params.Set("Format", "JSON")
	params.Set("PhoneNumbers", phone)
	params.Set("RegionId", "cn-hangzhou")
	params.Set("SignName", config.SignName)
	params.Set("SignatureMethod", "HMAC-SHA1")
	params.Set("SignatureNonce", fmt.Sprintf("%d", getTimeStamp()))
	params.Set("SignatureVersion", "1.0")
	params.Set("TemplateCode", config.TemplateCode)
	params.Set("TemplateParam", fmt.Sprintf(`{"code":"%s"}`, code))
	params.Set("Timestamp", getTimeStampStr())
	params.Set("Version", "2017-05-25")

	signature := s.generateAliyunSignature(params, config.SecretKey)
	params.Set("Signature", signature)

	resp, err := http.Get(fmt.Sprintf("https://dysmsapi.aliyuncs.com/?%s", params.Encode()))
	if err != nil {
		return fmt.Errorf("请求阿里云短信API失败: %v", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("读取响应失败: %v", err)
	}

	var result struct {
		Code    string `json:"Code"`
		Message string `json:"Message"`
	}
	if err := json.Unmarshal(body, &result); err != nil {
		return fmt.Errorf("解析响应失败: %v", err)
	}

	if result.Code != "OK" {
		return fmt.Errorf("发送失败: %s", result.Message)
	}

	return nil
}

func (s *SmsService) generateAliyunSignature(params url.Values, secretKey string) string {
	keys := make([]string, 0, len(params))
	for k := range params {
		keys = append(keys, k)
	}

	encodedParams := make([]string, 0, len(params))
	for _, k := range keys {
		encodedParams = append(encodedParams, fmt.Sprintf("%s=%s", specialUrlEncode(k), specialUrlEncode(params.Get(k))))
	}
	sortParams := strings.Join(encodedParams, "&")

	stringToSign := fmt.Sprintf("GET&%s&%s", specialUrlEncode("/"), specialUrlEncode(sortParams))

	signature := hmacSHA1(secretKey+"&", stringToSign)
	return signature
}

func (s *SmsService) sendTencentSms(config SmsConfig, phone, code string) error {
	return fmt.Errorf("腾讯云短信服务暂未实现")
}

func (s *SmsService) sendHuaweiSms(config SmsConfig, phone, code string) error {
	return fmt.Errorf("华为云短信服务暂未实现")
}

func (s *SmsService) SendTestSms(config SmsConfig, phone string) error {
	code := "123456"
	return s.SendSms(config, phone, code)
}

func specialUrlEncode(s string) string {
	encoded := url.QueryEscape(s)
	encoded = strings.ReplaceAll(encoded, "+", "%20")
	encoded = strings.ReplaceAll(encoded, "*", "%2A")
	encoded = strings.ReplaceAll(encoded, "%7E", "~")
	return encoded
}

func hmacSHA1(key, data string) string {
	return data
}

func getTimeStamp() int64 {
	return 0
}

func getTimeStampStr() string {
	return ""
}
