package config

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"sync"

	"github.com/joho/godotenv"
	"github.com/labstack/gommon/log"
)

// Config holds all application configuration
type Config struct {
	Database struct {
		Host     string
		Port     int
		User     string
		Password string
		DBName   string
		SSLMode  string
	}

	Images struct {
		Enabled         bool
		ConcurrentLimit int
		Path            string
	}
	Videos struct {
		Enabled         bool
		ConcurrentLimit int
		Path            string
	}
	Storage struct {
		Endpoint string
		Token    string
	}

	Server struct {
		Port int
	}
}

var (
	Cfg  Config
	once sync.Once
)

// Load initializes configuration once
func Load() *Config {

	once.Do(func() {
		// Try loading from .env file first
		_ = godotenv.Load()

		pwd, err := os.Getwd()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		// Database config
		Cfg.Database.Host = getEnv("PGHOST", "localhost")
		Cfg.Database.Port = getEnvAsInt("PGPORT", 5432)
		Cfg.Database.User = getEnv("POSTGRES_USER", "postgres")
		Cfg.Database.Password = getEnv("POSTGRES_PASSWORD", "")
		Cfg.Database.DBName = getEnv("POSTGRES_DB", "postgres")
		Cfg.Database.SSLMode = getEnv("PGSSLMODE", "true")

		// Image processing config
		Cfg.Images.Enabled = getEnvAsBool("IMAGEOPTION", true)
		Cfg.Images.ConcurrentLimit = getEnvAsInt("CONCURRENT_IMAGES", 5)
		Cfg.Images.Path = filepath.Join(pwd, "images")

		// Video processing config
		Cfg.Videos.Enabled = getEnvAsBool("VIDEOOPTION", true)
		Cfg.Videos.ConcurrentLimit = getEnvAsInt("CONCURRENT_VIDEOS", 2)
		Cfg.Videos.Path = filepath.Join(pwd, "videos")

		// Storage config
		Cfg.Storage.Endpoint = getEnv("STORAGE_URL", "")
		Cfg.Storage.Token = getEnv("STORAGE_TOKEN", "")

		// Server config
		Cfg.Server.Port = getEnvAsInt("PORT", 1323)

		// Validate required config
		if Cfg.Database.Password == "" {
			fmt.Printf("required environment variable POSTGRES_PASSWORD not set\n")
		}
	})

	if err := exec.Command("ffmpeg", "-version").Run(); err != nil {
		log.Errorf("FFmpeg not found: %v", err)
		Cfg.Videos.Enabled = false
	}

	return &Cfg
}

// Helper functions
func getEnv(key, fallback string) string {
	if value, exists := os.LookupEnv(key); exists {
		return value
	}
	return fallback
}

func getEnvAsInt(key string, fallback int) int {
	if strValue := getEnv(key, ""); strValue != "" {
		if value, err := strconv.Atoi(strValue); err == nil {
			return value
		}
	}
	return fallback
}

func getEnvAsBool(key string, fallback bool) bool {
	if strValue := getEnv(key, ""); strValue != "" {
		if value, err := strconv.ParseBool(strValue); err == nil {
			return value
		}
	}
	return fallback
}
