package paymentService

import (
	"PaymentCenter/app/constants/common"
	"PaymentCenter/app/data"
	"PaymentCenter/app/models/orderthirdpaylogmodel"
	"PaymentCenter/app/models/paychannelmodel"
	"PaymentCenter/app/third/paymentService/payCommon"
	"context"
	"encoding/json"
	"strconv"
)

type PayOrderRequest struct {
	PayChannelId  int64  `json:"pay_channel_id"`  //	支付方式ID
	OrderId       int64  `json:"order_id"`        //	平台订单号
	ChannelType   int    `json:"channel_type"`    //	支付渠道枚举,1微信JSAPI,2微信H5,3微信app,4微信Native,5微信小程序,6支付宝网页&移动应用,7支付宝小程序,8支付宝JSAPI
	Description   string `json:"description"`     //	商品描述
	Amount        int    `json:"amount"`          //	金额单位为分
	PayerClientIp string `json:"payer_client_ip"` //	终端IP
	ReturnUrl     string `json:"return_url"`      //	支付成功后回调地址
	Wx            WxPay  `json:"wx"`              // 微信支付参数
	Ali           AliPay `json:"ali"`             // 支付宝参数
	OpenId        string `json:"open_id"`         // 支付者信息。 openid
}

type WxPay struct {
	AppId      string `json:"app_id"`      //	应用ID
	MchId      string `json:"mch_id"`      //	商户ID 或者服务商模式的 sp_mchid
	SerialNo   string `json:"serial_no"`   //	商户证书的证书序列号
	ApiV3Key   string `json:"api_v_3_key"` //	apiV3Key,商户平台获取
	PrivateKey string `json:"private_key"` //	私钥 apiclient_key.pem 读取后的内容
}

type AliPay struct {
	AppId            string `json:"app_id"`             //	应用ID
	PrivateKey       string `json:"private_key"`        //	应用私钥
	AppPublicCert    string `json:"app_public_cert"`    //	应用公钥
	AlipayRootCert   string `json:"alipay_root_cert"`   //	支付宝根证书
	AlipayPublicCert string `json:"alipay_public_cert"` //	支付宝公钥
}

type PayOrderResponse struct {
	Code     int    `json:"code"`
	ErrorMsg string `json:"error_msg"`
	Result   string `json:"result"`
}

// PaymentService	统一发起支付
func PaymentService(c context.Context, payOrderRequest PayOrderRequest) PayOrderResponse {
	//logger.Info(c, "PaymentService 收到支付请求", payOrderRequest)
	var err error
	var info string
	var payOrderResponse PayOrderResponse
	switch payOrderRequest.ChannelType {
	case payCommon.PAY_CHANNEL_WECHAT_H5:
		// 微信H5支付
		info, err = WxH5PayInfo(c, payOrderRequest)
	case payCommon.PAY_CHANNEL_ALIPAY_WEB:
		// 支付宝H5支付
		info, err = ALiH5PayInfo(c, payOrderRequest)
	case payCommon.PAY_CHANNEL_WECHAT_JSAPI:
		// 微信JSAPI支付
		info, err = WxJsApiPayInfo(c, payOrderRequest)

	default:
		payOrderResponse = PayOrderResponse{
			Code:     payCommon.PAY_NOT_FOUND_CODE,
			ErrorMsg: "暂不支持该支付渠道,请后续再使用",
		}
	}

	logStatus := common.THIRD_ORDER_LOG_STATUS_FAIL
	if err != nil {
		payOrderResponse = PayOrderResponse{
			Code:     payCommon.PAY_ERROR_CODE,
			ErrorMsg: err.Error(),
		}
		logStatus = common.THIRD_ORDER_LOG_STATUS_FAIL
	} else if payOrderResponse.ErrorMsg == "" {
		payOrderResponse = PayOrderResponse{
			Code:     payCommon.PAY_SUCCESS_CODE,
			ErrorMsg: "",
			Result:   info,
		}
		logStatus = common.THIRD_ORDER_LOG_STATUS_SUCCESS
	}

	//	记录日志
	go func() {
		orderId := payOrderRequest.OrderId
		payCallback, _ := json.Marshal(info)
		//payCallback := fmt.Sprintf("{%s}", info)
		payParam, _ := json.Marshal(payOrderRequest)
		merchantCallback, _ := json.Marshal(payOrderResponse)
		SaveLog(orderId, common.THIRD_ORDER_TYPE_PAY, string(payCallback), string(payParam), string(merchantCallback), logStatus)
	}()
	return payOrderResponse
}

