package media

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"io"
	"net/http"

	"git.netflux.io/rob/clipper/generated/store"
	"github.com/google/uuid"
)

type VideoThumbnail struct {
	Data          []byte
	Width, Height int
}

func (s *MediaSetService) GetVideoThumbnail(ctx context.Context, id uuid.UUID) (VideoThumbnail, error) {
	mediaSet, err := s.store.GetMediaSet(ctx, id)
	if err != nil {
		return VideoThumbnail{}, fmt.Errorf("error getting media set: %v", err)
	}

	if mediaSet.VideoThumbnailS3UploadedAt.Valid {
		return s.getThumbnailFromFileStore(ctx, mediaSet)
	}

	return s.getThumbnailFromYoutube(ctx, mediaSet)
}

func (s *MediaSetService) getThumbnailFromFileStore(ctx context.Context, mediaSet store.MediaSet) (VideoThumbnail, error) {
	object, err := s.fileStore.GetObject(ctx, mediaSet.VideoThumbnailS3Key.String)
	if err != nil {
		return VideoThumbnail{}, fmt.Errorf("error fetching thumbnail from file store: %v", err)
	}
	defer object.Close()

	imageData, err := io.ReadAll(object)
	if err != nil {
		return VideoThumbnail{}, fmt.Errorf("error reading thumbnail from file store: %v", err)
	}

	return VideoThumbnail{
		Width:  int(mediaSet.VideoThumbnailWidth.Int32),
		Height: int(mediaSet.VideoThumbnailHeight.Int32),
		Data:   imageData,
	}, nil
}

func (s *MediaSetService) getThumbnailFromYoutube(ctx context.Context, mediaSet store.MediaSet) (VideoThumbnail, error) {
	video, err := s.youtube.GetVideoContext(ctx, mediaSet.YoutubeID)
	if err != nil {
		return VideoThumbnail{}, fmt.Errorf("error fetching video: %v", err)
	}

	if len(video.Formats) == 0 {
		return VideoThumbnail{}, errors.New("no format available")
	}

	thumbnails := video.Thumbnails
	SortYoutubeThumbnails(thumbnails)
	thumbnail := thumbnails[0]

	resp, err := http.Get(thumbnail.URL)
	if err != nil {
		return VideoThumbnail{}, fmt.Errorf("error fetching thumbnail: %v", err)
	}
	defer resp.Body.Close()

	imageData, err := io.ReadAll(resp.Body)
	if err != nil {
		return VideoThumbnail{}, fmt.Errorf("error reading thumbnail: %v", err)
	}

	// TODO: use mediaSet func to fetch key
	thumbnailKey := fmt.Sprintf("media_sets/%s/thumbnail.jpg", mediaSet.ID)

	const mimeType = "application/jpeg"
	_, err = s.fileStore.PutObject(ctx, thumbnailKey, bytes.NewReader(imageData), mimeType)
	if err != nil {
		return VideoThumbnail{}, fmt.Errorf("error uploading thumbnail: %v", err)
	}

	storeParams := store.SetVideoThumbnailUploadedParams{
		ID:                     mediaSet.ID,
		VideoThumbnailMimeType: sqlString(mimeType),
		VideoThumbnailS3Key:    sqlString(thumbnailKey),
		VideoThumbnailWidth:    sqlInt32(int32(thumbnail.Width)),
		VideoThumbnailHeight:   sqlInt32(int32(thumbnail.Height)),
	}
	if _, err := s.store.SetVideoThumbnailUploaded(ctx, storeParams); err != nil {
		return VideoThumbnail{}, fmt.Errorf("error updating media set: %v", err)
	}

	return VideoThumbnail{Width: int(thumbnail.Width), Height: int(thumbnail.Height), Data: imageData}, nil
}
