package legacyid

import (
	"crypto/sha1"
	"encoding/hex"
	"errors"
	"fmt"
	"strings"
)

// Namespace is stable for the lifetime of this migration lineage. Changing it
// would generate different UUIDs for the same legacy records.
const Namespace = "e2464f95-0c8d-5a9c-9c1d-d5bca69bb09f"

// UUID returns an RFC 4122 UUIDv5 for a legacy record. SHA-1 is required by the
// UUIDv5 standard here and is not used for credentials or signatures.
func UUID(sourceSystem, entityType, legacyID string) (string, error) {
	sourceSystem = strings.TrimSpace(sourceSystem)
	entityType = strings.TrimSpace(entityType)
	legacyID = strings.TrimSpace(legacyID)
	if sourceSystem == "" || entityType == "" || legacyID == "" {
		return "", errors.New("legacy ID components must not be empty")
	}
	if len(sourceSystem) > 64 || len(entityType) > 128 || len(legacyID) > 256 {
		return "", errors.New("legacy ID component is too long")
	}
	namespace, err := hex.DecodeString(strings.ReplaceAll(Namespace, "-", ""))
	if err != nil || len(namespace) != 16 {
		return "", errors.New("invalid UUID namespace")
	}
	name := sourceSystem + "/" + entityType + "/" + legacyID
	digest := sha1.Sum(append(namespace, []byte(name)...))
	digest[6] = digest[6]&0x0f | 0x50
	digest[8] = digest[8]&0x3f | 0x80
	return fmt.Sprintf("%x-%x-%x-%x-%x", digest[0:4], digest[4:6], digest[6:8], digest[8:10], digest[10:16]), nil
}