type PayOrderQueryRequest struct {
	OrderId    int64  `json:"order_id"`    //	商户订单号
	PayChannel int    `json:"pay_channel"` //	支付渠道类型 1:wx,2:zfb
	Wx         WxPay  `json:"wx"`
	Ali        AliPay `json:"ali"`
}

type PayOrderQueryResponse struct {
	Code     int               `json:"code"`
	ErrorMsg string            `json:"error_msg"`
	Result   PayOrderQueryInfo `json:"result"`
}

type PayOrderQueryInfo struct {
	AppId          string `json:"app_id"`           //	应用ID
	OutTradeNo     int64  `json:"out_trade_no"`     //	商家订单号
	TransactionId  string `json:"transaction_id"`   //	第三方订单号
	TradeState     string `json:"trade_state"`      //  交易状态 SUCCESS:成功、REFUND:转入退款、NOTPAY:未支付、CLOSED:已关闭
	TradeStateDesc string `json:"trade_state_desc"` //	交易描述
	SuccessTime    string `json:"success_time"`     //	交易完成时间
	AmountTotal    int64  `json:"amount_total"`     //	订单总金额,单位:分
	PayerTotal     int64  `json:"payer_total"`      //	支付总金额,单位:分
}

// PayOrderQuery	查询订单状态
func PayOrderQuery(c context.Context, payOrderQueryRequest PayOrderQueryRequest) PayOrderQueryResponse {
	var err error
	var info PayOrderQueryInfo
	var payOrderQueryResponse PayOrderQueryResponse
	switch payOrderQueryRequest.PayChannel {
	case payCommon.PAY_CHANNLE_TYPE_WECHAT:
		// 微信H5支付
		info, err = WxOrderQuery(c, payOrderQueryRequest.Wx, strconv.FormatInt(payOrderQueryRequest.OrderId, 10))
	case payCommon.PAY_CHANNLE_TYPE_ZFB:
		info, err = ALiOrderQuery(c, payOrderQueryRequest.Ali, strconv.FormatInt(payOrderQueryRequest.OrderId, 10))
	default:
		payOrderQueryResponse = PayOrderQueryResponse{
			Code:     payCommon.PAY_ERROR_CODE,
			ErrorMsg: "暂不支持该支付渠道,请后续再使用",
		}
	}

	logStatus := common.THIRD_ORDER_LOG_STATUS_FAIL
	if err != nil {
		payOrderQueryResponse = PayOrderQueryResponse{
			Code:     payCommon.PAY_ERROR_CODE,
			ErrorMsg: err.Error(),
		}
		logStatus = common.THIRD_ORDER_LOG_STATUS_FAIL
	} else if payOrderQueryResponse.ErrorMsg == "" {
		payOrderQueryResponse = PayOrderQueryResponse{
			Code:   payCommon.PAY_SUCCESS_CODE,
			Result: info,
		}
		logStatus = common.THIRD_ORDER_LOG_STATUS_SUCCESS
	}

	//	记录日志
	go func() {
		orderId := payOrderQueryRequest.OrderId
		payCallback, _ := json.Marshal(info)
		payParam, _ := json.Marshal(payOrderQueryRequest)
		merchantCallback, _ := json.Marshal(payOrderQueryResponse)
		SaveLog(orderId, common.THIRD_ORDER_TYPE_ORDER_QUERY, string(payCallback), string(payParam), string(merchantCallback), logStatus)
	}()
	return payOrderQueryResponse
}

type OrderRefundRequest struct {
	OrderId       int64  `json:"order_id"`        //	订单编号
	RefundOrderId int64  `json:"refund_order_id"` //	退款订单号
	RefundReason  string `json:"refund_reason"`   //	退款原因
	RefundAmount  int64  `json:"refund_amount"`   //	退款金额,单位分, 微信需要传入订单总额,不是用户实际支付金额
	PayChannel    int    `json:"pay_channel"`     //	支付渠道类型 1:wx,2:zfb
	Wx            WxPay  `json:"wx"`
	Ali           AliPay `json:"ali"`
}

