package jobs

import (
	"context"
	"os/exec"
	"path/filepath"
	"time"

	"quyun/v2/app/jobs/args"
	"quyun/v2/database/models"
	"quyun/v2/pkg/consts"
	"quyun/v2/providers/storage"

	"github.com/riverqueue/river"
	log "github.com/sirupsen/logrus"
)

// @provider(job)
type MediaProcessWorker struct {
	river.WorkerDefaults[args.MediaProcessArgs]
	storage *storage.Storage
}

func (j *MediaProcessWorker) Work(ctx context.Context, job *river.Job[args.MediaProcessArgs]) error {
	arg := job.Args
	// 1. Fetch Asset
	asset, err := models.MediaAssetQuery.WithContext(ctx).Where(models.MediaAssetQuery.ID.Eq(arg.AssetID)).First()
	if err != nil {
		return err
	}

	// 2. Update status to processing
	_, err = models.MediaAssetQuery.WithContext(ctx).
		Where(models.MediaAssetQuery.ID.Eq(asset.ID)).
		UpdateSimple(models.MediaAssetQuery.Status.Value(consts.MediaAssetStatusProcessing))
	if err != nil {
		return err
	}

	// 3. Process Video (FFmpeg)
	if asset.Type == consts.MediaAssetTypeVideo {
		if _, err := exec.LookPath("ffmpeg"); err == nil {
			localPath := j.storage.Config.LocalPath
			if localPath == "" {
				localPath = "./storage"
			}
			inputFile := filepath.Join(localPath, asset.ObjectKey)
			outputDir := filepath.Dir(inputFile)
			// Simple transcoding: convert to MP4 (mocking complex HLS for simplicity)
			// Or just extract cover
			coverKey := asset.ObjectKey + ".jpg"
			coverFile := filepath.Join(outputDir, filepath.Base(coverKey))

			// Generate Cover
			cmd := exec.CommandContext(
				ctx,
				"ffmpeg",
				"-y",
				"-i",
				inputFile,
				"-ss",
				"00:00:01.000",
				"-vframes",
				"1",
				coverFile,
			)
			if out, err := cmd.CombinedOutput(); err != nil {
				log.Errorf("ffmpeg failed: %s, output: %s", err, string(out))
				// Don't fail the job, just skip cover
			} else {
				log.Infof("Generated cover: %s", coverFile)
				// TODO: Create MediaAsset for cover? Or update meta?
			}
		} else {
			log.Warn("ffmpeg not found, skipping real transcoding")
		}
	}

	// 4. Update status to ready
	_, err = models.MediaAssetQuery.WithContext(ctx).
		Where(models.MediaAssetQuery.ID.Eq(asset.ID)).
		Updates(&models.MediaAsset{
			Status:    consts.MediaAssetStatusReady,
			UpdatedAt: time.Now(),
		})
	return err
}
