package worker

import (
	"context"
	"time"
)

type Job interface {
	Name() string
	Run(context.Context) error
}

type Logger func(format string, args ...any)

type Runner struct {
	jobs     []Job
	interval time.Duration
	logger   Logger
}

func NewRunner(jobs []Job, interval time.Duration, logger Logger) *Runner {
	return &Runner{
		jobs:     append([]Job(nil), jobs...),
		interval: interval,
		logger:   logger,
	}
}

func (r *Runner) Start(ctx context.Context) {
	if r == nil {
		return
	}
	go func() {
		r.runOnce(ctx)
		if ctx.Err() != nil || r.interval <= 0 {
			return
		}

		ticker := time.NewTicker(r.interval)
		defer ticker.Stop()

		for {
			select {
			case <-ctx.Done():
				return
			case <-ticker.C:
				r.runOnce(ctx)
			}
		}
	}()
}

func (r *Runner) runOnce(ctx context.Context) {
	for _, job := range r.jobs {
		if ctx.Err() != nil {
			return
		}
		if job == nil {
			continue
		}
		if err := job.Run(ctx); err != nil && ctx.Err() == nil && r.logger != nil {
			r.logger("%s: %v", job.Name(), err)
		}
	}
}
