package managed_resources //nolint:staticcheck

import (
	"fmt"
	"html/template"
	"regexp"
	"strings"
)

// rendererFuncMap a list of functions to use when rendering templates.
// The functions must be deterministic.
var rendererFuncMap = template.FuncMap{
	"lower":      strings.ToLower,
	"substr":     substr,
	"replace":    replace,
	"trimSuffix": trimSuffix,
	"trimPrefix": trimPrefix,
	"slugify":    slugify,
}

func substr(start, end int, s string) string {
	if start < 0 {
		return s[:end]
	}

	if end < 0 || end > len(s) {
		return s[start:]
	}

	return s[start:end]
}

func replace(o, n, s string) string {
	return strings.ReplaceAll(s, o, n)
}

func trimSuffix(suffix, s string) string {
	return strings.TrimSuffix(s, suffix)
}

func trimPrefix(prefix, s string) string {
	return strings.TrimPrefix(s, prefix)
}

var (
	// invalidCharsRegex matches any character that is not a letter, digit, or hyphen
	invalidCharsRegex = regexp.MustCompile(`[^a-z0-9-]`)
)

func slugify(args ...any) (string, error) {
	var s string
	cutOffLen := 63

	switch len(args) {
	case 1:
		s = fmt.Sprint(args[0])
	case 2:
		// We must have a pair of (length, string) when used as {{ string | slugify length }}
		var ok bool
		cutOffLen, ok = args[0].(int)
		if !ok || cutOffLen < 0 {
			return "", fmt.Errorf("the first argument passed to slugify must be a positive or zero integer that specifies the cut off position")
		}
		s = fmt.Sprint(args[1])
	}

	// Convert to lowercase
	result := strings.ToLower(s)

	// Replace invalid characters with hyphens
	result = invalidCharsRegex.ReplaceAllString(result, "-")

	// Trim leading and trailing hyphens
	result = strings.Trim(result, "-")

	// Trim to cut-off length
	if cutOffLen > 0 && len(result) > cutOffLen {
		result = result[:cutOffLen]
		// Ensure we don't end with a hyphen after truncation
		result = strings.TrimRight(result, "-")
	}

	return result, nil
}
