package config

import (
	"fmt"
	"math"
	"strconv"
	"strings"
)

func parseBool(value string) (bool, error) {
	switch strings.ToLower(strings.TrimSpace(value)) {
	case "1", "t", "true", "y", "yes", "on":
		return true, nil
	case "0", "f", "false", "n", "no", "off":
		return false, nil
	default:
		return false, fmt.Errorf("must be a boolean")
	}
}

func parseInt64(value string, min int64) (int64, error) {
	parsed, err := strconv.ParseInt(strings.TrimSpace(value), 10, 64)
	if err != nil {
		return 0, fmt.Errorf("must be an integer")
	}
	if parsed < min {
		return 0, fmt.Errorf("must be at least %d", min)
	}
	return parsed, nil
}

func parseInt(value string, min int) (int, error) {
	parsed64, err := parseInt64(value, int64(min))
	if err != nil {
		return 0, err
	}
	if parsed64 > int64(^uint(0)>>1) {
		return 0, fmt.Errorf("is too large")
	}
	return int(parsed64), nil
}

const bytesPerGigabyte = 1024 * 1024 * 1024

func parseGigabytes(value string, min float64) (int64, error) {
	raw := strings.TrimSpace(value)
	lower := strings.ToLower(raw)
	if strings.HasSuffix(lower, "gb") {
		raw = strings.TrimSpace(raw[:len(raw)-2])
	}
	parsed, err := strconv.ParseFloat(raw, 64)
	if err != nil {
		return 0, fmt.Errorf("must be a number of GB")
	}
	if parsed < min {
		return 0, fmt.Errorf("must be at least %s", trimTrailingZeros(min))
	}
	bytes := parsed * bytesPerGigabyte
	if bytes > math.MaxInt64 {
		return 0, fmt.Errorf("is too large")
	}
	return int64(math.Round(bytes)), nil
}

func formatGigabytesFromBytes(bytes int64) string {
	if bytes <= 0 {
		return "0"
	}
	value := float64(bytes) / bytesPerGigabyte
	return trimTrailingZeros(value)
}

func trimTrailingZeros(value float64) string {
	text := strconv.FormatFloat(value, 'f', 3, 64)
	text = strings.TrimRight(text, "0")
	text = strings.TrimRight(text, ".")
	if text == "" {
		return "0"
	}
	return text
}

func formatBool(value bool) string {
	if value {
		return "true"
	}
	return "false"
}
