package bus

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"pay/conf"
	"pay/db/model"
	"pay/log"
	"pay/pay"
	"pay/utils"
	"strconv"
	"time"

	"github.com/go-pay/gopay"
	cpay "infish.cn/comm/pay"
)

type SingleWechatPay struct {
}

func NewSingleWechatPay() PayInf {
	return &SingleWechatPay{}
}

func (a *SingleWechatPay) Pay(ctx context.Context, orderMsg *cpay.OrderMsg) (interface{}, error) {

	fmt.Println("====================single-wechat二维码获取=====================")

	// 初始化 BodyMap
	orderId := orderMsg.Id.Hex()
	bm := make(gopay.BodyMap)
	singlePayCnf := utils.GetSinglePayConfig(conf.AppConfig)
	amount, err := strconv.ParseFloat(fmt.Sprintf("%.2f", *orderMsg.Amount), 64)
	if err != nil {
		return nil, errors.New("价格parse错误！")
	}

	bm.Set("appid", singlePayCnf.WechatPay.AppId).
		Set("mchid", singlePayCnf.WechatPay.MchId).
		Set("description", orderMsg.Name).
		Set("out_trade_no", orderId).
		Set("time_expire", time.Now().Add(10*time.Minute).Format(time.RFC3339)).
		Set("notify_url", singlePayCnf.WechatPay.NotifyUrl).
		SetBodyMap("amount", func(bm gopay.BodyMap) {
			bm.Set("total", amount*100).
				Set("currency", "CNY")
		})

	res, err := pay.SingleWechatpayClient.V3TransactionNative(context.Background(), bm)
	if err != nil {
		fmt.Println(err)
		return false, err
	}

	if res.Code != 0 {
		fmt.Println("wxRsp:", res.Error)
		errMap := map[string]string{}
		msg := res.Error
		err = json.Unmarshal([]byte(res.Error), &errMap)
		if err == nil && len(errMap["message"]) > 0 {
			msg = errMap["message"]
		}
		return nil, errors.New(msg)
	}

	log.Debugf("wxRsp: %#v", res.Response)

	return res.Response.CodeUrl, nil
}

func (a *SingleWechatPay) Close(ctx context.Context, orderMsg *cpay.OrderMsg) (bool, error) {

	orderId := orderMsg.Project + "_" + orderMsg.Id.Hex()
	res, err := pay.SingleWechatpayClient.V3TransactionCloseOrder(ctx, orderId)
	if err != nil {
		return false, err
	}
	if res.Code != 0 {
		return false, errors.New(res.Error)
	}
	return true, nil
}

// https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_9.shtml
// 客户端对应必要参数 out_trade_no out_refund_no total refund payMode
func (s *SingleWechatPay) ReFundPay(ctx context.Context, refund *model.ReFund) (interface{}, error) {
	bm := make(gopay.BodyMap)
	singlePayCnf := utils.GetSinglePayConfig(conf.AppConfig)

	// 商品
	goods := make([]gopay.BodyMap, 0)
	gd := make(gopay.BodyMap)
	gd.Set("merchant_goods_id", refund.ProductId.Hex()).
		Set("goods_name", refund.ProductName).
		Set("unit_price", refund.ProductPrice).
		Set("refund_amount", refund.RefundAmount).
		Set("refund_quantity", refund.RefundQuantity)
	goods = append(goods, gd)

	bm.Set("out_trade_no", refund.TradeNo).
		Set("out_refund_no", refund.Id.Hex()).
		Set("reason", refund.Reason).
		Set("notify_url", singlePayCnf.WechatPay.NotifyUrl).
		SetBodyMap("amount", func(bm gopay.BodyMap) {
			bm.Set("total", refund.Total).
				Set("currency", "CNY").
				Set("refund", refund.Refund)
		})
	// 商品相关
	if len(refund.ProductId.Hex()) > 10 {
		bm.Set("goods_detail", goods)
	}

	res, err := pay.SingleWechatpayClient.V3Refund(ctx, bm)
	if err != nil {
		return false, err
	}
	if res.Code != 0 {
		return false, errors.New(res.Error)
	}

	return true, nil
}

// 退款状态查询
func (s *SingleWechatPay) ReFundQuery(ctx context.Context, refund *model.ReFund) (interface{}, error) {
	res, err := pay.SingleWechatpayClient.V3RefundQuery(ctx, refund.Id.Hex(), nil)
	if err != nil {
		return nil, err
	}
	if res.Code != 0 {
		return nil, errors.New(res.Error)
	}

	return res.Response.Status, nil
	// return res.Response, nil
}
