package model

import (
	"errors"
	"fmt"
)

// MaxVMNameLen is the upper bound on a user-provided VM name. DNS
// labels (RFC 1123) allow up to 63 octets; the name ends up as the
// first label of `<name>.vm` records served by banger's vmdns, and
// also as the guest's /etc/hostname — so fitting both invariants in
// a single ceiling keeps the model simple.
const MaxVMNameLen = 63

// ValidateVMName rejects names that aren't safe to use as a DNS
// label, a Linux hostname, a kernel-command-line token, or a
// file-path component. Concretely: lowercase ASCII letters, digits,
// and '-', 1..MaxVMNameLen chars, no leading or trailing hyphen.
//
// No normalization (trimming, case folding) — the VM name becomes
// the user-visible identifier (store lookup key, `ssh <name>.vm`,
// `vm show <name>`), and a silent rewrite would hand the user back
// a different name than they typed. Reject early with an explicit
// message instead.
func ValidateVMName(name string) error {
	if name == "" {
		return errors.New("vm name is required")
	}
	if len(name) > MaxVMNameLen {
		return fmt.Errorf("vm name %q is %d characters; max is %d (DNS label limit)", name, len(name), MaxVMNameLen)
	}
	if name[0] == '-' || name[len(name)-1] == '-' {
		return fmt.Errorf("vm name %q cannot start or end with '-'", name)
	}
	for i, r := range name {
		switch {
		case r >= 'a' && r <= 'z':
		case r >= '0' && r <= '9':
		case r == '-':
		default:
			return fmt.Errorf("vm name %q has invalid character %q at position %d (allowed: lowercase a-z, 0-9, '-')", name, r, i)
		}
	}
	return nil
}
