package bus

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

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

type MutliWechatPay struct {
}

func NewMutliWechatPay() PayInf {
	return &MutliWechatPay{}
}

func (w *MutliWechatPay) Pay(ctx context.Context, orderMsg *cpay.OrderMsg) (interface{}, error) {
	// 测试um
	// orderMsg.SellerKey = "um"
	if orderMsg.SellerKey == "" || orderMsg.SellerKey == "sku3d" {
		orderMsg.SellerKey = "sku3d"
		singleWechatPay := new(SingleWechatPay)
		return singleWechatPay.Pay(ctx, orderMsg)
	}

	log.Info("====================二维码获取=====================")
	fmt.Println("====================二维码获取1=====================")
	multiPayCnf := utils.GetMultiPayConfig(conf.AppConfig)

	seller := &model.MultiSeller{}
	fmt.Println("----------------------------wechat-pay-orderMsg------------------------------")
	fmt.Printf("%#v\n", orderMsg)

	// 设置默认收款

	fmt.Println("----------------------------wechat-pay-sellerkey------------------------------")
	println(orderMsg.SellerKey)
	ok, err := repo.RepoSeachDoc(&repo.RepoSession{Ctx: ctx, Client: db.GMongoDb}, &repo.DocSearchOptions{
		CollectName: "multi-sellers", //商家信息
		Query:       repo.Map{"key": orderMsg.SellerKey},
	}, seller)
	fmt.Println("----------------------------wechat-multi-sellers------------------------------")
	fmt.Printf("%#v\n", seller)

	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, fmt.Errorf("当前商户 %s 支付模块没接入", orderMsg.SellerKey)
	}
	amount, err := strconv.ParseFloat(fmt.Sprintf("%.2f", *orderMsg.Amount), 64)
	if err != nil {
		return nil, errors.New("价格parse错误！")
	}

	// 初始化 BodyMap
	orderId := orderMsg.Project + "_" + orderMsg.Id.Hex()
	bm := make(gopay.BodyMap)
	bm.Set("sp_appid", multiPayCnf.WechatPay.AppId).
		Set("sp_mchid", multiPayCnf.WechatPay.MchId).
		Set("sub_mchid", seller.WechatSellerId).
		Set("description", orderMsg.Name).
		Set("out_trade_no", orderId).
		Set("time_expire", time.Now().Add(10*time.Minute).Format(time.RFC3339)).
		Set("notify_url", multiPayCnf.WechatPay.NotifyUrl).
		SetBodyMap("amount", func(bm gopay.BodyMap) {
			bm.Set("total", amount*100).
				Set("currency", "CNY")
		})

	// 判断是电脑支付还是h5
	var url string
	if orderMsg.Os == "andriod" || orderMsg.Os == "iphone" || orderMsg.Os == "wap" {
		bm.SetBodyMap("scene_info", func(bm gopay.BodyMap) {
			bm.Set("payer_client_ip", orderMsg.Ip)
			bm.SetBodyMap("h5_info", func(b gopay.BodyMap) {
				b.Set("type", orderMsg.Ip)
			})
		})
		res, err := pay.MultiWechatpayClient.V3PartnerTransactionH5(ctx, bm)
		if err != nil {
			return false, err
		}

		if res.Code != 0 {
			return false, err
		}
		url = res.Response.H5Url
	} else {
		res, err := pay.MultiWechatpayClient.V3PartnerTransactionNative(ctx, bm)
		if err != nil {
			return false, err
		}

		if res.Code != 0 {
			return false, err
		}
		url = res.Response.CodeUrl
	}
	return url, nil
}

func (a *MutliWechatPay) Close(ctx context.Context, orderMsg *cpay.OrderMsg) (bool, error) {
	multiPayCnf := utils.GetMultiPayConfig(conf.AppConfig)
	orderId := orderMsg.Project + "_" + orderMsg.Id.Hex()
	bm := make(gopay.BodyMap)
	bm.Set("sp_mchid", multiPayCnf.WechatPay.MchId).
		Set("sub_mchid", orderMsg.SubId)
	wxRsp, err := pay.MultiWechatpayClient.V3PartnerCloseOrder(ctx, orderId, bm)
	if err != nil {
		return false, err
	}
	if wxRsp.Code != 0 {
		return false, errors.New(wxRsp.Error)
	}
	return true, nil
}

// 客户端对应必要参数 out_trade_no out_refund_no total refund payMode
func (m *MutliWechatPay) ReFundPay(ctx context.Context, refund *model.ReFund) (interface{}, error) {
	fmt.Println("----------------------------wechat-pay-refundPay------------------------------")

	// ??? 适配账号缺失
	if refund.SellerKey == "" || refund.SellerKey == "sku3d" {
		fmt.Println("----------------------------comming-sing-wechtpay-refundPay------------------------------")
		refund.SellerKey = "sku3d"
		singleWechatPay := new(SingleWechatPay)
		return singleWechatPay.ReFundPay(ctx, refund)
	}
	fmt.Println("----------------------------comming-multi-wechtpay-refundPay------------------------------")

	seller := &model.MultiSeller{}
	println(refund.SellerKey)
	ok, err := repo.RepoSeachDoc(&repo.RepoSession{Ctx: ctx, Client: db.GMongoDb}, &repo.DocSearchOptions{
		CollectName: "multi-sellers", //商家信息
		Query:       repo.Map{"key": refund.SellerKey},
	}, seller)
	fmt.Println("----------------------------wechat-multi-seller------------------------------")
	fmt.Printf("%#v\n", seller)

	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, fmt.Errorf("当前商户 %s 支付模块没接入", refund.SellerKey)
	}

	bm := make(gopay.BodyMap)
	multiPayCnf := utils.GetMultiPayConfig(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("sub_mchid", multiPayCnf.WechatPay.SubMchId).
		Set("out_refund_no", refund.Id.Hex()).
		Set("reason", refund.Reason).
		Set("notify_url", multiPayCnf.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)
	}

	fmt.Println("-----------------------------------------")
	fmt.Printf("bm--------------------------%#v\n", bm)

	wxRsp, err := pay.MultiWechatpayClient.V3Refund(ctx, bm)

	if err != nil {
		return false, err
	}
	if wxRsp.Code != 0 {
		return false, errors.New(wxRsp.Error)
	}
	// 退款状态
	// refundStatus := wxRsp.Response.Status

	return true, nil
}

// 退款状态查询
func (m *MutliWechatPay) ReFundQuery(ctx context.Context, refund *model.ReFund) (interface{}, error) {
	bm := make(gopay.BodyMap)
	// 需要设置子商户id
	multiPayCnf := utils.GetMultiPayConfig(conf.AppConfig)
	bm.Set("sub_mchid", multiPayCnf.WechatPay.SubMchId)
	res, err := pay.MultiWechatpayClient.V3RefundQuery(ctx, refund.Id.Hex(), bm)
	if err != nil {
		return nil, err
	}
	if res.Code != 0 {
		return nil, errors.New(res.Error)
	}

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