package jobs

import (
	"log/slog"
	"time"

	"warpbox.dev/backend/libs/config"
	"warpbox.dev/backend/libs/services"
)

func newCleanupJob(cfg config.Config, logger *slog.Logger, uploadService *services.UploadService) job {
	return job{
		name:     "cleanup",
		enabled:  cfg.CleanupEnabled,
		interval: cfg.CleanupEvery,
		run: func() {
			cleaned, err := cleanupUnavailableBoxes(uploadService, logger)
			if err != nil {
				logger.Warn("cleanup job failed", "source", "housekeeping", "severity", "warn", "code", 4202, "error", err.Error())
				return
			}
			if cleaned > 0 {
				logger.Info("cleanup job complete", "source", "housekeeping", "severity", "user_activity", "code", 2202, "cleaned", cleaned)
			}
		},
	}
}

func RunCleanupNow(uploadService *services.UploadService, logger *slog.Logger) (int, error) {
	return cleanupUnavailableBoxes(uploadService, logger)
}

func cleanupUnavailableBoxes(uploadService *services.UploadService, logger *slog.Logger) (int, error) {
	boxes, err := uploadService.ListBoxes(0)
	if err != nil {
		return 0, err
	}

	now := time.Now().UTC()
	cleaned := 0
	for _, box := range boxes {
		if !shouldDeleteBox(box, now) {
			continue
		}
		if err := uploadService.DeleteBoxWithSource(box.ID, "housekeeping"); err != nil {
			return cleaned, err
		}
		cleaned++
	}
	if cleaned > 0 {
		logger.Info("unavailable boxes cleaned", "source", "housekeeping", "severity", "user_activity", "code", 2201, "cleaned", cleaned)
	}
	return cleaned, nil
}

func shouldDeleteBox(box services.Box, now time.Time) bool {
	if !box.ExpiresAt.After(now) {
		return true
	}
	return box.MaxDownloads > 0 && box.DownloadCount >= box.MaxDownloads
}
