package payment

import (
	"encoding/json"
	"errors"
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"github.com/beego/beego/v2/adapter/httplib"
	"github.com/gin-gonic/gin"

	"tower_api/pkg/util"
	"tower_api/service"
)

type SYPay struct {
	secret  string //每个游戏包的密钥不一样,需要根据不同的游戏包获取
	orderId string
}

func NewSYPay() *SYPay {
	return &SYPay{}
}

// Callback 请求回调
func (s *SYPay) Callback(c *gin.Context) (orderSn string, amount int, err error) {
	//1.请求数据解析
	var callback SyCallBack
	if c.ShouldBind(&callback) != nil || callback.Validate() != nil {
		return "", 0, errors.New("params error")
	}
	//1.1 通过订单号找到具体包,找到对应的密钥
	orderService := service.NewOrderService()
	secret := orderService.GetSecret(callback.OrderId)
	if secret == "" {
		return "", 0, errors.New("can not find secret")
	}
	s.secret = secret
	s.orderId = callback.OrderId
	//2.验证签名
	callbackMap := util.Struct2Map(callback)
	tmpSign := util.GenSignMD5(callbackMap, s.secret)
	if tmpSign != callback.Sign {
		return "", 0, errors.New("sign error")
	}
	//金额解析为分
	tmpMoney, _ := strconv.ParseFloat(callback.Price, 64)
	price := int(tmpMoney * 100)
	//4. 返回数据
	return s.orderId, price, err
}

// Confirm 确认订单是否支付成功
func (s *SYPay) Confirm() error {
	//请求上游查询接口，判断订单是否真的成功
	tmpToSignStr := fmt.Sprintf("channel=%s&orderid=%s", s.secret, s.orderId)
	sign := util.EncodeMD5(tmpToSignStr)
	req := httplib.Post("http://docater1.cn/index.php?g=Wap&m=MiniGame&a=getPayInfo")
	req.Param("channel", s.secret)
	req.Param("orderid", s.orderId)
	req.Param("sign", sign)
	byteRes, err := req.Bytes()
	if err != nil {
		return errors.New("http request err")
	}
	var syPayInfo SyPayInfo
	err = json.Unmarshal(byteRes, &syPayInfo)
	if err != nil {
		return errors.New("http result err")
	}
	if strings.ToUpper(syPayInfo.Data.State) != "SUCCESS" {
		return errors.New("un pay")
	}
	return nil
}

// ReplyContent 校验成功后返回给上游的内容
func (s *SYPay) ReplyContent(success bool) string {
	if success == true {
		return strings.ToLower("SUCCESS")
	} else {
		return strings.ToLower("FAIL")
	}
}

// SyCallBack 盛也支付回调的参数
type SyCallBack struct {
	OrderId string `form:"orderid" json:"orderid" `
	OpenId  string `form:"openid" json:"openid"`
	Price   string `form:"price" json:"price" `
	ItemId  int    `form:"item_id" json:"item_id"`
	Other   string `form:"other" json:"other"`
	Sign    string `form:"sign" json:"sign" `
}

// Validate 校验参数
func (s *SyCallBack) Validate() error {
	s.OrderId = strings.TrimSpace(s.OrderId)
	s.OpenId = strings.TrimSpace(s.OpenId)
	s.Other = strings.TrimSpace(s.Other)
	s.Sign = strings.TrimSpace(s.Sign)
	if isOrderSn(s.OrderId) == false || s.Sign == "" {
		return errors.New("parameter invalid")
	}
	return nil
}

// SyPayInfo PayInfo 查询订单接口返回
type SyPayInfo struct {
	Data struct {
		ExtendParam1 string `json:"extend_param1"`
		ExtendParam2 string `json:"extend_param2"`
		ItemID       string `json:"item_id"`
		OpenID       string `json:"openId"`
		OrderId      string `json:"orderid"`
		Other        string `json:"other"`
		Price        string `json:"price"`
		State        string `json:"state"`
	} `json:"data"`
	Info   string `json:"info"`
	Status int64  `json:"status"`
}

// 校验sy的单号格式是否正确
func isOrderSn(orderSn string) bool {
	if m, _ := regexp.MatchString(`^\w+$`, orderSn); !m {
		return false
	}
	return true
}
