// Package config provides shared config loading and environment override helpers.
package config

import (
	"errors"
	"os"
	"strconv"
	"strings"
	"time"

	"hyapp/pkg/configx"
)

// Validator lets a service config enforce cross-field invariants after file and env overrides are applied.
type Validator interface {
	Validate() error
}

// LoadYAML loads YAML into out and calls Validate when the target config implements Validator.
func LoadYAML(path string, out any) error {
	if strings.TrimSpace(path) == "" {
		return errors.New("config path is required")
	}
	if out == nil {
		return errors.New("config target is required")
	}
	if err := configx.LoadYAML(path, out); err != nil {
		return err
	}
	if validator, ok := out.(Validator); ok {
		return validator.Validate()
	}
	return nil
}

// OverrideStringFromEnv replaces target when envName exists and is not blank.
func OverrideStringFromEnv(target *string, envName string) {
	if target == nil || strings.TrimSpace(envName) == "" {
		return
	}
	if value, ok := os.LookupEnv(envName); ok && strings.TrimSpace(value) != "" {
		*target = strings.TrimSpace(value)
	}
}

// OverrideBoolFromEnv parses a bool environment value into target when envName exists.
func OverrideBoolFromEnv(target *bool, envName string) error {
	if target == nil || strings.TrimSpace(envName) == "" {
		return nil
	}
	value, ok := os.LookupEnv(envName)
	if !ok || strings.TrimSpace(value) == "" {
		return nil
	}
	parsed, err := strconv.ParseBool(strings.TrimSpace(value))
	if err != nil {
		return err
	}
	*target = parsed
	return nil
}

// OverrideDurationFromEnv parses a Go duration environment value into target when envName exists.
func OverrideDurationFromEnv(target *time.Duration, envName string) error {
	if target == nil || strings.TrimSpace(envName) == "" {
		return nil
	}
	value, ok := os.LookupEnv(envName)
	if !ok || strings.TrimSpace(value) == "" {
		return nil
	}
	parsed, err := time.ParseDuration(strings.TrimSpace(value))
	if err != nil {
		return err
	}
	*target = parsed
	return nil
}
