package wxpay

import (
	"applet/app/utils"
	"applet/app/utils/logx"
	"fmt"
	"github.com/iGoogle-ink/gopay"
	"github.com/iGoogle-ink/gopay/pkg/util"
	"github.com/iGoogle-ink/gopay/wechat"
	v3 "github.com/iGoogle-ink/gopay/wechat/v3"
	"strconv"
	"time"
)

func NewClient(appId, mchId, apiKey string, isProd bool) *wechat.Client {
	// 初始化微信客户端
	//    appId:应用ID
	//    mchId:商户ID
	//    apiKey:API秘钥值
	//    isProd:是否是正式环境
	client := wechat.NewClient(appId, mchId, apiKey, isProd)
	// 打开Debug开关,输出请求日志,默认关闭
	client.DebugSwitch = gopay.DebugOn
	// 设置国家:不设置默认 中国国内
	//    wechat.China:中国国内
	//    wechat.China2:中国国内备用
	//    wechat.SoutheastAsia:东南亚
	//    wechat.Other:其他国家
	client.SetCountry(wechat.China)
	// 添加微信证书 Path 路径
	//    certFilePath:apiclient_cert.pem 路径
	//    keyFilePath:apiclient_key.pem 路径
	//    pkcs12FilePath:apiclient_cert.p12 路径
	//    返回err
	//client.AddCertFilePath()

	// 添加微信证书内容 Content
	//	certFileContent:apiclient_cert.pem 内容
	//	keyFileContent:apiclient_key.pem 内容
	//	pkcs12FileContent:apiclient_cert.p12 内容
	//	返回err
	//client.AddCertFileContent()
	return client
}