type OrderRefundResponse struct {
	Code     int             `json:"code"`
	ErrorMsg string          `json:"error_msg"`
	Result   OrderRefundInfo `json:"result"`
}

type OrderRefundInfo struct {
	OutTradeNo        int64  `json:"out_trade_no"`        //	商家订单号
	TransactionId     string `json:"transaction_id"`      //	第三方订单号
	RefundFee         int64  `json:"refund_fee"`          //	退款金额
	RefundOrderId     int64  `json:"refund_order_id"`     //	退款订单号
	RefundStatus      int    `json:"refund_status"`       //	退款状态 0:未申请,1:退款中,2:退款成功,3:退款失败
	RefundSuccessTime string `json:"refund_success_time"` //	退款时间
}

// OrderRefund	订单退款
func OrderRefund(c context.Context, orderRefundRequest OrderRefundRequest) OrderRefundResponse {
	//logger.Info(c, "PaymentService 收到退款请求", orderRefundRequest)
	var err error
	var info OrderRefundInfo
	var orderRefundResponse OrderRefundResponse
	switch orderRefundRequest.PayChannel {
	case payCommon.PAY_CHANNLE_TYPE_WECHAT:
		// 微信H5支付
		info, err = WxOrderRefund(c, orderRefundRequest)
	case payCommon.PAY_CHANNLE_TYPE_ZFB:
		info, err = AliRefundOrder(c, orderRefundRequest)
	default:
		orderRefundResponse = OrderRefundResponse{
			Code:     payCommon.PAY_ERROR_CODE,
			ErrorMsg: "暂不支持该支付渠道,请后续再使用",
		}
	}

	logStatus := common.THIRD_ORDER_LOG_STATUS_FAIL
	if err != nil {
		orderRefundResponse = OrderRefundResponse{
			Code:     payCommon.PAY_ERROR_CODE,
			ErrorMsg: err.Error(),
		}
		logStatus = common.THIRD_ORDER_LOG_STATUS_FAIL
	} else if orderRefundResponse.ErrorMsg == "" {
		orderRefundResponse = OrderRefundResponse{
			Code:   payCommon.PAY_SUCCESS_CODE,
			Result: info,
		}
		logStatus = common.THIRD_ORDER_LOG_STATUS_SUCCESS
	}

	//	记录日志
	go func() {
		orderId := orderRefundRequest.OrderId
		payCallback, _ := json.Marshal(info)
		payParam, _ := json.Marshal(orderRefundRequest)
		merchantCallback, _ := json.Marshal(orderRefundResponse)
		SaveLog(orderId, common.THIRD_ORDER_TYPE_REFUND, string(payCallback), string(payParam), string(merchantCallback), logStatus)
	}()
	return orderRefundResponse
}

type OrderRefundQueryRequest struct {
	RefundOrderId int64  `json:"refund_order_id"` //	退款订单号
	OrderId       int64  `json:"order_id"`        //	支付订单号
	PayChannel    int    `json:"pay_channel"`     //	支付渠道类型 1:wx,2:zfb
	Wx            WxPay  `json:"wx"`
	Ali           AliPay `json:"ali"`
}
type OrderRefundQueryResponse struct {
	Code     int             `json:"code"`
	ErrorMsg string          `json:"error_msg"`
	Result   OrderRefundInfo `json:"result"`
}

