package storage

import (
	"context"
	"time"

	"github.com/atlasos/calypso/internal/common/database"
	"github.com/atlasos/calypso/internal/common/logger"
)

// SnapshotScheduleWorker handles periodic execution of snapshot schedules
type SnapshotScheduleWorker struct {
	scheduleService *SnapshotScheduleService
	logger          *logger.Logger
	interval        time.Duration
	stopCh          chan struct{}
}

// NewSnapshotScheduleWorker creates a new snapshot schedule worker
func NewSnapshotScheduleWorker(db *database.DB, log *logger.Logger, snapshotService *SnapshotService, interval time.Duration) *SnapshotScheduleWorker {
	scheduleService := NewSnapshotScheduleService(db, log, snapshotService)
	return &SnapshotScheduleWorker{
		scheduleService: scheduleService,
		logger:          log,
		interval:        interval,
		stopCh:          make(chan struct{}),
	}
}

// Start starts the snapshot schedule worker background service
func (w *SnapshotScheduleWorker) Start(ctx context.Context) {
	w.logger.Info("Starting snapshot schedule worker", "interval", w.interval)
	ticker := time.NewTicker(w.interval)
	defer ticker.Stop()

	// Run initial check immediately
	w.processSchedules(ctx)

	for {
		select {
		case <-ctx.Done():
			w.logger.Info("Snapshot schedule worker stopped")
			return
		case <-w.stopCh:
			w.logger.Info("Snapshot schedule worker stopped")
			return
		case <-ticker.C:
			w.processSchedules(ctx)
		}
	}
}

// Stop stops the snapshot schedule worker service
func (w *SnapshotScheduleWorker) Stop() {
	close(w.stopCh)
}

// processSchedules processes all due snapshot schedules
func (w *SnapshotScheduleWorker) processSchedules(ctx context.Context) {
	w.logger.Debug("Checking for due snapshot schedules")

	// Get all schedules that are due to run
	schedules, err := w.scheduleService.GetDueSchedules(ctx)
	if err != nil {
		w.logger.Error("Failed to get due schedules", "error", err)
		return
	}

	if len(schedules) == 0 {
		w.logger.Debug("No snapshot schedules due to run")
		return
	}

	w.logger.Info("Found due snapshot schedules", "count", len(schedules))

	// Execute each schedule
	for _, schedule := range schedules {
		w.logger.Info("Executing snapshot schedule", "schedule", schedule.Name, "dataset", schedule.Dataset)

		if err := w.scheduleService.ExecuteSchedule(ctx, schedule); err != nil {
			w.logger.Error("Failed to execute snapshot schedule", "error", err, "schedule", schedule.Name)
			continue
		}

		w.logger.Info("Successfully executed snapshot schedule", "schedule", schedule.Name)
	}
}
