package card_redeem_order

import (
	"context"
	"fmt"
	"kami/internal/consts"
	"kami/internal/errHandler"
	"kami/internal/model"
	"kami/internal/model/entity"
	"kami/internal/service"
	"kami/utility/pool"
	"kami/utility/utils"
	"time"

	"github.com/gogf/gf/v2/net/gtrace"
	"go.opentelemetry.io/otel/trace"

	"github.com/duke-git/lancet/v2/slice"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/gclient"
	"github.com/gogf/gf/v2/os/glog"
	"github.com/gogf/gf/v2/os/gtime"
	"github.com/gogf/gf/v2/text/gstr"
	"github.com/gogf/gf/v2/util/gconv"
)

func (h *sCardRedeemOrder) CallBackOrderToUpstream(ctx context.Context, orderNo string, autoCallback bool) (err error) {
	ctx, span := gtrace.NewTracer("兑换回调").Start(ctx, "兑换回调", trace.WithNewRoot(), trace.WithTimestamp(time.Now()))
	defer span.End()
	err = pool.New(pool.RedeemCardCallback, 20).Add(ctx, func(ctx2 context.Context) {

		orderEntity, err2 := h.GetOrderOneByOrderNo(ctx2, orderNo, nil)
		if err2 != nil {
			glog.Error(ctx2, "回调上游失败，原因：", err)
			return
		}

		if !slice.Contain([]consts.RedeemOrderStatus{consts.RedeemOrderSuccess, consts.RedeemOrderFail}, consts.RedeemOrderStatus(orderEntity.Status)) {
			return
		}

		if consts.RedeemOrderStatus(orderEntity.OrderStatus) == consts.RedeemOrderFailWithDifferentAmount &&
			!service.SysConfigDict().GetRedeemCardFailCallbackIsAllow(ctx2, consts.CardRedeemAccountCategory(orderEntity.Category)) {
			_ = h.AddHistory(ctx2, &model.RedeemCardOrderAddHistory{
				Amount:          orderEntity.ActualAmount,
				OrderNo:         orderEntity.OrderNo,
				AccountId:       orderEntity.AccountId,
				AccountName:     orderEntity.AccountName,
				OperationStatus: consts.RedeemOrderOperationCallbackNotExecuteWithUserCfg,
				Remark:          "用户充值金额与实际金额不符，不充值不回调",
			}, nil)
			return
		}

		if consts.RedeemOrderStatus(orderEntity.OrderStatus) == consts.RedeemOrderSuccessWithDifferentAmount &&
			!service.SysConfigDict().GetRedeemCardSucceedCallbackIsAllow(ctx2, consts.CardRedeemAccountCategory(orderEntity.Category)) {
			_ = h.AddHistory(ctx2, &model.RedeemCardOrderAddHistory{
				Amount:          orderEntity.ActualAmount,
				OrderNo:         orderEntity.OrderNo,
				AccountId:       orderEntity.AccountId,
				AccountName:     orderEntity.AccountName,
				OperationStatus: consts.RedeemOrderOperationCallbackNotExecuteWithUserCfg,
				Remark:          "用户充值金额与实际金额不符，进行充值，但不回调",
			}, nil)
			return
		}

		//TODO: 强制处理，卡面异议的不回调
		if slice.Contain([]consts.RedeemOrderStatus{consts.RedeemOrderSuccessWithDifferentAmount}, consts.RedeemOrderStatus(orderEntity.OrderStatus)) {
			orderEntity.Status = int(consts.RedeemOrderFail)
		}

		_ = h.AddHistory(ctx2, &model.RedeemCardOrderAddHistory{
			Amount:          orderEntity.ActualAmount,
			OrderNo:         orderEntity.OrderNo,
			AccountId:       orderEntity.AccountId,
			AccountName:     orderEntity.AccountName,
			OperationStatus: consts.RedeemOrderOperationCallbackStart,
		}, nil)

		isOk := false

		if consts.RedeemOrderStatus(orderEntity.OrderStatus) == consts.RedeemOrderSuccessWithCompensated &&
			(!service.SysConfigDict().GetRedeemCardCompensatedAutoCallback(ctx, consts.CardRedeemAccountCategory(orderEntity.Category)) && !autoCallback) {
			_ = h.AddHistory(ctx2, &model.RedeemCardOrderAddHistory{
				Amount:          orderEntity.ActualAmount,
				OrderNo:         orderEntity.OrderNo,
				AccountId:       orderEntity.AccountId,
				AccountName:     orderEntity.AccountName,
				OperationStatus: consts.RedeemOrderOperationCallbackNotExecuteWithUserCfg,
				Remark:          "用户设置：补卡不会自动回调",
			}, nil)
			return
		}

		for i := 1; i < 4; i++ {
			isOk, _ = h.callbackOrder(ctx2, orderEntity)
			if isOk {
				break
			}
			time.Sleep(time.Duration(i*2) * time.Second)
		}

		operationStatus := consts.RedeemOrderCallbackStatusFail
		callbackStatus := consts.RedeemOrderOperationCallbackFailed
		if isOk {
			operationStatus = consts.RedeemOrderCallbackStatusSuccess
			callbackStatus = consts.RedeemOrderOperationCallbackSucceed
		}

		_ = h.ModifyCallBackStatus(ctx2, orderEntity.OrderNo, operationStatus, nil)
		_ = h.AddHistory(ctx2, &model.RedeemCardOrderAddHistory{
			OrderNo:         orderEntity.OrderNo,
			Amount:          orderEntity.ActualAmount,
			OperationStatus: callbackStatus,
			AccountId:       orderEntity.AccountId,
			AccountName:     orderEntity.AccountName,
		}, nil)
	})
	return
}

// CallbackOrder 回调订单给第三方
func (h *sCardRedeemOrder) callbackOrder(ctx context.Context, data *entity.V1CardRedeemOrderInfo) (bool, error) {
	timestamp := gtime.Now().Timestamp()
	params := g.Map{
		"attach":     data.Attach,
		"merchantId": data.MerchantId,
		"amount":     data.ActualAmount,
		"status":     data.Status,
		"remark":     data.Remark,
		"timestamp":  timestamp,
		"sign":       utils.TmpEncrypt(data.Attach + data.OrderNo + gconv.String(timestamp)),
	}

	response, err := gclient.New().SetTimeout(3*time.Second).Get(ctx, data.NotifyUrl, params)
	if err != nil {
		glog.Error(ctx, "回调上游失败，原因：", err)
		return false, err
	}
	glog.Info(ctx, "回调参数：", params, "回调地址：", data.NotifyUrl, "回调id地址", response.StatusCode)
	body := gconv.String(response.ReadAll())
	glog.Info(ctx, "回调结果：", body)
	if gstr.ToLower(body) == "success" {
		glog.Info(ctx, "回调成功：", response)
		return true, nil
	}
	return false, gerror.NewCode(errHandler.HttpClientGetError, fmt.Sprintf("回调失败：%s", body))
}