// OrderRefundQuery	订单退款查询
func OrderRefundQuery(c context.Context, orderRefundQueryRequest OrderRefundQueryRequest) OrderRefundQueryResponse {
	var err error
	var info OrderRefundInfo
	var orderRefundQueryResponse OrderRefundQueryResponse
	switch orderRefundQueryRequest.PayChannel {
	case payCommon.PAY_CHANNLE_TYPE_WECHAT:
		// 微信H5支付
		info, err = WxOrderRefundQuery(c, orderRefundQueryRequest)
	case payCommon.PAY_CHANNLE_TYPE_ZFB:
		info, err = AliRefundOrderQuery(c, orderRefundQueryRequest)
	default:
		orderRefundQueryResponse = OrderRefundQueryResponse{
			Code:     payCommon.PAY_ERROR_CODE,
			ErrorMsg: "暂不支持该支付渠道,请后续再使用",
		}
	}

	logStatus := common.THIRD_ORDER_LOG_STATUS_FAIL
	if err != nil {
		orderRefundQueryResponse = OrderRefundQueryResponse{
			Code:     payCommon.PAY_ERROR_CODE,
			ErrorMsg: err.Error(),
		}
		logStatus = common.THIRD_ORDER_LOG_STATUS_FAIL
	} else if orderRefundQueryResponse.ErrorMsg == "" {
		orderRefundQueryResponse = OrderRefundQueryResponse{
			Code:   payCommon.PAY_SUCCESS_CODE,
			Result: info,
		}
		logStatus = common.THIRD_ORDER_LOG_STATUS_SUCCESS
	}

	//	记录日志
	go func() {
		orderId := orderRefundQueryRequest.OrderId
		payCallback, _ := json.Marshal(info)
		payParam, _ := json.Marshal(orderRefundQueryRequest)
		merchantCallback, _ := json.Marshal(orderRefundQueryResponse)
		SaveLog(orderId, common.THIRD_ORDER_TYPE_REFUND_QUERY, string(payCallback), string(payParam), string(merchantCallback), logStatus)
	}()
	return orderRefundQueryResponse
}

type OrderCloseRequest struct {
	OrderId    int64  `json:"order_id"`    //	支付订单号
	PayChannel int    `json:"pay_channel"` //	支付渠道类型 1:wx,2:zfb
	Wx         WxPay  `json:"wx"`
	Ali        AliPay `json:"ali"`
}

type OrderCloseResponse struct {
	Code     int            `json:"code"`
	ErrorMsg string         `json:"error_msg"`
	Result   OrderCloseInfo `json:"result"`
}

type OrderCloseInfo struct {
	OutTradeNo int64 `json:"out_trade_no"` //	商家订单号
}

// OrderClose	关闭订单
func OrderClose(c context.Context, orderCloseRequest OrderCloseRequest) OrderCloseResponse {
	//logger.Info(c, "PaymentService 收到关闭订单请求", orderCloseRequest)
	var err error
	var info OrderCloseInfo
	var orderCloseResponse OrderCloseResponse
	switch orderCloseRequest.PayChannel {
	case payCommon.PAY_CHANNLE_TYPE_WECHAT:
		// 微信H5支付
		info, err = WxCloseOrder(c, orderCloseRequest)
	case payCommon.PAY_CHANNLE_TYPE_ZFB:
		info, err = AliCloseOrder(c, orderCloseRequest)
	default:
		orderCloseResponse = OrderCloseResponse{
			Code:     payCommon.PAY_ERROR_CODE,
			ErrorMsg: "暂不支持该支付渠道,请后续再使用",
		}
	}

	logStatus := common.THIRD_ORDER_LOG_STATUS_FAIL
	if err != nil {
		orderCloseResponse = OrderCloseResponse{
			Code:     payCommon.PAY_ERROR_CODE,
			ErrorMsg: err.Error(),
		}
		logStatus = common.THIRD_ORDER_LOG_STATUS_FAIL
	} else if orderCloseResponse.ErrorMsg == "" {
		orderCloseResponse = OrderCloseResponse{
			Code:   payCommon.PAY_SUCCESS_CODE,
			Result: info,
		}
		logStatus = common.THIRD_ORDER_LOG_STATUS_SUCCESS
	}

	//	记录日志
	go func() {
		orderId := orderCloseRequest.OrderId
		payCallback, _ := json.Marshal(info)
		payParam, _ := json.Marshal(orderCloseRequest)
		merchantCallback, _ := json.Marshal(orderCloseResponse)
		SaveLog(orderId, common.THIRD_ORDER_TYPE_CLOSE, string(payCallback), string(payParam), string(merchantCallback), logStatus)
	}()
	return orderCloseResponse
}

// SaveLog	记录操作日志
func SaveLog(orderId int64, OType int, payCallback string, PayParam string, MerchantCallback string, status int) {
	thirdRepo := data.NewOrderThirdPayLogRepo(paychannelmodel.GetInstance().GetDb())
	log := orderthirdpaylogmodel.OrderThirdPayLog{
		OrderId:          orderId,
		PayCallback:      payCallback,
		Status:           status,
		PayParam:         PayParam,
		MerchantCallback: MerchantCallback,
		Type:             OType,
	}
	_, err := thirdRepo.OrderThirdPayLogInsertOne(&log)
	if err != nil {
		return
	}
}