package service

import (
	"context"
	"log"
	"sync"
	"time"

	"github.com/jackc/pgx/v5/pgxpool"
)

// CronJob defines a scheduled task.
type CronJob struct {
	Name     string
	Interval time.Duration
	Handler  func(ctx context.Context, pool *pgxpool.Pool) error
	running  bool
}

// CronScheduler manages periodic jobs.
type CronScheduler struct {
	jobs   []*CronJob
	mu     sync.Mutex
	ctx    context.Context
	cancel context.CancelFunc
}

// NewCronScheduler creates a new scheduler.
func NewCronScheduler() *CronScheduler {
	ctx, cancel := context.WithCancel(context.Background())
	return &CronScheduler{ctx: ctx, cancel: cancel}
}

// Register adds a job to the scheduler.
func (s *CronScheduler) Register(job *CronJob) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.jobs = append(s.jobs, job)
}

// Start begins running all registered jobs.
func (s *CronScheduler) Start(pool *pgxpool.Pool) {
	for _, job := range s.jobs {
		go s.runJob(job, pool)
	}
	log.Printf("cron: started %d jobs", len(s.jobs))
}

// Stop cancels all running jobs.
func (s *CronScheduler) Stop() {
	s.cancel()
}

func (s *CronScheduler) runJob(job *CronJob, pool *pgxpool.Pool) {
	ticker := time.NewTicker(job.Interval)
	defer ticker.Stop()

	for {
		select {
		case <-s.ctx.Done():
			return
		case <-ticker.C:
			if err := job.Handler(s.ctx, pool); err != nil {
				log.Printf("cron: %s error: %v", job.Name, err)
			}
		}
	}
}
