package cron

import (
	"fmt"
	"github.com/UpmeshLTD/urus-aio/cronjob/config"
	logger "github.com/UpmeshLTD/urus-aio/cronjob/log"
	"github.com/UpmeshLTD/urus-aio/cronjob/service"
	"github.com/robfig/cron/v3"
	"log"
	"sync"
	"time"
)

//go:generate mockery --name=Server --inpackage --case=snake
type Server interface {
	Serve() error
}

type serverImpl struct {
	config  config.Config
	logger  logger.Logger
	service service.Service
	cron    *cron.Cron
}

func NewServer(
	config config.Config,
	logger logger.Logger,
	service service.Service,
) Server {
	return &serverImpl{
		config:  config,
		logger:  logger,
		service: service,
		cron:    cron.New(),
	}
}

func (i *serverImpl) Serve() error {
	log.Printf(" 🚀 Cronjob service started")
	i.registerJobs()
	i.cron.Start()
	return nil
}

func (i *serverImpl) addJob(name, schedule string, lock bool, callback func()) {
	var mutex sync.Mutex
	_, err := i.cron.AddFunc(schedule, func() {
		if lock {
			mutex.Lock()
			defer mutex.Unlock()
		}
		log.Printf("Start: %s\n", name)
		t := time.Now()
		callback()
		log.Printf("End: %s (%s)\n", name, time.Now().Sub(t))
	})
	if err != nil {
		panic(err)
	}
	log.Printf("Cronjob `%s` has been schedule for %s", name, schedule)
}

func (i *serverImpl) registerJobs() {
	schedule := fmt.Sprintf("@every %dm", i.config.GetCronjobConfig().SyncCourierShipmentStatusInterval)
	i.addJob("SyncCourierShipmentStatusKerryExpressTH", schedule, true, i.service.SyncCourierShipmentStatusKerryExpressTH)
}
