package wt_sdk

import (
	"gitea.weitiangame.com/sdk/wt-game/utils"
	"sort"
	"strings"
	"sync"
)

// Order 表示订单对象,用于签名参数
type Order struct {
	Uid         string // 用户ID
	BsTradeNo   string // 交易编号
	Role        string // 用户角色
	RoleId      string // 角色ID
	ServerId    string // 服务器ID
	GoodsName   string // 商品名称
	OutTradeNo  string // 外部交易编号
	Body        string // 商品描述
	CpExtraInfo string // 扩展信息
	TradeState  string // 交易状态
	TotalFee    string // 总费用
	PayFee      string // 支付费用
	PayTime     string // 支付时间
}

// SDK结构体封装了SDK的配置和工具函数
type SDK struct {
	SecretKey string // 秘钥
}

// 单例实例和互斥锁,确保线程安全
var instance *SDK
var once sync.Once

// NewOrderPayment 返回一个SDK单例实例,初始化时传入秘钥
func NewOrderPayment(secretKey string) *SDK {
	once.Do(func() {
		instance = &SDK{
			SecretKey: secretKey,
		}
	})
	return instance // 返回单例实例
}

// SignParam 为提供的Order对象生成签名
func (s *SDK) SignParam(order *Order) (string, error) {
	// 创建待签名参数映射
	paramMap := s.createParamMap(order)

	// 按照字典顺序排序并生成待签名字符串
	signStr := s.BuildSignString(paramMap)

	// 计算最终签名并返回
	return utils.Md5String(signStr), nil
}

// createParamMap 构建参数映射,跳过 "sign" 和 "-" 键
func (s *SDK) createParamMap(order *Order) map[string]string {
	return map[string]string{
		"uid":          order.Uid,
		"bs_trade_no":  order.BsTradeNo,
		"role":         order.Role,
		"role_id":      order.RoleId,
		"server_id":    order.ServerId,
		"goods_name":   order.GoodsName,
		"out_trade_no": order.OutTradeNo,
		"body":         order.Body,
		"extra_info":   order.CpExtraInfo,
		"order_status": order.TradeState,
		"total_fee":    order.TotalFee,
		"pay_fee":      order.PayFee,
		"pay_time":     order.PayTime,
		"sign":         "", // 初始化签名为空
	}
}

// buildSignString 按照字典顺序排序参数并拼接成签名字符串
func (s *SDK) BuildSignString(params map[string]string) string {
	var builder strings.Builder
	keys := s.getSortedKeys(params) // 获取排序后的键

	// 拼接所有键对应的值
	for _, k := range keys {
		builder.WriteString(params[k])
	}

	// 将秘钥追加到签名字符串后
	builder.WriteString(s.SecretKey)

	return builder.String()
}

// getSortedKeys 返回排除 "sign" 和 "-" 键后的排序键列表
func (s *SDK) getSortedKeys(params map[string]string) []string {
	var keys []string
	for k := range params {
		// 跳过 "sign" 和 "-" 键
		if k == "sign" || k == "-" {
			continue
		}
		keys = append(keys, k)
	}
	sort.Strings(keys) // 排序键
	return keys
}