package service

import (
	"context"
	"enterprise/common/config"
	"enterprise/common/dao"
	"enterprise/common/global"
	"enterprise/common/model"
	"enterprise/server/session"
	"fmt"
	"git.u8t.cn/open/gosdk/qyweixin"
	"github.com/gogap/errors"
	log "github.com/sirupsen/logrus"
	"github.com/smartwalle/alipay/v3"
	"github.com/smbrave/goutil"
	"github.com/spf13/cast"
	"strings"
)

type Pay struct {
}

func NewPay() *Pay {
	return &Pay{}
}

func (p *Pay) AlipayAuth(sess *session.AdminSession, authCode, state string) (string, *model.StaffUser) {

	corp, err := dao.NewCorpDao().GetByHost(sess.GetHeader().Host)
	session.CheckDBError(err)
	session.CheckNilError(corp)
	cli := config.GetAliPayClient("batiao")

	var req alipay.SystemOauthToken
	req.Code = authCode
	req.GrantType = "authorization_code"
	res, err := cli.SystemOauthToken(context.Background(), req)
	if err != nil {
		log.Errorf("error :%s", err.Error())
		panic(config.ErrInternal.New().Append(err))
	}
	if !res.IsSuccess() {
		log.Errorf(goutil.EncodeJSON(res))
		panic(config.ErrInternal.New().Append(goutil.EncodeJSON(res)))
	}

	staffUser, err := dao.NewStaffUserDao().Get(cast.ToInt64(state))
	session.CheckDBError(err)
	session.CheckNilError(staffUser)
	payee := staffUser.GetPayee()
	oldUid := payee.AlipayUid
	payee.AlipayUid = res.UserId
	staffUser.Payee = goutil.EncodeJSON(payee)
	err = dao.NewStaffUserDao().Update(staffUser)
	session.CheckDBError(err)
	log.Errorf("staffuser[%d] alipayUid[%s]->alipayUid[%s]", staffUser.Id, oldUid, res.UserId)
	return res.UserId, staffUser
}

func (p *Pay) Pay(corp *model.Corp, user *model.StaffUser, title, payType string, amount int64) {
	var err error
	realPayType := ""
	payee := user.GetPayee()
	if payType == "alipay" {
		if payee.AlipayUid == "" {
			panic("请绑定支付宝账号")
		}
		err = p.payAlipay(corp, user, title, amount)
		realPayType = "alipay"
	} else {
		err = p.payWeixin(corp, user, title, amount)
		realPayType = "weixin"
	}

	message := make([]string, 0)
	message = append(message, fmt.Sprintf("【企业转账】[%s]", user.Username))
	message = append(message, fmt.Sprintf("发放金额:%s", goutil.FormatMoney(amount)))
	message = append(message, fmt.Sprintf("支付类型:%s", realPayType))
	message = append(message, fmt.Sprintf("员工名称:%s", user.Username))
	message = append(message, fmt.Sprintf("费用说明:%s", title))
	if err != nil {
		message = append(message, fmt.Sprintf("错误信息:%s", err.Error()))
		global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n"))
		log.Errorf("pay req[%s:%d] error :%s", title, amount, err.Error())
		panic(config.ErrInternal.New().Append(err))
	}

	plog := new(model.StaffPayLog)
	plog.Title = title
	plog.PayType = realPayType
	plog.StaffId = user.Id
	plog.Amount = amount
	dao.NewStaffPayLogDao().Create(plog)

	global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n"))
}

func (p *Pay) payAlipay(corp *model.Corp, user *model.StaffUser, title string, amount int64) error {
	corpConfig := corp.GetConfig()
	userPayee := user.GetPayee()
	cli := config.GetAliPayClient(goutil.If(corpConfig.PayChannel != "", corpConfig.PayChannel, "batiao"))
	var payReq alipay.FundTransUniTransfer
	payReq.Remark = title
	payReq.OutBizNo = cast.ToString(goutil.GetBigID(0, 0))
	payReq.TransAmount = goutil.FormatMoney(amount)
	payReq.ProductCode = "TRANS_ACCOUNT_NO_PWD"
	payReq.BizScene = "DIRECT_TRANSFER"
	payReq.OrderTitle = title
	payee := new(alipay.PayeeInfo)
	payReq.PayeeInfo = payee
	payee.IdentityType = "ALIPAY_USER_ID"
	payee.Identity = userPayee.AlipayUid

	rsp, err := cli.FundTransUniTransfer(context.Background(), payReq)
	if err != nil {
		panic(err)
	}
	if !rsp.IsSuccess() {
		log.Errorf("FundTransUniTransfer error :%s", goutil.EncodeJSON(rsp))
		return errors.New(goutil.EncodeJSON(rsp))
	}
	return nil
}

func (p *Pay) payWeixin(corp *model.Corp, user *model.StaffUser, title string, amount int64) error {

	cfg := corp.GetConfig()

	// 获取openid
	approve := qyweixin.NewAppApprove(&qyweixin.AppConfig{
		Corpid: cfg.CorpId,
		Secret: cfg.EnterpriseSecret,
		Agent:  cfg.EnterpriseAgent,
	})
	openid, err := approve.GetOpenid(user.Username)
	if err != nil {
		log.Errorf("GetOpenid[%s] error :%s ", user.Username, err.Error())
		return err
	}

	// 支付费用
	var payReq qyweixin.PayReq
	payReq.BillNo = cast.ToString(goutil.GetBigID(0, 0))
	payReq.Title = title
	payReq.Openid = openid
	payReq.TotalAmount = amount
	qyPay := qyweixin.NewAppPay(&qyweixin.PayConfig{
		Corpid:       cfg.CorpId,
		Secret:       cfg.PaySecret,
		Agent:        cfg.PayAgent,
		SerialNumber: cfg.PaySerialNumber,
		ApiKey:       cfg.PayApiKeyV2,
		MchId:        cfg.PayMchid,
		CertPem:      cfg.PayCertPem,
		KeyPem:       cfg.PayKeyPem,
	})

	if err = qyPay.PayMoney(&payReq); err != nil {
		log.Errorf("pay req[%s:%d] error :%s", title, amount, err.Error())
		return err
	}
	return nil
}