package jobs

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

	"quyun/app/models"
	"quyun/database/fields"
	"quyun/pkg/utils"
	"quyun/providers/app"
	"quyun/providers/job"

	"github.com/pkg/errors"
	. "github.com/riverqueue/river"
	log "github.com/sirupsen/logrus"
	_ "go.ipao.vip/atom"
	"go.ipao.vip/atom/contracts"
)

var _ contracts.JobArgs = (*VideoCut)(nil)

type VideoCut struct {
	MediaHash string `json:"media_hash"`
}

func (s VideoCut) InsertOpts() InsertOpts {
	return InsertOpts{
		Queue:    QueueDefault,
		Priority: PriorityDefault,
	}
}

func (s VideoCut) Kind() string     { return "video_cut" }
func (a VideoCut) UniqueID() string { return a.Kind() }

var _ Worker[VideoCut] = (*VideoCutWorker)(nil)

// @provider(job)
type VideoCutWorker struct {
	WorkerDefaults[VideoCut]

	job *job.Job
	app *app.Config
}

func (w *VideoCutWorker) NextRetry(job *Job[VideoCut]) time.Time {
	return time.Now().Add(30 * time.Second)
}

func (w *VideoCutWorker) Work(ctx context.Context, job *Job[VideoCut]) error {
	log := log.WithField("job", job.Args.Kind())

	log.Infof("[Start] Working on job with strings: %+v", job.Args)
	defer log.Infof("[End] Finished %s", job.Args.Kind())

	media, err := models.Medias.GetByHash(ctx, job.Args.MediaHash)
	if err != nil {
		log.Errorf("Error getting media by ID: %v", err)
		return JobCancel(err)
	}

	input := filepath.Join(w.app.StoragePath, media.Path)
	output := input[:len(input)-len(filepath.Ext(input))] + "-short" + filepath.Ext(input)

	log.Infof("cut video process %s to %s", input, output)

	if err := utils.CutMedia(input, output, 0, 60); err != nil {
		log.Errorf("Error cutting media: %v", err)
		return errors.Wrap(err, "cut media")
	}

	duration, err := utils.GetMediaDuration(input)
	if err != nil {
		log.Errorf("Error getting media duration: %v", err)
		return errors.Wrap(err, "get media duration")
	}
	// update media metas
	metas := fields.MediaMetas{
		ParentHash: "",
		Short:      false,
		Duration:   duration,
	}
	if err := models.Medias.UpdateMetas(ctx, media.ID, metas); err != nil {
		log.Errorf("Error updating media metas: %v", err)
		return errors.Wrap(err, "update media metas")
	}

	// save to database
	return w.job.Add(&VideoStoreShort{
		MediaHash: media.Hash,
		FilePath:  output,
	})
}
