package cron

import (
	"context"
	"sync"

	"mini-chat/internal/pkg/errors"
	"mini-chat/internal/pkg/logger"
	"mini-chat/internal/repository/mysql"

	"github.com/jakecoffman/cron"
)

var _ Server = (*server)(nil)

type taskCount struct {
	wg   sync.WaitGroup
	exit chan struct{}
}

func (tc *taskCount) i() {}

func (tc *taskCount) Add() {
	tc.wg.Add(1)
}

func (tc *taskCount) Done() {
	tc.wg.Done()
}

func (tc *taskCount) Exit() {
	tc.wg.Done()
	<-tc.exit
}

func (tc *taskCount) Wait() {
	tc.Add()
	tc.wg.Wait()
	close(tc.exit)
}

type server struct {
	logger      logger.CustomLogger
	db          mysql.Repo
	cron        *cron.Cron
	taskCount   *taskCount
	taskContext map[string]context.CancelFunc // 存储任务的取消上下文
	mu          sync.Mutex                    // 保护 taskContext 的互斥
}

type Server interface {
	i()

	// Start 启动 cron 服务
	Start()

	// Stop 停止 cron 服务
	Stop()

	// AddTask 增加定时任务
	AddTask()

	// AddJob 增加定时任务执行的工作内容
	AddJob() cron.FuncJob

	// StopJob 停止定时任务
	StopJob(taskCode string)

	// RemoveTask 删除定时任务
	RemoveTask(taskCode string)

	Entries() []*cron.Entry
}

func New(logger logger.CustomLogger, db mysql.Repo) (Server, error) {
	if logger == nil {
		return nil, errors.New("logger required")
	}

	return &server{
		logger: logger,
		cron:   cron.New(),
		db:     db,
		taskCount: &taskCount{
			wg:   sync.WaitGroup{},
			exit: make(chan struct{}),
		},
		taskContext: make(map[string]context.CancelFunc),
	}, nil
}

func (s *server) i() {}

func (s *server) Entries() []*cron.Entry {
	return s.cron.Entries()
}
