package do

import (
	"PaymentCenter/app/constants/common"
	"PaymentCenter/app/constants/errorcode"
	"PaymentCenter/app/services"
	"PaymentCenter/app/services/thirdpay/types"
	"xorm.io/builder"

	"PaymentCenter/app/models/merchantmodel"
	"PaymentCenter/app/models/orderrequestlogmodel"
	"PaymentCenter/app/models/ordersmodel"
	"PaymentCenter/app/models/paychannelmodel"
	"context"
)

type PayCheck struct {
	ctx        *context.Context
	Reqs       *types.Reqs
	AppCheck   *services.AppCheck
	RequestLog *orderrequestlogmodel.OrderRequestLog
	Channel    *paychannelmodel.PayChannel
	Merchant   *merchantmodel.Merchant
	OldOrder   *ordersmodel.Orders
	CheckCode  int
}

func NewPayCheck(ctx *context.Context, reqs *types.Reqs, appCheck *services.AppCheck, ip string) *PayCheck {
	if appCheck == nil {
		appCheck = services.GetAppCheck(reqs.AppId, ip)
	}
	return &PayCheck{
		ctx:       ctx,
		Reqs:      reqs,
		AppCheck:  appCheck,
		CheckCode: appCheck.Code,
	}
}

func (w *PayCheck) CheckPayInfo() {
	w.CheckMerchant()
	if w.CheckCode != errorcode.Success {
		return
	}
	w.CheckPayChannel()
	if w.CheckCode != errorcode.Success {
		return
	}
}

func (w *PayCheck) CheckPayChannel() {
	conn := builder.NewCond()
	conn = conn.And(builder.Eq{"id": w.Reqs.PayChannelId})
	w.Channel, w.CheckCode = services.GetAndCheckPayChannel(&paychannelmodel.PayChannel{}, conn)
}

func (w *PayCheck) CheckMerchant() {
	conn := builder.NewCond()
	conn = conn.And(builder.Eq{"id": w.AppCheck.App.MerchantId})
	w.Merchant, w.CheckCode = services.GetAndCheckMerchant(&merchantmodel.Merchant{}, conn)
}

func (w *PayCheck) CheckOrderPay() {
	w.GetOldOrder(&types.OrderFindOne{
		OutTradeNo: w.Reqs.OutTradeNo,
	})
	if w.OldOrder != nil {
		switch w.OldOrder.Status {
		case common.ORDER_STATUS_CLOSE:
			w.CheckCode = errorcode.OrderClosed
		case common.ORDER_STATUS_FAILED:
			w.CheckCode = errorcode.OrderFailed
		case common.ORDER_STATUS_PAYED:
			w.CheckCode = errorcode.OrderPayed
		default:
		}
		// 切换了支付方式
		if w.OldOrder.Status == common.ORDER_STATUS_PAYING && w.Reqs.PayChannelId != w.OldOrder.PayChannelId {
			w.CheckCode = errorcode.OrderPayChannelChange
		}
	}

	return
}

func (w *PayCheck) CheckOrderRefund() (order *ordersmodel.Orders) {
	// 查询原来的支付单
	w.GetOldOrder(&types.OrderFindOne{
		OutTradeNo: w.Reqs.RefundOutTradeNo,
		OrderId:    w.Reqs.RefundOrderId,
	})
	if w.OldOrder == nil {
		w.CheckCode = errorcode.RefundOrderNotFound
		return
	}
	if w.OldOrder.Status != common.ORDER_STATUS_PAYED {
		w.CheckCode = errorcode.OrderStatusRefundNotSupport
	}

	if w.OldOrder.Amount < w.Reqs.Amount {
		w.CheckCode = errorcode.OrderRefundAmountError
	}
	//暂不支持部分退款
	if w.OldOrder.Amount > w.Reqs.Amount {
		w.CheckCode = errorcode.OrderNotSupportRefundPart
	}

	return
}

func (w *PayCheck) GetOldOrder(orderCol *types.OrderFindOne) {
	order, code := w.GetOrder(orderCol)
	if code == errorcode.SystemError {
		w.CheckCode = code
		return
	}
	if code == errorcode.Success {
		w.OldOrder = order
	}
	return
}

func (w *PayCheck) GetOrder(orderCol *types.OrderFindOne) (order *ordersmodel.Orders, code int) {
	cond := builder.NewCond()
	cond = cond.And(builder.Eq{"app_id": w.AppCheck.AppId})
	if orderCol.OrderId == "" && orderCol.OutTradeNo == "" {
		w.CheckCode = errorcode.OrdersNotFound
		return
	}
	if orderCol.OrderId != "" {
		cond = cond.And(builder.Eq{"order_id": orderCol.OrderId})
	}
	if orderCol.OutTradeNo != "" {
		cond = cond.And(builder.Eq{"out_trade_no": orderCol.OutTradeNo})
	}
	order, code = services.OrderFindOne(&ordersmodel.Orders{}, cond)

	return
}