package payment

import (
	"context"
	"strings"

	"bsm/full/module/finance/wallet/internal/excode"
	"bsm/full/module/finance/wallet/internal/logic/alipay"
	"bsm/full/module/finance/wallet/internal/logic/wechat"
	"bsm/full/module/finance/wallet/internal/models"
	pb "bsm/full/module/finance/wallet/pb"
	"git.apinb.com/bsm-sdk/core/env"
	"git.apinb.com/bsm-sdk/core/errcode"
	"git.apinb.com/bsm-sdk/core/printer"
	"git.apinb.com/bsm-sdk/core/service"
	"git.apinb.com/bsm-sdk/core/utils"
)

// 支付-充值
func ByCharge(ctx context.Context, in *pb.ChargeRequest) (reply *pb.PaymentReply, err error) {
	auth, ok := service.ParseMetaCtx(ctx, nil)
	if ok != nil {
		return nil, ok
	}

	if in.Amount == 0 || in.Desc == "" {
		return nil, errcode.ErrInvalidArgument
	}

	var (
		myWallet, wErr = models.GetWalletByPassportIdentity(auth.ID, auth.Identity)
		orderNo        = utils.RandomString(32)
		paymentRecrod  = models.WalletPayment{
			WalletIdentity: myWallet.Identity,
			Type:           1, //1充值，2为订单
			OrderNo:        orderNo,
			PayChannel:     int8(in.PayChannel),
			PayType:        in.PayType,
			Amount:         in.Amount,
		}
	)
	if wErr != nil || myWallet.Identity == "" {
		return nil, errcode.ErrNotFound(404, "wallet")
	}

	paymentRecrod.Identity = utils.UUID()
	paymentRecrod.PassportID = auth.ID
	paymentRecrod.PassportIdentity = auth.Identity

	var payBodyAttach strings.Builder
	payBodyAttach.WriteString(env.Runtime.Workspace)
	payBodyAttach.WriteString(",")
	payBodyAttach.WriteString(paymentRecrod.Identity)

	replyResult := map[string]string{}
	switch in.PayChannel {
	case 1:
		if in.OpenId == "" {
			return nil, errcode.ErrInvalidArgument
		}
		wechat, err := wechat.NewWechat()
		if err != nil {
			printer.Error(err.Error())
			return nil, excode.ErrWechatInit
		}
		res, err := wechat.GetResponse(payBodyAttach.String(), orderNo, in.Desc, in.OpenId, in.Amount)
		if err != nil {
			printer.Error(err.Error())
			return nil, excode.ErrWechatGetResp
		}

		switch in.PayType {
		case "JSAPI":
			replyResult, err = wechat.JsapiPaySign(res.PrepayId)
			if err != nil {
				printer.Error(err.Error())
				return nil, excode.ErrWechatGetResp
			}
		case "APP":
			replyResult, err = wechat.AppPaySign(res.PrepayId)
			if err != nil {
				printer.Error(err.Error())
				return nil, excode.ErrWechatGetResp
			}
		case "MINI":
			replyResult, err = wechat.MiniPaySign(res.PrepayId)
			if err != nil {
				printer.Error(err.Error())
				return nil, excode.ErrWechatGetResp
			}
		default:
			return nil, excode.ErrPayType
		}

	case 2:
		var result string
		alipay, err := alipay.NewAlipay()
		if err != nil {
			printer.Error(err.Error())
			return nil, excode.ErrAlipayInit
		}
		alipay.SetBody(payBodyAttach.String(), orderNo, in.Amount)

		switch in.PayType {
		case "WAP":
			result, err = alipay.TradeWapPay()
			if err != nil {
				printer.Error(err.Error())
				return nil, excode.ErrAlipayGetResp
			}

		case "APP":
			result, err = alipay.TradeAppPay()
			if err != nil {
				printer.Error(err.Error())
				return nil, excode.ErrAlipayGetResp
			}
		default:
			return nil, excode.ErrPayType
		}

		replyResult["payUrl"] = result

	default:
		return nil, excode.ErrPayChannel
	}

	//写入支付记录表（不可忽略错误）
	if err := models.CreatePaymentRecord(&paymentRecrod); err != nil {
		printer.Error("CreatePaymentRecord failed: ", err.Error())
		return nil, errcode.ErrDB
	}

	return &pb.PaymentReply{
		Code:   200,
		Result: replyResult,
	}, nil
}
