package mru

import (
	"sync"

	"github.com/nexuscrm/shared/pkg/salesforce"
)

// IDRegistry provides ID-to-ObjectType resolution using Salesforce keyPrefix patterns
// This enables Salesforce v63.0 compliance by eliminating the need for explicit type hints

var (
	// keyPrefixMutex protects keyPrefixToObject for concurrent access
	keyPrefixMutex sync.RWMutex

	// keyPrefixToObject maps Salesforce key prefixes (first 3 chars of ID) to object API names
	// IMPORTANT: These are loaded dynamically from _System_Object metadata at startup.
	// The registry is seeded with canonical Salesforce standard-object prefixes
	// and may be extended or overridden from metadata at startup.
	keyPrefixToObject = salesforce.StandardKeyPrefixToObjectMap()

	// objectToKeyPrefix is the INVERTED map: object API name -> key prefix
	// Used by GetKeyPrefix for Salesforce v63.0 describe responses
	// IMPORTANT: Seeded from canonical Salesforce standard objects, then
	// populated dynamically from metadata at startup.
	objectToKeyPrefix = salesforce.StandardObjectToKeyPrefixMap()
)

// ResolveTypeFromID attempts to resolve the object type from a Salesforce-style record ID
// Returns the object API name and true if resolved, empty string and false otherwise
// Thread-safe via RWMutex
func ResolveTypeFromID(recordID string) (string, bool) {
	if len(recordID) < 3 {
		return "", false
	}

	prefix := recordID[:3]

	keyPrefixMutex.RLock()
	defer keyPrefixMutex.RUnlock()

	// Check exact 3-char prefix first
	if objType, ok := keyPrefixToObject[prefix]; ok {
		return objType, true
	}

	// Check 2-char prefix for custom objects (a0, a1, etc.)
	if len(prefix) >= 2 {
		prefix2 := prefix[:2]
		if objType, ok := keyPrefixToObject[prefix2]; ok {
			return objType, true
		}
	}

	// Unknown prefix - could be a custom object with non-standard prefix
	return "", false
}

// GetKeyPrefix returns the standard 3-character key prefix for an object
// This is the SSoT for keyPrefix lookup - used by all handlers
// Thread-safe via RWMutex
func GetKeyPrefix(objectAPIName string) string {
	keyPrefixMutex.RLock()
	defer keyPrefixMutex.RUnlock()

	if prefix, ok := objectToKeyPrefix[objectAPIName]; ok {
		return prefix
	}

	// No fallback: keyPrefix must come from registered metadata.
	// Salesforce returns null for keyPrefix when not available.
	return ""
}

// RegisterKeyPrefix allows dynamic registration of custom object prefixes
// This should be called during metadata initialization
// Thread-safe via RWMutex
func RegisterKeyPrefix(prefix, objectAPIName string) {
	keyPrefixMutex.Lock()
	defer keyPrefixMutex.Unlock()
	keyPrefixToObject[prefix] = objectAPIName
	objectToKeyPrefix[objectAPIName] = prefix
}

// GenerateCustomPrefix generates a Salesforce-style prefix for custom objects
// Pattern: a0X where X is 0-9, A-Z (giving 36 possible prefixes per a0 series)
// Then a1X, a2X, etc.
func GenerateCustomPrefix(index int) string {
	const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	series := index / 36 // a0, a1, a2, ...
	offset := index % 36 // 0-Z within series

	seriesChar := chars[series%36]
	offsetChar := chars[offset]

	return "a" + string(seriesChar) + string(offsetChar)
}
