package localjx

import (
	"fmt"
	"time"

	"git.rosy.net.cn/baseapi/platformapi/wxpayapi"
	"git.rosy.net.cn/baseapi/utils"
	"git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin"
	"git.rosy.net.cn/jx-callback/business/jxutils"
	"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
	"git.rosy.net.cn/jx-callback/business/model"
	"git.rosy.net.cn/jx-callback/business/model/dao"
	"git.rosy.net.cn/jx-callback/globals"
	"git.rosy.net.cn/jx-callback/globals/api"
)

func vendorPayType2WxpayType(vendorPayType string) string {
	return vendorPayType
}

func getOrderBrief(order *model.GoodsOrder) string {
	return fmt.Sprintf("%s等共%d件商品", order.Skus[0].SkuName, order.GoodsCount)
}

func pay4OrderByWX(ctx *jxcontext.Context, order *model.GoodsOrder, vendorPayType string) (orderPay *model.OrderPay, err error) {
	payCreatedAt := time.Now()
	param := &wxpayapi.CreateOrderParam{
		OutTradeNo:     utils.Int64ToStr(GenPayOrderID(order)),
		Body:           getOrderBrief(order),
		NotifyURL:      globals.WxpayNotifyURL,
		SpbillCreateIP: ctx.GetRealRemoteIP(),
		TradeType:      vendorPayType2WxpayType(vendorPayType),
		TotalFee:       int(order.ActualPayPrice),

		TimeStart: wxpayapi.Time2PayTime(payCreatedAt),
		// TimeExpire: wxpayapi.Time2PayTime(payCreatedAt.Add(PayWaitingTime)),
		ProfitSharing: wxpayapi.OptYes,
	}
	if authInfo, err := ctx.GetV2AuthInfo(); err == nil && authInfo.GetAuthType() == weixin.AuthTypeMini {
		param.OpenID = authInfo.GetAuthID()
	}

	result, err := api.WxpayAPI.CreateUnifiedOrder(param)
	if err == nil {
		orderPay = &model.OrderPay{
			PayOrderID:    param.OutTradeNo,
			PayType:       model.PayTypeWX,
			VendorPayType: vendorPayType,

			VendorOrderID: order.VendorOrderID,
			VendorID:      order.VendorID,
			Status:        0,
			PayCreatedAt:  payCreatedAt,
			PrepayID:      result.PrepayID,
			CodeURL:       result.CodeURL,
			TotalFee:      int(order.ActualPayPrice),
		}
	}
	return orderPay, err
}

func OnWxPayCallback(msg *wxpayapi.CallbackMsg) (err error) {
	switch msg.MsgType {
	case wxpayapi.MsgTypePay:
		err = onWxpayFinished(msg.Data.(*wxpayapi.PayResultMsg))
	case wxpayapi.MsgTypeRefund:
		err = onWxpayRefund(msg.Data.(*wxpayapi.RefundResultMsg))
	}
	return err
}

func onWxpayFinished(msg *wxpayapi.PayResultMsg) (err error) {
	orderPay := &model.OrderPay{
		PayOrderID: msg.OutTradeNo,
		PayType:    model.PayTypeWX,
	}
	orderPay.DeletedAt = utils.DefaultTimeValue
	db := dao.GetDB()
	if err = dao.GetEntity(db, orderPay, "PayOrderID", "PayType", "DeletedAt"); err == nil {
		orderPay.PayFinishedAt = utils.Time2Pointer(wxpayapi.PayTime2Time(msg.TimeEnd))
		orderPay.TransactionID = msg.TransactionID
		orderPay.OriginalData = utils.Format4Output(msg, true)
		if msg.ResultCode == wxpayapi.ResponseCodeSuccess {
			orderPay.Status = model.PayStatusYes
		} else {
			orderPay.Status = model.PayStatusFailed
		}
		dao.UpdateEntity(db, orderPay)
		if msg.ResultCode == wxpayapi.ResponseCodeSuccess {
			err = OnPayFinished(orderPay)
		}
	} else {
		globals.SugarLogger.Debugf("onWxpayFinished msg:%s, err:%v", utils.Format4Output(msg, true), err)
	}
	return err
}

func onWxpayRefund(msg *wxpayapi.RefundResultMsg) (err error) {
	orderPayRefund := &model.OrderPayRefund{
		RefundID: msg.ReqInfoObj.OutRefundNo,
	}
	db := dao.GetDB()
	if err = dao.GetEntity(db, orderPayRefund, "RefundID"); err == nil {
		if msg.ResultCode == wxpayapi.ResponseCodeSuccess {
			orderPayRefund.Status = model.RefundStatusYes
		} else {
			orderPayRefund.Status = model.RefundStatusFailed
		}
		orderPayRefund.OriginalData = utils.Format4Output(msg, true)
		dao.UpdateEntity(db, orderPayRefund)
	} else if dao.IsNoRowsError(err) {
		globals.SugarLogger.Warnf("收到异常的退款事件, msg:%s", utils.Format4Output(msg, true))
	}

	orderPay := &model.OrderPay{
		VendorOrderID: orderPayRefund.VendorOrderID,
		VendorID:      jxutils.GetPossibleVendorIDFromVendorOrderID(orderPayRefund.VendorOrderID),
		PayType:       model.PayTypeWX,
		Status:        model.PayStatusYes,
	}
	orderPay.DeletedAt = utils.DefaultTimeValue
	if err = dao.GetEntity(db, orderPay, "VendorOrderID", "VendorID", "PayType", "Status", "DeletedAt"); err == nil {
		orderPay.Status = model.PayStatusRefund
		dao.UpdateEntity(db, orderPay)
	}
	return err
}

func refundOrderByWX(ctx *jxcontext.Context, orderPay *model.OrderPay, refundID string, refundFee int, refundDesc string) (orderPayRefund *model.OrderPayRefund, err error) {
	result, err := api.WxpayAPI.PayRefund(&wxpayapi.PayRefundParam{
		OutTradeNo:  orderPay.VendorOrderID,
		NotifyURL:   globals.WxpayNotifyURL,
		OutRefundNo: refundID,
		TotalFee:    orderPay.TotalFee,
		RefundFee:   refundFee,
		RefundDesc:  wxpayapi.CData(refundDesc),
	})
	if err == nil {
		orderPayRefund = &model.OrderPayRefund{
			RefundID:        refundID,
			VendorRefundID:  result.RefundID,
			VendorOrderID:   orderPay.VendorOrderID,
			VendorID:        orderPay.VendorID,
			Status:          model.RefundStatusNo,
			TransactionID:   orderPay.TransactionID,
			RefundFee:       orderPay.TotalFee,
			RefundCreatedAt: time.Now(),
		}
	}
	return orderPayRefund, err
}
