package paymentutil

import (
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"net/url"
	"sort"
	"strings"
)

func WechatV2Sign(values map[string]string, key, signType string) string {
	keys := make([]string, 0, len(values))
	for k, v := range values {
		if k != "sign" && v != "" {
			keys = append(keys, k)
		}
	}
	sort.Strings(keys)
	parts := make([]string, 0, len(keys))
	for _, k := range keys {
		parts = append(parts, k+"="+values[k])
	}
	raw := strings.Join(parts, "&") + "&key=" + key
	if strings.EqualFold(signType, "HMAC-SHA256") {
		return HMACSHA256Hex([]byte(raw), key, true)
	}
	sum := md5.Sum([]byte(raw))
	return strings.ToUpper(hex.EncodeToString(sum[:]))
}

func MD5Canonical(values map[string]any, secret string) string {
	keys := make([]string, 0, len(values))
	for key, value := range values {
		if key != "sign" && value != nil && fmt.Sprint(value) != "" {
			keys = append(keys, key)
		}
	}
	sort.Strings(keys)
	query := url.Values{}
	for _, key := range keys {
		query.Set(key, fmt.Sprint(values[key]))
	}
	sum := md5.Sum([]byte(query.Encode() + "&key=" + secret))
	return strings.ToUpper(hex.EncodeToString(sum[:]))
}

func HMACSHA256Hex(raw []byte, secret string, upper bool) string {
	h := hmac.New(sha256.New, []byte(secret))
	_, _ = h.Write(raw)
	result := hex.EncodeToString(h.Sum(nil))
	if upper {
		return strings.ToUpper(result)
	}
	return result
}
