package serverinit

import (
	"fmt"
	"go-admin/app/admin/models"
	"go-admin/app/admin/service"
	"go-admin/common/const/rediskey"
	"go-admin/common/helper"
	"go-admin/config"
	"go-admin/pkg/httputils"
	"go-admin/services/binanceservice"
	"go-admin/services/cacheservice"
	"go-admin/services/futureservice"
	"go-admin/services/scriptservice"
	"os"
	"time"

	"github.com/bytedance/sonic"
	"github.com/go-admin-team/go-admin-core/logger"
	"github.com/go-admin-team/go-admin-core/sdk"
	"github.com/robfig/cron/v3"
	"gorm.io/gorm"
)

// 业务初始化
func BusinessInit(db *gorm.DB) {
	httputils.InitProxy(config.ExtConfig.ProxyUrl)

	if err := loadApiUser(db); err != nil { //加载api用户
		os.Exit(-1)
	}

	lineApiService := service.LineApiUser{}
	lineApiService.Orm = db
	lineApiService.Log = logger.NewHelper(sdk.Runtime.GetLogger()).WithFields(map[string]interface{}{})

	if err := lineApiService.CacheRelation(); err != nil {
		lineApiService.Log.Errorf("初始化api关系失败 err:%v", err)
		os.Exit(-1)
	}

	reverseSettingService := service.LineReverseSetting{}
	reverseSettingService.Orm = db
	reverseSettingService.Log = lineApiService.Log

	if err := reverseSettingService.SaveCache(models.LineReverseSetting{}); err != nil {
		reverseSettingService.Log.Errorf("初始化反单设置失败 err:%v", err)
		os.Exit(-1)
	}

	//初始化参数配置
	cacheservice.InitConfigCache(db)
	//初始化可缓存价格交易对
	symbolPriceService := service.LineSymbolPrice{}
	symbolPriceService.Orm = db
	symbolPriceService.Log = logger.NewHelper(sdk.Runtime.GetLogger()).WithFields(map[string]interface{}{})
	symbolPriceService.InitCache()

	//清理交易对缓存价格
	clearSymbolPrice()

	//初始化订单配置
	cacheservice.ResetSystemSetting(db)
	lineApiUser := service.LineApiUser{}
	lineApiUser.Orm = db
	if err := lineApiUser.InitCache(); err != nil {
		logger.Errorf("初始化api用户失败:%v", err)
		os.Exit(-1)
	}

	//币安 现货交易对
	SpotCurrencyInit()
	//币安 合约交易对
	FuturesInit()

	//第一次初始化交易对价格
	spotApi := binanceservice.SpotRestApi{}
	futApi := binanceservice.FutRestApi{}
	spotApi.Ticker()
	futApi.Ticker()

	//现货 订阅
	SpotSubscribeInit("normal")
	//合约订阅
	futureservice.StartBinanceProWs("normal")
	//定时任务
	RunSpotJobs(db)
}

// 开启现货ws监听
func SpotWsInit() {
	//启动websocket服务
	//go func() {
	//	err := wsservice.StartServer(":3333")
	//	if err != nil {
	//		log.Info("wsservice.StartServer", zap.Error(err))
	//
	//		_, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	//		cancel()
	//	}
	//}()
}

// 定义任务
func RunSpotJobs(db *gorm.DB) {
	cronJob := cron.New()
	//添加任务 同步交易对行情
	// spotApi := spotservice.SpotRestApi{}
	// futApi := futureservice.FutRestApi{}
	// _, err := cronJob.AddFunc("@every 10s", func() {
	// 	//BuySellOrderNew(db)
	// spotApi.Ticker()
	// futApi.Ticker()
	// })
	// if err != nil {
	// 	return
	// }

	//定时执行脚本任务
	_, err := cronJob.AddFunc("@every 3s", func() {
		order := scriptservice.PreOrder{}
		order.AddOrder(db)
	})
	if err != nil {
		return
	}

	//启动
	cronJob.Start()
}

/*
加载api user
*/
func loadApiUser(db *gorm.DB) error {
	users := make([]models.LineApiUser, 0)

	if err := db.Model(&models.LineApiUser{}).Where("open_status =1").Find(&users).Error; err != nil {
		logger.Error("loadApiUser：", err)
		return err
	}

	for _, user := range users {
		key := fmt.Sprintf(rediskey.API_USER, user.Id)
		val, _ := sonic.MarshalString(&user)

		if val != "" {
			if err := helper.DefaultRedis.SetString(key, val); err != nil {
				logger.Error("loadApiUser 保存redis：", err)
			}
		}
	}

	groups := make([]models.LineApiGroup, 0)

	if err := db.Model(&models.LineApiGroup{}).Find(&groups).Error; err != nil {
		logger.Error("loadApiGroup：", err)
		return err
	}

	apiGroupService := service.LineApiGroup{}
	apiGroupService.Log = logger.NewHelper(sdk.Runtime.GetLogger()).WithFields(map[string]interface{}{})

	for _, group := range groups {
		service.SetApiGroupCache(group)
	}

	return nil
}

// 清理交易对价格缓存
func clearSymbolPrice() error {
	spotAll, _ := helper.DefaultRedis.ScanKeys("spot_ticker_last_price:*")
	futAllKey, _ := helper.DefaultRedis.ScanKeys("fut_ticker_last_price:*")
	beforeTimeUtc := time.Now().UnixMilli()

	for _, item := range spotAll {
		if _, err := helper.DefaultRedis.RemoveBeforeScore(item, float64(beforeTimeUtc)); err != nil {
			logger.Error("现货 清理交易对价格缓存失败：", err)
		}
	}

	for _, item := range futAllKey {
		if _, err := helper.DefaultRedis.RemoveBeforeScore(item, float64(beforeTimeUtc)); err != nil {
			logger.Error("合约 清理交易对价格缓存失败：", err)
		}
	}

	return nil
}
