package binanceservice

import (
	"fmt"
	"strings"

	DbModels "go-admin/app/admin/models"
	"go-admin/pkg/retryhelper"

	"github.com/bytedance/sonic"
	log "github.com/go-admin-team/go-admin-core/logger"
	"github.com/go-admin-team/go-admin-core/sdk/service"
)

type FuturesResetV2 struct {
	service.Service
}

// 带重试机制的合约下单
func (e *FuturesResetV2) OrderPlaceLoop(apiUserInfo *DbModels.LineApiUser, params FutOrderPlace) error {
	opts := retryhelper.DefaultRetryOptions()
	opts.RetryableErrFn = func(err error) bool {
		if strings.Contains(err.Error(), "LOT_SIZE") {
			return false
		}
		//重试
		return true
	}

	err := retryhelper.Retry(func() error {
		return e.OrderPlace(apiUserInfo, params)
	}, opts)

	if err != nil {
		return err
	}
	return nil
}

// 合约下单
func (e *FuturesResetV2) OrderPlace(apiUserInfo *DbModels.LineApiUser, params FutOrderPlace) error {
	if err := params.CheckParams(); err != nil {
		return err
	}

	orderType := strings.ToUpper(params.OrderType)
	side := strings.ToUpper(params.Side)

	paramsMaps := map[string]string{
		"symbol":           params.Symbol,
		"side":             side,
		"quantity":         params.Quantity.String(),
		"type":             orderType,
		"newClientOrderId": params.NewClientOrderId,
		"positionSide":     params.PositionSide,
	}

	// 设置市价和限价等类型的参数
	switch orderType {
	case "LIMIT":
		paramsMaps["price"] = params.Price.String()
		paramsMaps["timeInForce"] = "GTC"
	case "TAKE_PROFIT_MARKET":
		paramsMaps["timeInForce"] = "GTC"
		paramsMaps["stopprice"] = params.Profit.String()
		paramsMaps["workingType"] = "MARK_PRICE"
	case "TAKE_PROFIT":
		paramsMaps["price"] = params.Price.String()
		paramsMaps["stopprice"] = params.Profit.String()
		paramsMaps["timeInForce"] = "GTC"
	case "STOP_MARKET":
		paramsMaps["stopprice"] = params.StopPrice.String()
		paramsMaps["workingType"] = "MARK_PRICE"
		paramsMaps["timeInForce"] = "GTC"
	case "STOP":
		paramsMaps["price"] = params.Price.String()
		paramsMaps["stopprice"] = params.StopPrice.String()
		paramsMaps["workingType"] = "MARK_PRICE"
		paramsMaps["timeInForce"] = "GTC"
	}

	// 获取 API 信息和发送下单请求
	client := GetClient(apiUserInfo)
	_, statusCode, err := client.SendFuturesRequestAuth("/fapi/v1/order", "POST", paramsMaps)

	if err != nil {
		return parseOrderError(err, paramsMaps, statusCode, apiUserInfo)
	}
	return nil
}

// 拆出的错误解析函数
func parseOrderError(err error, paramsMaps map[string]string, statusCode int, apiUserInfo *DbModels.LineApiUser) error {
	var dataMap map[string]interface{}

	if err2 := sonic.Unmarshal([]byte(err.Error()), &dataMap); err2 == nil {
		if code, ok := dataMap["code"]; ok {
			paramsVal, _ := sonic.MarshalString(&paramsMaps)
			log.Error("下单失败 参数:", paramsVal)
			errContent := FutErrorMaps[code.(float64)]
			if errContent == "" {
				errContent = err.Error()
			}
			return fmt.Errorf("api_id:%d 交易对:%s 下单失败:%s", apiUserInfo.Id, paramsMaps["symbol"], errContent)
		}
	}

	// 特殊处理保证金不足
	if strings.Contains(err.Error(), "Margin is insufficient.") {
		return fmt.Errorf("api_id:%d 交易对:%s 下单失败:%s", apiUserInfo.Id, paramsMaps["symbol"], FutErrorMaps[-2019])
	}

	return fmt.Errorf("api_id:%d 交易对:%s statusCode:%v 下单失败:%s", apiUserInfo.Id, paramsMaps["symbol"], statusCode, err.Error())
}
