package controller

import (
	"crypto/sha1"
	"encoding/hex"
	"regexp"
	"strings"
)

const (
	// maxObjectName is the DNS-1123 subdomain limit for Kubernetes object names.
	maxObjectName = 253
	// maxBucketName is the DNS-1123 label limit RGW enforces on S3 bucket names.
	maxBucketName = 63
	namePrefix    = "autobk"
)

var invalidNameChars = regexp.MustCompile(`[^a-z0-9-]+`)

// bucketName derives the namespace-scoped, globally-unique S3 bucket name (and
// the Bucket CR name) for an annotated object, clamped to the 63-char RGW limit.
func bucketName(namespace, obj string) string {
	return boundedName(maxBucketName, namePrefix, namespace, obj)
}

// userName, accessName, credSecretName, resticSecretName and scheduleName derive
// the per-object child resource names. These are namespaced objects, so the
// namespace is not part of the name (only uniqueness within the namespace is
// required).
func userName(obj string) string       { return boundedName(maxObjectName, namePrefix, obj, "owner") }
func accessName(obj string) string     { return boundedName(maxObjectName, namePrefix, obj, "rw") }
func credSecretName(obj string) string { return boundedName(maxObjectName, obj, "autobackup", "rgw") }
func resticSecretName(obj string) string {
	return boundedName(maxObjectName, obj, "autobackup", "restic")
}
func scheduleName(obj string) string { return boundedName(maxObjectName, obj, "autobackup") }

// boundedName joins parts with "-", sanitises to a DNS-safe token and, when the
// result would exceed max, truncates it and appends a short deterministic hash
// of the full joined value so long inputs stay unique and within limits.
func boundedName(max int, parts ...string) string {
	joined := strings.Join(parts, "-")
	s := sanitizeName(joined)
	if len(s) <= max {
		return s
	}
	sum := sha1.Sum([]byte(joined))
	h := hex.EncodeToString(sum[:])[:8]
	keep := max - len(h) - 1
	if keep < 1 {
		return h[:max]
	}
	return strings.TrimRight(s[:keep], "-") + "-" + h
}

func sanitizeName(s string) string {
	s = strings.ToLower(s)
	s = invalidNameChars.ReplaceAllString(s, "-")
	s = strings.Trim(s, "-")
	if s == "" {
		return namePrefix
	}
	return s
}
