// Package config provides a generic environment-variable + .env configuration
// loader. Each application defines its own configuration struct (with
// `env:"..."` tags) and calls Load to populate it. The framework owns only the
// loading mechanism, never the schema — so the two apps can have completely
// different configuration structs while sharing this loader.
package config

import (
	"os"

	"github.com/caarlos0/env/v11"
	"github.com/joho/godotenv"
)

// Load populates dst from the process environment. A ".env" file in the working
// directory is loaded implicitly when present; passing a non-empty overrideFile
// (e.g. from a --env-file flag) loads that file instead. In either case godotenv
// never overwrites a variable already set in the real environment, so actual
// environment variables always take precedence over the file.
//
// Load returns an error rather than exiting; callers (typically a thin app-side
// wrapper) decide how to handle failure.
func Load[T any](overrideFile string, dst *T) error {
	switch {
	case overrideFile != "":
		// Explicit override: the file is required, so a missing/unreadable file
		// is an error.
		if err := godotenv.Load(overrideFile); err != nil {
			return err
		}
	default:
		// Implicitly load ".env" when it exists. Its absence is not an error —
		// the process environment may already carry everything.
		if _, err := os.Stat(".env"); err == nil {
			if err := godotenv.Load(".env"); err != nil {
				return err
			}
		}
	}

	return env.Parse(dst)
}
