package worker

import (
	"context"
	"fmt"
	"log/slog"
	"syscall"

	"github.com/TopherMayor/unified-media-manager/internal/config"
	"github.com/TopherMayor/unified-media-manager/internal/db"
)

type DiskUsageWorker struct {
	database *db.DB
	cfg      *config.Config
}

func NewDiskUsageWorker(database *db.DB, cfg *config.Config) *DiskUsageWorker {
	return &DiskUsageWorker{
		database: database,
		cfg:      cfg,
	}
}

func (w *DiskUsageWorker) Name() string {
	return "disk_usage"
}

func (w *DiskUsageWorker) CronExpr() string {
	return w.cfg.WorkerDiskUsageInterval
}

func (w *DiskUsageWorker) Run(ctx context.Context) error {
	rows, err := w.database.Pool.Query(ctx, "SELECT id, path FROM root_folders")
	if err != nil {
		return fmt.Errorf("query root folders: %w", err)
	}
	defer rows.Close()

	updated := 0
	for rows.Next() {
		var id int64
		var path string
		if err := rows.Scan(&id, &path); err != nil {
			slog.Error("failed to scan root folder", "error", err)
			continue
		}

		var stat syscall.Statfs_t
		if err := syscall.Statfs(path, &stat); err != nil {
			slog.Error("failed to stat filesystem", "path", path, "error", err)
			continue
		}

		freeSpace := int64(stat.Bavail) * int64(stat.Bsize)

		_, err := w.database.Pool.Exec(ctx,
			"UPDATE root_folders SET free_space = $1 WHERE id = $2",
			freeSpace, id)
		if err != nil {
			slog.Error("failed to update free space", "id", id, "error", err)
			continue
		}
		updated++
	}

	slog.Info("disk usage updated", "folders_updated", updated)
	return nil
}
