package console

import (
	"PaymentCenter/app/constants/common"
	"PaymentCenter/app/data"
	"PaymentCenter/app/http/entities"
	"PaymentCenter/app/http/entities/backend"
	"PaymentCenter/app/models/ordersmodel"
	"PaymentCenter/app/models/orderthirdpaylogmodel"
	"PaymentCenter/app/third/paymentService"
	"PaymentCenter/app/third/paymentService/payCommon"
	"PaymentCenter/app/utils"
	"PaymentCenter/config"
	"context"
	"encoding/json"
	"github.com/qit-team/snow-core/command"
	"strconv"
	"sync"
	"time"
	"xorm.io/builder"
)

func RegisterCommand(c *command.Command) {
	c.AddFunc("test", test)
	c.AddFunc("closeOrder", closeOrder)
}

// 关闭长时间支付中的订单
func closeOrder() {
	var now = time.Now().Format(time.DateTime)
	utils.Log(nil, "关闭订单", now)
	var ctx = context.Background()
	orderIds := make([]int64, 0)
	// 查询未支付的订单
	repo := data.NewOrderRepo(ordersmodel.GetInstance().GetDb())
	// 拼接条件
	cond := builder.NewCond()
	cond = cond.And(builder.Eq{"status": common.ORDER_STATUS_PAYING}, builder.Lt{"orders.create_time": time.Now().Add(-time.Second * time.Duration(config.GetConf().CronConfig.CloseOrderTime))})
	// 查询订单
	order := make([]ordersmodel.OrdersLeftPayChannelList, 0)
	err := repo.OrdersLeftPayChannelList(cond, entities.PageRequest{}, &order)
	if err != nil {
		utils.Log(nil, "关闭订单,查询未支付订单失败", err)
	} else if len(order) > 0 {
		for i := range order {
			orderInfo := order[i]
			// 往上游发送关闭订单请求
			req := paymentService.OrderCloseRequest{OrderId: orderInfo.Id}

			switch utils.PayType(orderInfo.ChannelType) {
			case common.PAY_CHANNLE_TYPE_WECHAT:
				wx := backend.WechatPayChannel{}
				_ = json.Unmarshal([]byte(orderInfo.ExtJson), &wx)
				req.PayChannel = payCommon.PAY_CHANNLE_TYPE_WECHAT
				req.Wx = paymentService.WxPay{
					AppId:      orderInfo.AppId,
					MchId:      wx.MchId,
					SerialNo:   wx.SerialNo,
					ApiV3Key:   wx.ApiV3Key,
					PrivateKey: wx.PrivateKey,
				}
			case common.PAY_CHANNLE_TYPE_ZFB:
				var ali backend.AliPayChannel

				req.PayChannel = payCommon.PAY_CHANNLE_TYPE_ZFB
				_ = json.Unmarshal([]byte(orderInfo.ExtJson), &ali)
				req.Ali = paymentService.AliPay{
					AppId:            orderInfo.AppId,
					PrivateKey:       ali.PrivateKey,
					AppPublicCert:    ali.AppPublicCert,
					AlipayRootCert:   ali.AlipayRootCert,
					AlipayPublicCert: ali.AlipayPublicCert,
				}
			default:
				utils.Log(nil, "关闭订单,支付渠道不支持", orderInfo.ChannelType)
				continue
			}
			// 发起关闭订单请求
			response := paymentService.OrderClose(ctx, req)
			// 成功
			if response.Code == payCommon.PAY_SUCCESS_CODE {
				orderIds = append(orderIds, orderInfo.Id)
			} else {
				utils.Log(nil, "关闭订单,上游支付失败", response)
			}
		}
		// 修改订单状态为关闭
		cond = builder.NewCond()
		cond = cond.And(builder.In("id", orderIds))
		_, err = repo.OrderUpdate(&ordersmodel.Orders{Status: common.ORDER_STATUS_CLOSE}, cond, "status")
		if err != nil {
			utils.Log(nil, "关闭订单,修改订单状态失败", err)
			return
		}
	}
	utils.Log(nil, "关闭订单,修改订单状态成功", "总数量="+strconv.Itoa(len(order)), "成功数量="+strconv.Itoa(len(orderIds)))
}