// TradeAppPay is 微信APP支付
func TradeAppPay(client *wechat.Client, subject, orderID, amount, notifyUrl string) (map[string]string, error) {
	// 初始化 BodyMap
	bm := make(gopay.BodyMap)
	bm.Set("nonce_str", util.GetRandomString(32)).
		Set("body", subject).
		Set("out_trade_no", orderID).
		Set("total_fee", amount).
		Set("spbill_create_ip", "127.0.0.1").
		Set("notify_url", notifyUrl).
		Set("trade_type", wechat.TradeType_App).
		Set("sign_type", wechat.SignType_MD5)
	/*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/
	// 预下单
	wxRsp, err := client.UnifiedOrder(bm)
	if err != nil {
		_ = logx.Warn(err)
		return nil, err
	}
	_, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp)
	if err != nil {
		_ = logx.Warn(err)
		return nil, err
	}
	//if !ok {
	//	return nil, errors.New("验签失败")
	//}
	timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
	paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey)
	res := map[string]string{
		"appid":     client.AppId,
		"partnerid": client.MchId,
		"prepayid":  wxRsp.PrepayId,
		"sign":      paySign,
		"package":   "Sign=WXPay",
		"noncestr":  wxRsp.NonceStr,
		"timestamp": timeStamp,
	}
	return res, nil
}

// TradeAppPay is 微信H5支付
func TradeH5Pay(client *wechat.Client, subject, orderID, amount, notifyUrl, ip string) (map[string]string, error) {
	// 初始化 BodyMap
	bm := make(gopay.BodyMap)
	bm.Set("nonce_str", util.GetRandomString(32)).
		Set("body", subject).
		Set("out_trade_no", orderID).
		Set("total_fee", amount).
		//Set("spbill_create_ip", "121.196.29.49").
		Set("spbill_create_ip", ip).
		Set("notify_url", notifyUrl).
		Set("trade_type", wechat.TradeType_H5).
		Set("sign_type", wechat.SignType_MD5).
		SetBodyMap("scene_info", func(bm gopay.BodyMap) {
			bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) {
				bm.Set("type", "Wap")
				bm.Set("wap_url", "https://www.fumm.cc")
				bm.Set("wap_name", "zyos")
			})
		})
	/*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/
	// 预下单
	fmt.Println(bm)
	wxRsp, err := client.UnifiedOrder(bm)
	fmt.Println(wxRsp)
	if err != nil {
		_ = logx.Warn(err)
		return nil, err
	}
	_, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp)
	if err != nil {
		_ = logx.Warn(err)
		return nil, err
	}
	timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
	packages := "prepay_id=" + wxRsp.PrepayId
	paySign := wechat.GetH5PaySign(client.AppId, wxRsp.NonceStr, packages, wechat.SignType_MD5, timeStamp, client.ApiKey)
	fmt.Println("paySign===", paySign)
	r := map[string]string{
		"redirect_url": wxRsp.MwebUrl,
	}
	return r, nil
}

// TradeMiniProgPay is 微信小程序支付 ☑️
func TradeMiniProgPay(client *wechat.Client, subject, orderID, amount, notifyUrl, openid string) (map[string]string, error) {
	// 初始化 BodyMap
	bm := make(gopay.BodyMap)
	bm.Set("nonce_str", util.GetRandomString(32)).
		Set("body", subject).
		Set("openid", openid).
		Set("out_trade_no", orderID).
		Set("total_fee", amount).
		Set("spbill_create_ip", "127.0.0.1").
		Set("notify_url", notifyUrl).
		Set("trade_type", wechat.TradeType_Mini).
		Set("sign_type", wechat.SignType_MD5)
	// 预下单
	wxRsp, err := client.UnifiedOrder(bm)
	if err != nil {
		_ = logx.Warn(err)
		return nil, err
	}
	timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
	packages := "prepay_id=" + wxRsp.PrepayId
	paySign := wechat.GetMiniPaySign(client.AppId, wxRsp.NonceStr, packages, wechat.SignType_MD5, timeStamp, client.ApiKey)
	res := map[string]string{
		"appId":     client.AppId,
		"paySign":   paySign,
		"signType":  wechat.SignType_MD5,
		"package":   packages,
		"nonceStr":  wxRsp.NonceStr,
		"timeStamp": timeStamp,
	}
	return res, nil
}

// TradeAppPayV3 is 微信APP支付v3
func TradeAppPayV3(client *v3.ClientV3, subject, orderID, amount, notifyUrl string) (map[string]string, error) {
	// 初始化 BodyMap
	amountNew := utils.AnyToFloat64(amount) * 100
	bm := make(gopay.BodyMap)
	bm.Set("nonce_str", util.GetRandomString(32)).
		Set("body", subject).
		Set("out_trade_no", orderID).
		Set("total_fee", amountNew).
		Set("spbill_create_ip", "127.0.0.1").
		Set("notify_url", notifyUrl).
		Set("trade_type", wechat.TradeType_App).
		Set("sign_type", wechat.SignType_MD5)
	/*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/
	//// 预下单
	//wxRsp, err := v3.UnifiedOrder(bm)
	//if err != nil {
	//	_ = logx.Warn(err)
	//	return nil, err
	//}
	//_, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp)
	//if err != nil {
	//	_ = logx.Warn(err)
	//	return nil, err
	//}
	////if !ok {
	////	return nil, errors.New("验签失败")
	////}
	//timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
	//paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey)
	//res := map[string]string{
	//	"appid":     client.AppId,
	//	"partnerid": client.MchId,
	//	"prepayid":  wxRsp.PrepayId,
	//	"sign":      paySign,
	//	"package":   "Sign=WXPay",
	//	"noncestr":  wxRsp.NonceStr,
	//	"timestamp": timeStamp,
	//}
	//return res, nil
	return nil, nil
}

//// TradeJSAPIPay is 微信JSAPI支付
func TradeJSAPIPay(client *wechat.Client, subject, orderID, amount, notifyUrl, openid string) (map[string]string, error) {
	// 初始化 BodyMap
	bm := make(gopay.BodyMap)
	bm.Set("nonce_str", util.GetRandomString(32)).
		Set("body", subject).
		Set("out_trade_no", orderID).
		Set("total_fee", amount).
		Set("spbill_create_ip", "121.196.29.49").
		Set("notify_url", notifyUrl).
		Set("trade_type", wechat.TradeType_JsApi).
		Set("sign_type", wechat.SignType_MD5).
		Set("openid", openid).
		SetBodyMap("scene_info", func(bm gopay.BodyMap) {
			bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) {
				bm.Set("type", "Wap")
				bm.Set("wap_url", "https://www.fumm.cc")
				bm.Set("wap_name", "zyos")
			})
		})
	// 预下单
	wxRsp, err := client.UnifiedOrder(bm)
	if err != nil {
		_ = logx.Warn(err)
		return nil, err
	}
	_, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp)
	if err != nil {
		_ = logx.Warn(err)
		return nil, err
	}
	//if !ok {
	//	return nil, errors.New("验签失败")
	//}
	timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
	//paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey)
	packages := "prepay_id=" + wxRsp.PrepayId
	paySign := wechat.GetJsapiPaySign(client.AppId, wxRsp.NonceStr, packages, wechat.SignType_MD5, timeStamp, client.ApiKey)

	logx.Info("wxRsp.PrepayId:" + wxRsp.PrepayId)
	logx.Info("wxRsp.PrepayId:" + wxRsp.PrepayId)
	logx.Info("wxRsp.PrepayId:" + openid)
	res := map[string]string{
		"appid":     client.AppId,
		"partnerid": client.MchId,
		"prepayid":  wxRsp.PrepayId,
		"sign":      paySign,
		"package":   "prepay_id=" + wxRsp.PrepayId,
		"noncestr":  wxRsp.NonceStr,
		"timestamp": timeStamp,
	}
	return res, nil
}

// TradeH5PayV3 is 微信H5支付v3
func TradeH5PayV3(client *wechat.Client, subject, orderID, amount, notifyUrl string) (string, error) {
	// 初始化 BodyMap
	bm := make(gopay.BodyMap)
	bm.Set("nonce_str", util.GetRandomString(32)).
		Set("body", subject).
		Set("out_trade_no", orderID).
		Set("total_fee", amount).
		Set("spbill_create_ip", "127.0.0.1").
		Set("notify_url", notifyUrl).
		Set("trade_type", wechat.TradeType_App).
		Set("device_info", "WEB").
		Set("sign_type", wechat.SignType_MD5).
		SetBodyMap("scene_info", func(bm gopay.BodyMap) {
			bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) {
				bm.Set("type", "Wap")
				bm.Set("wap_url", "https://www.fumm.cc")
				bm.Set("wap_name", "H5测试支付")
			})
		}) /*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/
	// 预下单
	wxRsp, err := client.UnifiedOrder(bm)
	if err != nil {
		_ = logx.Warn(err)
		return "", err
	}
	// ====APP支付 paySign====
	timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
	// 获取APP支付的 paySign
	// 注意:package 参数因为是固定值,无需开发者再传入
	//    appId:AppID
	//    partnerid:partnerid
	//    nonceStr:随机字符串
	//    prepayId:统一下单成功后得到的值
	//    signType:签名方式,务必与统一下单时用的签名方式一致
	//    timeStamp:时间
	//    apiKey:API秘钥值
	paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey)
	return paySign, nil
}

// TradeMiniProgPayV3 is 微信小程序支付v3
func TradeMiniProgPayV3(client *v3.ClientV3, subject, orderID, amount, notifyUrl string) (string, error) {
	return "", nil
}