package worker

import (
	"context"
	"log/slog"
	"os"
	"path/filepath"
	"time"

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

type SubtitleSearchWorker struct {
	database    *db.DB
	subtitleSvc *service.SubtitleService
	cfg         *config.Config
}

func NewSubtitleSearchWorker(database *db.DB, subtitleSvc *service.SubtitleService, cfg *config.Config) *SubtitleSearchWorker {
	return &SubtitleSearchWorker{
		database:    database,
		subtitleSvc: subtitleSvc,
		cfg:         cfg,
	}
}

func (w *SubtitleSearchWorker) Name() string {
	return "subtitle_search"
}

func (w *SubtitleSearchWorker) CronExpr() string {
	return w.cfg.WorkerSubtitleInterval
}

func (w *SubtitleSearchWorker) Run(ctx context.Context) error {
	ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
	defer cancel()

	searched := 0
	downloaded := 0
	errors := 0

	rows, err := w.database.Pool.Query(ctx,
		`SELECT m.id, m.media_type, m.title, mf.path
		 FROM media m
		 JOIN media_files mf ON m.id = mf.media_id AND mf.deleted_at IS NULL
		 WHERE m.deleted_at IS NULL AND m.status = 'available'
		 ORDER BY m.id`)
	if err != nil {
		return err
	}
	defer rows.Close()

	type mediaFile struct {
		mediaID   int64
		mediaType string
		title     string
		path      string
	}

	var files []mediaFile
	for rows.Next() {
		var f mediaFile
		if err := rows.Scan(&f.mediaID, &f.mediaType, &f.title, &f.path); err != nil {
			slog.Error("failed to scan media file", "error", err)
			continue
		}
		files = append(files, f)
	}

	for _, f := range files {
		ext := filepath.Ext(f.path)
		basePath := f.path[:len(f.path)-len(ext)]
		srtPath := basePath + ".eng.srt"
		sdhPath := basePath + ".eng.sdh.srt"

		if _, err := os.Stat(srtPath); err == nil {
			continue
		}
		if _, err := os.Stat(sdhPath); err == nil {
			continue
		}

		results, err := w.subtitleSvc.Search(ctx, f.title, service.SubtitleSearchOptions{
			LanguageCodes: []string{"eng"},
		})
		if err != nil {
			slog.Error("failed to search subtitles", "media_id", f.mediaID, "error", err)
			errors++
			continue
		}
		searched++

		if len(results) == 0 {
			continue
		}

		baseName := filepath.Base(basePath)
		_, err = w.subtitleSvc.Download(ctx, results[0].ID, filepath.Dir(f.path), baseName, results[0].LanguageCode, results[0].HI, results[0].Forced)
		if err != nil {
			slog.Error("failed to download subtitle", "media_id", f.mediaID, "error", err)
			errors++
			continue
		}
		downloaded++
	}

	slog.Info("subtitle search completed", "searched", searched, "downloaded", downloaded, "errors", errors)
	return nil
}