// 主动查询订单支付状态
func queryOrder() {
	var now = time.Now().Format(time.DateTime)
	utils.Log(nil, "主动查询订单支付状态", now)
	ctx := context.Background()
	// 查询未支付的订单
	repo := data.NewOrderRepo(ordersmodel.GetInstance().GetDb())
	// 拼接条件
	cond := builder.NewCond()
	cond = cond.And(builder.Eq{"status": common.ORDER_STATUS_PAYING}, builder.Gt{"orders.create_time": time.Now().Add(-time.Second * time.Duration(config.GetConf().CronConfig.QueryOrderTime))})
	order := make([]ordersmodel.OrdersLeftPayChannelList, 0)
	err := repo.OrdersLeftPayChannelList(cond, entities.PageRequest{}, &order)
	if err != nil {
		utils.Log(nil, "主动查询订单支付状态,查询未付中订单失败", err)
		return
	} else if len(order) > 0 {
		ch := make(chan struct{}, config.GetConf().CronConfig.ConcurrentNumber)
		wg := sync.WaitGroup{}

		for index := range order {
			ch <- struct{}{}
			wg.Add(1)
			orderInfo := order[index]

			// 发起查询上游支付
			go func(orderInfo ordersmodel.OrdersLeftPayChannelList) {
				defer func() {
					<-ch
					wg.Done()
				}()

				query := paymentService.PayOrderQueryRequest{
					OrderId: orderInfo.Id,
				}
				switch utils.PayType(orderInfo.ChannelType) {
				case common.PAY_CHANNLE_TYPE_WECHAT:
					wx := backend.WechatPayChannel{}
					_ = json.Unmarshal([]byte(orderInfo.ExtJson), &wx)
					query.PayChannel = payCommon.PAY_CHANNLE_TYPE_WECHAT
					query.Wx = paymentService.WxPay{
						AppId:      orderInfo.AppId,
						MchId:      wx.MchId,
						SerialNo:   wx.SerialNo,
						ApiV3Key:   wx.ApiV3Key,
						PrivateKey: wx.PrivateKey,
					}
				case common.PAY_CHANNLE_TYPE_ZFB:
					ali := backend.AliPayChannel{}
					query.PayChannel = payCommon.PAY_CHANNLE_TYPE_ZFB
					_ = json.Unmarshal([]byte(orderInfo.ExtJson), &ali)
					query.Ali = paymentService.AliPay{
						AppId:            orderInfo.AppId,
						PrivateKey:       ali.PrivateKey,
						AppPublicCert:    ali.AppPublicCert,
						AlipayRootCert:   ali.AlipayRootCert,
						AlipayPublicCert: ali.AlipayPublicCert,
					}
				default:
					utils.Log(nil, "查询订单,支付渠道不支持", orderInfo.ChannelType)
					return
				}

				// 发起查询
				result := paymentService.PayOrderQuery(ctx, query)
				utils.Log(nil, "主动查询订单支付状态,上游返回数据", result)
				// 查询成功,校验状态
				var status int
				if result.Code == payCommon.PAY_SUCCESS_CODE {
					switch result.Result.TradeState {
					case "SUCCESS":
						// 成功
						status = common.ORDER_STATUS_PAYED
					case "REFUND":
						// 退款

					case "NOTPAY":
						// 未支付
						return
					case "CLOSED":
						// 关闭
						status = common.ORDER_STATUS_CLOSE

					}
					// 回调通知下游	todo

					// 更新订单状态 todo
					orderUpdate := ordersmodel.Orders{
						Id:     orderInfo.Id,
						Status: status,
					}

					session := ordersmodel.GetInstance().GetDb().NewSession()
					if err = session.Begin(); err != nil {
						utils.Log(nil, "主动查询订单支付状态,更新订单状态失败", err)
						return
					}
					defer func() {
						if err != nil {
							session.Rollback()
						} else {
							err = session.Commit()
						}
					}()
					orderLogRepo := data.NewOrderThirdPayLogRepo(session)
					orderRepo := data.NewOrderRepo(session)

					conn := builder.NewCond()
					conn = conn.And(builder.Eq{"id": orderInfo.Id})
					_, err = orderRepo.OrderUpdate(&orderUpdate, conn)
					if err != nil {
						utils.Log(nil, "主动查询订单支付状态,更新订单状态失败", err)
						return
					}

					// 写入日志
					body, _ := json.Marshal(result)
					log := orderthirdpaylogmodel.OrderThirdPayLog{
						OrderId:          orderInfo.Id,
						PayCallback:      string(body),
						Status:           0,
						PayParam:         "",
						MerchantCallback: "",
					}
					_, err = orderLogRepo.OrderThirdPayLogInsertOne(&log)
					if err != nil {
						utils.Log(nil, "主动查询订单支付状态,写入支付日志失败", err)
					}

				}
			}(orderInfo)
		}
		wg.Wait()
	}
}

// 回调下游
func callbackOrder() {
	var now = time.Now().Format(time.DateTime)
	utils.Log(nil, "回调下游", now)
	// 查询回调失败的订单

	// 发起回调
}