package salesforce

// standardRelationshipToForeignKey maps Salesforce standard relationship names
// to their foreign-key field names. Used by the formula / flow resolver chain
// when a relationship segment is neither a custom `__r` suffix nor present on
// the schema's RelationshipName index — it lets resolvers reach the FK column
// even when per-field metadata is unavailable (cold start, partial schema).
var standardRelationshipToForeignKey = map[string]string{
	"Account":        "AccountId",
	"Campaign":       "CampaignId",
	"Case":           "CaseId",
	"Contact":        "ContactId",
	"Contract":       "ContractId",
	"CreatedBy":      "CreatedById",
	"LastModifiedBy": "LastModifiedById",
	"Manager":        "ManagerId",
	"Opportunity":    "OpportunityId",
	"Order":          "OrderId",
	"Owner":          "OwnerId",
	"Parent":         "ParentId",
	"Pricebook2":     "Pricebook2Id",
	"Product2":       "Product2Id",
	"Profile":        "ProfileId",
	"Quote":          "QuoteId",
	"RecordType":     "RecordTypeId",
	"UserRole":       "UserRoleId",
}

// standardForeignKeyToObject maps Salesforce standard foreign-key field names
// back to their canonical target SObject API names. Mirror of the table above
// for the reverse direction; both must stay in sync so the resolver and the
// `loadRelatedRecord` cache-miss fallback agree on `(segment, fkColumn,
// targetObject)` for every standard reference.
var standardForeignKeyToObject = map[string]string{
	"AccountId":        "Account",
	"CampaignId":       "Campaign",
	"CaseId":           "Case",
	"ContactId":        "Contact",
	"ContractId":       "Contract",
	"CreatedById":      "User",
	"LastModifiedById": "User",
	"LeadId":           "Lead",
	"ManagerId":        "User",
	"OpportunityId":    "Opportunity",
	"OrderId":          "Order",
	"OwnerId":          "User",
	"Pricebook2Id":     "Pricebook2",
	"Product2Id":       "Product2",
	"ProfileId":        "Profile",
	"QuoteId":          "Quote",
	"RecordTypeId":     "RecordType",
	"UserRoleId":       "UserRole",
}

// standardKeyPrefixToObject maps Salesforce 3-character key prefixes to their
// canonical standard SObject API names.
var standardKeyPrefixToObject = map[string]string{
	"001": "Account",
	"003": "Contact",
	"005": "User",
	"006": "Opportunity",
	"00D": "Organization",
	"00Q": "Lead",
	"00T": "Task",
	"00U": "Event",
	"300": "FlowDefinition",
	"301": "Flow",
	"500": "Case",
	"701": "Campaign",
	"800": "Contract",
}

var standardObjectToKeyPrefix = map[string]string{
	"Account":        "001",
	"Campaign":       "701",
	"Case":           "500",
	"Contact":        "003",
	"Contract":       "800",
	"Event":          "00U",
	"Flow":           "301",
	"FlowDefinition": "300",
	"Lead":           "00Q",
	"Opportunity":    "006",
	"Organization":   "00D",
	"Task":           "00T",
	"User":           "005",
}

// StandardRelationshipForeignKey returns the Salesforce foreign-key field for
// a standard relationship name.
func StandardRelationshipForeignKey(name string) (string, bool) {
	fk, ok := standardRelationshipToForeignKey[name]
	return fk, ok
}

// StandardObjectForForeignKey returns the canonical target SObject API name
// for a Salesforce standard foreign-key field.
func StandardObjectForForeignKey(fk string) (string, bool) {
	objectAPIName, ok := standardForeignKeyToObject[fk]
	return objectAPIName, ok
}

// StandardObjectForKeyPrefix returns the canonical standard SObject API name
// for a Salesforce 3-character key prefix.
func StandardObjectForKeyPrefix(prefix string) (string, bool) {
	objectAPIName, ok := standardKeyPrefixToObject[prefix]
	return objectAPIName, ok
}

// StandardKeyPrefixForObject returns the Salesforce 3-character key prefix
// for a standard SObject API name.
func StandardKeyPrefixForObject(objectAPIName string) (string, bool) {
	prefix, ok := standardObjectToKeyPrefix[objectAPIName]
	return prefix, ok
}

// StandardKeyPrefixToObjectMap returns a copy of the standard key-prefix map
// so callers can seed mutable registries without sharing state.
func StandardKeyPrefixToObjectMap() map[string]string {
	out := make(map[string]string, len(standardKeyPrefixToObject))
	for prefix, objectAPIName := range standardKeyPrefixToObject {
		out[prefix] = objectAPIName
	}
	return out
}

// StandardObjectToKeyPrefixMap returns a copy of the inverse standard key-prefix map.
func StandardObjectToKeyPrefixMap() map[string]string {
	out := make(map[string]string, len(standardObjectToKeyPrefix))
	for objectAPIName, prefix := range standardObjectToKeyPrefix {
		out[objectAPIName] = prefix
	}
	return out
}
