package sqlx

import "strings"

// snakeCase converts a given string to a friendly snake case, e.g.
// - userId to user_id
// - ID     to id
// - ProviderAPIKey to provider_api_key
// - Option to option
func snakeCase(camel string) string {
	var (
		b            strings.Builder
		prevWasUpper bool
	)

	for i, c := range camel {
		if isUppercase(c) { // it's upper.
			if b.Len() > 0 && !prevWasUpper { // it's not the first and the previous was not uppercased too (e.g  "ID").
				b.WriteRune('_')
			} else { // check for XxxAPIKey, it should be written as xxx_api_key.
				next := i + 1
				if next > 1 && len(camel)-1 > next {
					if !isUppercase(rune(camel[next])) {
						b.WriteRune('_')
					}
				}
			}

			b.WriteRune(c - 'A' + 'a') // write its lowercase version.
			prevWasUpper = true
		} else {
			b.WriteRune(c) // write it as it is, it's already lowercased.
			prevWasUpper = false
		}
	}

	return b.String()
}

func isUppercase(c rune) bool {
	return 'A' <= c && c <= 'Z'
}