package plan

import (
	"fmt"
	"sort"
	"strings"
)

// NormalizeTenantIDs returns a sorted copy of tenant ids and their artifact
// stems: "tenants-" plus the sanitized id (1001:0 → tenants-1001-0).
//
// The per-tenant artifact family derives from the same stem:
// tenants-<stem>.json, tenants-<stem>-status.json, tenants-<stem>.log,
// tenants-<stem>-manifest.json. It rejects duplicate ids and
// sanitize-collisions without rendering any per-tenant commands.
func NormalizeTenantIDs(realTenants []string) ([]string, []string, error) {
	normalized := append([]string(nil), realTenants...)
	sort.Strings(normalized)
	if dup, ok := firstDuplicate(normalized); ok {
		return nil, nil, fmt.Errorf("duplicate tenant: %s", dup)
	}
	stems, err := sanitizedStems(normalized)
	if err != nil {
		return nil, nil, err
	}
	for i := range stems {
		stems[i] = "tenants-" + stems[i]
	}
	return normalized, stems, nil
}

// firstDuplicate returns the first repeated element.
//
// Input must be sorted.
func firstDuplicate(sorted []string) (string, bool) {
	for i := 1; i < len(sorted); i++ {
		if sorted[i] == sorted[i-1] {
			return sorted[i], true
		}
	}
	return "", false
}

// sanitizedStems returns sanitizeTenantName(t) for each tenant, failing on the
// first collision between two distinct tenants.
//
// Input must be sorted + deduped on the real-tenant axis.
func sanitizedStems(tenants []string) ([]string, error) {
	stems := make([]string, len(tenants))
	seen := make(map[string]struct{}, len(tenants))
	for i, t := range tenants {
		stem := sanitizeTenantName(t)
		if _, ok := seen[stem]; ok {
			return nil, fmt.Errorf("tenant name collision after sanitize: stem=%s", stem)
		}
		seen[stem] = struct{}{}
		stems[i] = stem
	}
	return stems, nil
}

// tenantSanitizer replaces filename-unsafe runes (":", "/", "\\", " ") with
// "-".
//
// Package-level so repeated calls don't rebuild the replacer state.
var tenantSanitizer = strings.NewReplacer(
	":", "-",
	"/", "-",
	"\\", "-",
	" ", "-",
)

// sanitizeTenantName replaces filename-unsafe runes with "-", producing the
// id component of a NormalizeTenantIDs artifact stem.
func sanitizeTenantName(t string) string {
	return tenantSanitizer.Replace(t)
}
