package main

import (
	"context"
	"log"
	"time"

	"git.netflux.io/rob/clipper/config"
	"git.netflux.io/rob/clipper/filestore"
	"git.netflux.io/rob/clipper/generated/store"
	"git.netflux.io/rob/clipper/media"
	"git.netflux.io/rob/clipper/server"
	awsconfig "github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/credentials"
	"github.com/aws/aws-sdk-go-v2/service/s3"
	"github.com/jackc/pgx/v4/pgxpool"
	"github.com/kkdai/youtube/v2"
	"go.uber.org/zap"
)

const (
	defaultTimeout         = 600 * time.Second
	defaultURLExpiry       = time.Hour
	maximumWorkerQueueSize = 32
)

func main() {
	ctx := context.Background()

	config, err := config.NewFromEnv()
	if err != nil {
		log.Fatalf("error loading config: %v", err)
	}

	// Create a store
	dbConn, err := pgxpool.Connect(ctx, config.DatabaseURL)
	if err != nil {
		log.Fatal(err)
	}
	store := store.New(dbConn)

	// Create a Youtube client
	var youtubeClient youtube.Client

	// Create a logger
	logger, err := buildLogger(config)
	if err != nil {
		log.Fatal(err)
	}
	defer logger.Sync()

	// Create a file store
	fileStore, err := buildFileStore(ctx, config, logger)
	if err != nil {
		log.Fatal(err)
	}

	// Create a worker pool
	wp := media.NewWorkerPool(config.FFmpegWorkerPoolSize, maximumWorkerQueueSize, logger.Sugar().Named("FFmpegWorkerPool"))
	wp.Run()

	log.Fatal(server.Start(server.Options{
		Config:        config,
		Timeout:       defaultTimeout,
		Store:         store,
		YoutubeClient: &youtubeClient,
		FileStore:     fileStore,
		WorkerPool:    wp,
		Logger:        logger,
	}))
}

func buildLogger(c config.Config) (*zap.Logger, error) {
	if c.Environment == config.EnvDevelopment {
		return zap.NewDevelopment()
	}
	return zap.NewProduction()
}

func buildFileStore(ctx context.Context, c config.Config, logger *zap.Logger) (media.FileStore, error) {
	if c.FileStore == config.S3Store {
		logger.Info("Initializing S3 store")
		// Create an Amazon S3 service s3Client
		cfg, err := awsconfig.LoadDefaultConfig(
			ctx,
			awsconfig.WithCredentialsProvider(
				credentials.NewStaticCredentialsProvider(c.AWSAccessKeyID, c.AWSSecretAccessKey, ""),
			),
			awsconfig.WithRegion(c.AWSRegion),
		)
		if err != nil {
			log.Fatal(err)
		}
		s3Client := s3.NewFromConfig(cfg)
		s3PresignClient := s3.NewPresignClient(s3Client)

		// Create a file store
		return filestore.NewS3FileStore(
			filestore.S3API{
				S3Client:        s3Client,
				S3PresignClient: s3PresignClient,
			},
			c.S3Bucket,
			defaultURLExpiry,
			logger.Sugar().Named("filestore"),
		), nil
	}

	logger.Info("Initializing file sysytem store")
	return filestore.NewFileSystemStore(c.FileStoreHTTPRoot, c.FileStoreHTTPBaseURL)
}
