package scriptservice

import (
	"fmt"
	"go-admin/app/admin/models"
	"go-admin/app/admin/service"
	"go-admin/app/admin/service/dto"
	"go-admin/common/const/rediskey"
	"go-admin/common/helper"
	"go-admin/pkg/utility"
	"runtime/debug"
	"strings"
	"sync"

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

type PreOrder struct {
}

const GoroutineNum = 5

func (receiver *PreOrder) AddOrder(orm *gorm.DB) {
	var wg sync.WaitGroup
	for i := 1; i <= GoroutineNum; i++ {
		wg.Add(1)
		utility.SafeGo(func() {
			workerWithLock(orm, &wg)
		})
	}
	wg.Wait()
}

func workerWithLock(orm *gorm.DB, wg *sync.WaitGroup) {
	scriptId, err := helper.DefaultRedis.LPopList(rediskey.PreOrderScriptList)
	if err != nil {
		return
	}

	defer func() {
		wg.Done()
		if r := recover(); r != nil {
			// 记录 Goroutine ID、panic 信息和堆栈
			err := string(debug.Stack())
			log.Error(fmt.Sprintf("Recovered from panic in Goroutine %s: %v\nStack Trace:\n%s", utility.GetGoroutineID(), r, err))

			orm.Model(&models.LinePreScript{}).Where("id = ? ", scriptId).Updates(map[string]interface{}{
				"status": "1",
				"error":  err,
			},
			)
		}
	}()

	var scriptInfo models.LinePreScript
	err = orm.Model(&models.LinePreScript{}).Where("id = ? AND status = '0'", scriptId).Find(&scriptInfo).Error
	if err != nil {
		log.Error("获取脚本记录失败mysql err:", err)
		return
	}
	if scriptInfo.Id > 0 {
		orm.Model(&models.LinePreScript{}).Where("id = ?", scriptId).Update("status", "1")
	}

	params := scriptInfo.ScriptParams
	var batchReq dto.LineBatchAddPreOrderReq
	sonic.Unmarshal([]byte(params), &batchReq)
	errs := make([]error, 0)
	errStr := make([]string, 0)
	order := service.LinePreOrder{
		Service: sysservice.Service{Orm: orm},
	}
	order.AddBatchPreOrder(&batchReq, nil, &errs)

	if len(errs) > 0 {
		//e.Logger.Error(err)
		for _, err2 := range errs {
			errStr = append(errStr, err2.Error())
		}
		//e.Error(500, nil, strings.Join(errStr, ","))
		orm.Model(&models.LinePreScript{}).Where("id = ?", scriptId).Updates(map[string]interface{}{
			"status": "2",
			"desc":   strings.Join(errStr, ","),
		})
		return
	} else {
		orm.Model(&models.LinePreScript{}).Where("id = ?", scriptId).Updates(map[string]interface{}{
			"status": "2",
			"desc":   "执行成功",
		})
	}
	return
}
