package payment

import (
	"encoding/xml"
	"errors"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"

	"tower_api/pkg/util"
	"tower_api/service"
)

// QuickPay quick支付回调
type QuickPay struct {
}

func NewQuickPay() *QuickPay {
	return &QuickPay{}
}

func (q *QuickPay) Callback(c *gin.Context) (orderSn string, amount int, err error) {
	//quick额外在url中把appid带过来(当前渠道数据回调都是加密的，不能直接获取到订单信息),即ProductKey
	appid := strings.TrimSpace(c.Query("appid"))
	callback := QuickPayCallBack{}
	if c.ShouldBind(&callback) != nil || !util.IsAppId(appid) {
		return "", 0, errors.New("params error")
	}

	//1 根据appid获取解密的Md5_Key和解密数据的Callback_Key
	playerSrv := service.NewPlayerService()
	packageInfo, err := playerSrv.CheckPkgByAppId(appid)
	if err != nil {
		return "", 0, errors.New("can not find package")
	}
	//校验签名是否正确
	checked := callback.Validate(packageInfo.Appsecret)
	if !checked {
		return "", 0, errors.New("sign err")
	}
	//解密回调数据
	data, err := callback.ParseOrderInfo(packageInfo.ChannelKey)
	if err != nil {
		return "", 0, errors.New("decode message fail")
	}
	//2 解析出订单金额
	tmpMoney, _ := strconv.ParseFloat(data.Amount, 64)
	price := int(tmpMoney * 100)
	//3 返回订单信息
	return data.GameOrder, price, err
}

func (q *QuickPay) Confirm() error {
	return nil
}

func (q *QuickPay) ReplyContent(success bool) string {
	if success == true {
		return strings.ToUpper("SUCCESS")
	} else {
		return strings.ToUpper("FAIL")
	}
}

// 定义与XML结构对应的Go结构体
type Message struct {
	IsTest       string `xml:"is_test"`
	Channel      string `xml:"channel"`
	ChannelUID   string `xml:"channel_uid"`
	GameOrder    string `xml:"game_order"`
	OrderNo      string `xml:"order_no"`
	PayTime      string `xml:"pay_time"`
	Amount       string `xml:"amount"`
	Status       string `xml:"status"`
	ExtrasParams string `xml:"extras_params"`
}

// 回调的订单xml数据
type QuickPayData struct {
	Message Message `xml:"message"`
}

// 回调数据
type QuickPayCallBack struct {
	NtData  string `form:"nt_data"`
	Md5Sign string `form:"md5Sign"`
	Sign    string `form:"sign"`
}

func (q *QuickPayCallBack) Validate(md5Key string) bool {
	q.NtData = strings.TrimSpace(q.NtData)
	q.Md5Sign = strings.TrimSpace(q.Md5Sign)
	q.Sign = strings.TrimSpace(q.Sign)
	if q.Sign == "" {
		return false
	}
	tmpSign := util.EncodeMD5(q.NtData + q.Sign + md5Key)
	return tmpSign == q.Md5Sign
}

func (q *QuickPayCallBack) ParseOrderInfo(callbackKey string) (*Message, error) {
	data := decryptData(q.NtData, callbackKey)
	var callback QuickPayData
	err := xml.Unmarshal([]byte(data), &callback)
	if err != nil {
		return nil, err
	}
	if callback.Message.OrderNo == "" || callback.Message.Amount == "" {
		return nil, errors.New("解析出来的订单号或金额为空")
	}
	return &callback.Message, err
}

// quick的解密数据
func decryptData(nt_data string, callback_key string) string {
	strLen := len(nt_data)
	newData := []rune(nt_data)
	resultData := string(newData[1:strLen])
	dataArr := strings.Split(resultData, "@")
	keyArr := []byte(callback_key)
	keyLen := len(keyArr)

	var tmpList []int

	for index, value := range dataArr {
		base, _ := strconv.Atoi(value)
		dataString := base - int(0xFF&keyArr[index%keyLen])
		tmpList = append(tmpList, dataString)
	}

	var str string

	for _, val := range tmpList {
		str += string(rune(val))
	}
	return str
}
