package openapiService

import (
	"context"
	"cron_admin/app/models/orderdetailsmodel"
	"cron_admin/app/models/ordersmodel"
	"cron_admin/app/models/usercouponmodel"
	"cron_admin/app/utils"
	"cron_admin/config"
	"crypto/aes"
	"encoding/base64"
	"gitee.com/chengdu_blue_brothers/openapi-go-sdk/api"
	"gitee.com/chengdu_blue_brothers/openapi-go-sdk/notify"
	"net/http"
	"time"
)

func CreatClient() (client *api.Client, err error) {
	merchantId := config.GetConf().OpenApi.MerchantId
	secretKey := config.GetConf().OpenApi.SecretKey
	isProd := config.GetConf().OpenApi.IsProd
	timeout := 10 * time.Second // 请求超时时间

	client, err = api.NewClient(merchantId, secretKey, isProd, timeout)
	if err != nil {
		return nil, err
	}
	return client, nil
}

type RechargeOrderReq struct {
	OutTradeNo      string
	ProductId       int
	RechargeAccount string
	AccountType     int
	Number          int
}

func RechargeOrder(rechargeOrderReq RechargeOrderReq) (result *api.RechargeOrderResp, err error) {
	req := &api.RechargeOrderReq{
		OutTradeNo:      rechargeOrderReq.OutTradeNo,
		ProductId:       rechargeOrderReq.ProductId,
		RechargeAccount: rechargeOrderReq.RechargeAccount,
		AccountType:     0,
		Number:          1,
		NotifyUrl:       config.GetConf().OpenApi.NotifyUrl,
	}
	client, err := CreatClient()
	if err != nil {
		return nil, err
	}
	result, err = client.RechargeOrder(context.Background(), req)
	if err != nil {
		return nil, err
	}
	if result.Code != api.CodeCreateOrderSuccess {
		return
	}
	return
}

func ReCardOrder(CardOrderReq api.CardOrderReq) (result *api.CardOrderResp, err error) {
	req := &api.CardOrderReq{
		OutTradeNo:  CardOrderReq.OutTradeNo,
		ProductId:   CardOrderReq.ProductId,
		AccountType: 0,
		Number:      1,
		NotifyUrl:   config.GetConf().OpenApi.NotifyUrl,
	}
	client, err := CreatClient()
	if err != nil {
		return nil, err
	}
	result, err = client.CardOrder(context.Background(), req)
	if err != nil {
		return nil, err
	}
	if result.Code != api.CodeCreateOrderSuccess {
		return
	}
	return
}

func DecryptCard(encCode string) (decode string, err error) {
	defer func() error {
		if r := recover(); r != nil {
			utils.Log(nil, "解密错误", err)

		}
		return err
	}()
	client, err := CreatClient()
	if err != nil {
		return
	}
	decryptedCode, err := decryptAES(encCode, client.GetSecretKey())
	if err != nil {
		return
	}
	return decryptedCode, nil
}

// AES 解密
func decryptAES(encryptedData string, secretKey string) (string, error) {
	// 第一步:对加密的卡密做base64 decode
	encryptedBytes, err := base64.StdEncoding.DecodeString(encryptedData)
	if err != nil {
		return "", err
	}

	// 第二步:使用aes-256-ecb解密
	cipher, _ := aes.NewCipher([]byte(secretKey))
	decrypted := make([]byte, len(encryptedBytes))
	size := 16
	for bs, be := 0, size; bs < len(encryptedBytes); bs, be = bs+size, be+size {
		cipher.Decrypt(decrypted[bs:be], encryptedBytes[bs:be])
	}
	paddingSize := int(decrypted[len(decrypted)-1])
	return string(decrypted[0 : len(decrypted)-paddingSize]), nil
}

func ParseAndVerify(request *http.Request) (req *notify.OrderReq, err error) {
	// 第一步:初使化client实例
	merchantId := config.GetConf().OpenApi.MerchantId
	secretKey := config.GetConf().OpenApi.SecretKey
	client := notify.NewNotify(merchantId, secretKey)

	// 第二步:验签并解析结果
	req, err = client.ParseAndVerify(request)
	if err != nil {
		return nil, err
	}
	return
}

// NotifyOperation /**
func NotifyOperation(order ordersmodel.Orders, req *notify.OrderReq) (err error) {
	var session = ordersmodel.GetInstance().GetDb().NewSession()
	session.Begin()
	updateOrder := ordersmodel.Orders{Status: 3}
	_, err = session.Where("Id = ?", order.Id).Update(&updateOrder)
	if err != nil {
		session.Rollback()
		return
	}
	//卡密
	if req.CardCode != "" {
		//订单详情
		updateOrderDetail := orderdetailsmodel.OrderDetails{Url: req.CardCode.Value()}
		_, err = session.Where("OrderId = ?", order.Id).Update(&updateOrderDetail)
		if err != nil {
			session.Rollback()
			return
		}
		userCouponDetail := usercouponmodel.UserCoupon{OrderInfo: req.CardCode.Value()}
		_, err = session.Where("OrderId = ?", order.Id).Update(&userCouponDetail)
		if err != nil {
			session.Rollback()
			return
		}
	}
	session.Commit()
	return
}