package controlplane

import (
	"fmt"
	"regexp"
	"sort"
	"strings"
	"testing"
)

func TestL0ReferenceSurfaceInventoryClassifiesSchemaReferences(t *testing.T) {
	referenceColumn := regexp.MustCompile(`(?i)(ObjectId|SobjectType|ObjectApiName|SourceObject|TargetObject|ParentObjectApiName|ChildObjectApiName|TriggerObjectOrEvent|TableEnumOrId|BaseObject|RequiredObject|MappingSourceObject|Object$|^Object$|FieldApiName|FieldAPIName|TargetFieldAPIName|SourceField|TargetField|SourceLookupField|ErrorDisplayField|FieldName|FieldId|ControllingField|ListFields|PathField|DisplayNameField|ProfileId|PermissionSetId|MutingPermissionSetId|LayoutId|RecordTypeId|ProcessDefinitionId|ProcessNodeId|GroupId|QueueId|TabName|AppId|ConnectedAppId|PermissionApiName|CustomPermissionId|RequiredPermission|RequiresPermission)`)
	classified := l0ClassifiedReferenceSurfacesForTest()

	var missing []string
	for _, def := range managedTableDefinitions() {
		for _, col := range def.Columns {
			if !referenceColumn.MatchString(col.Name) {
				continue
			}
			key := fmt.Sprintf("%s.%s", def.TableName, col.Name)
			if _, ok := classified[key]; !ok {
				missing = append(missing, key)
			}
		}
	}

	sort.Strings(missing)
	if len(missing) > 0 {
		t.Fatalf("L0 reference surface inventory is missing classifications:\n%s", strings.Join(missing, "\n"))
	}
}

func l0ClassifiedReferenceSurfacesForTest() map[string]string {
	out := map[string]string{}
	add := func(reason string, keys ...string) {
		for _, key := range keys {
			out[key] = reason
		}
	}

	for _, surface := range l0ObjectReferenceSurfaces {
		add("object-reference", surface.table+"."+surface.column)
	}
	for _, surface := range l0UnownedObjectComponentSurfaces {
		add("unowned-object-component", surface.table+"."+surface.column)
	}
	for _, surface := range l0FieldReferenceSurfaces {
		add("field-reference", surface.table+"."+surface.objectColumn, surface.table+"."+surface.fieldColumn)
	}
	for _, surface := range l0ProfileReferenceSurfaces {
		add("profile-reference", surface.table+"."+surface.column)
	}
	for _, surface := range l0PermissionSetReferenceSurfaces {
		add("permission-set-reference", surface.table+"."+surface.column)
	}
	for _, surface := range l0PermissionReferenceSurfaces {
		add("permission-reference", surface.table+"."+surface.column)
	}

	add("frontend-contribution-owner",
		"_System_App.FrontendAppId",
	)

	add("protocol-identity",
		"_System_ConnectorServingEpochReproducibility.ConnectorDigestProfileId",
	)

	add("historical-receipt-reference",
		"_System_PermissionSetAssignmentPolicyReleaseReceipt.PermissionSetId",
		"_System_PermissionSetAssignmentPolicyTargetReleaseReceipt.PermissionSetId",
		"_System_PermissionSetAssignmentPolicyTombstoneReceipt.PermissionSetId",
	)

	add("checked-by-dedicated-helper",
		"AppMenuItem.AppId",
		"MutingPermissionSet.GroupId",
		"PermissionSet.ProfileId",
		"PermissionSetAppVisibility.AppId",
		"PermissionSetAssignment.PermissionSetId",
		"PermissionSetCustomPermission.CustomPermissionId",
		"PermissionSetRecordTypeVisibility.RecordTypeId",
		"PermissionSetGroupAssignment.GroupId",
		"PermissionSetGroupComponent.GroupId",
		"PermissionSetGroupComponent.PermissionSetId",
		"PermissionSetTabSetting.TabName",
		"ProcessAction.FieldApiName",
		"ProcessAction.ProcessDefinitionId",
		"ProcessAction.ProcessNodeId",
		"ProcessNode.ProcessDefinitionId",
		"ProfileAppVisibility.AppId",
		"ProfileCustomPermission.CustomPermissionId",
		"ProfileLayout.LayoutId",
		"ProfileTabSetting.TabName",
		"QueueSobject.QueueId",
		"SharingRule.ShareWithGroupId",
		"SharingRule.SharedFromGroupId",
		"_System_Action.ObjectApiName",
		"_System_Action.TargetObject",
		"_System_ActionInputGuard.RequiredObject",
		"_System_ActionSchema.MappingSourceObject",
		"_System_AutoNumberCounter.FieldId",
		"_System_ConnectedAppAccess.ConnectedAppId",
		"_System_ConnectedAppDeclaration.ConnectedAppId",
		"_System_ConnectedAppStage.ConnectedAppId",
		"_System_CustomPermission.ConnectedAppId",
		"_System_Field.ObjectId",
		"_System_Field.ControllingField",
		"_System_FieldDependency.ControllingFieldId",
		"_System_FieldDependency.DependentFieldId",
		"_System_LayoutAssignment.LayoutId",
		"_System_LayoutAssignment.RecordTypeId",
		"_System_MutingPermissionSetPermission.MutingPermissionSetId",
		"_System_OAuthCustomScope.CustomPermissionId",
		"_System_Object.AppId",
		"_System_Object.ListFields",
		"_System_Object.ListFieldsCustomized",
		"_System_PageLayoutHistory.LayoutId",
		"_System_PermissionSetPermission.PermissionApiName",
		"_System_PermissionSetPermission.PermissionSetId",
		"_System_ProfilePermission.PermissionApiName",
		"_System_ProfilePermission.ProfileId",
		"_System_RecordType.ObjectId",
		"_System_RecordType.SobjectType",
		"_System_RecordTypePicklistValue.FieldId",
		"_System_RecordTypePicklistValue.RecordTypeId",
		"_System_ReportType.BaseObject",
		"_System_Relationship.FieldApiName",
		"_System_Relationship.RelatedListFields",
		"_System_StandardAction.RequiredPermissions",
		"_System_StandardAction.TargetObjects",
		"_System_StandardActionInternalAccessScope.ObjectApiName",
		"_System_ConnectorPushAttempt.AllowedSourceFieldsJSON",
		"_System_ConnectorPushAttempt.SourceObject",
		"_System_ConnectorPushAttempt.TargetObject",
		"_System_ConnectorRemoteLink.SourceObject",
		"_System_ConnectorRemoteLink.TargetObject",
	)

	add("runtime-data-excluded",
		"GroupMember.GroupId",
		"GroupMember.UserOrGroupId",
		"GroupMember.UserOrGroupId_type",
		"_System_OAuthDynamicClientRegistration.ConnectedAppId",
		"ProcessInstance.ProcessDefinitionId",
		"ProcessInstance.TargetObjectId",
		"ProcessInstanceHistory.ProcessNodeId",
		"ProcessInstanceHistory.TargetObjectId",
		"ProcessInstanceHistory.TargetObjectType",
		"ProcessInstanceNode.ProcessNodeId",
		"User.ProfileId",
		"_System_ApprovalActionOutbox.TargetObjectId",
		"_System_ApprovalActionLog.ProcessDefinitionId",
		"_System_ApprovalActionLog.TargetObjectId",
		"_System_ApprovalSubmitLineage.ProcessDefinitionId",
		"_System_ApprovalSubmitLineage.TargetObjectId",
		"_System_ApprovalWorkItem.ObjectApiName",
		"_System_AuditLog.FieldName",
		"_System_AuditLog.ObjectApiName",
		"_System_FieldHistorySequence.FieldId",
		"_System_FieldHistoryTrackingInterval.FieldId",
		"_System_FieldHistoryTrackingInterval.OpenFieldId",
		"_System_BulkJob.ExternalIdFieldName",
		"_System_BulkJob.Object",
		"_System_Comment.ObjectApiName",
		"_System_ConnectorEvent.SourceObjectID",
		"_System_ConnectorEvent.SourceObjectKind",
		"_System_ConnectorInboundProjectionSnapshot.SourceField",
		"_System_ConnectorInboundRemoteIDEvidence.SourceObject",
		"_System_IntegrationOutboundCommand.SourceObject",
		"_System_ConnectorWorkItem.DependencyConnectorSourceObject",
		"_System_ConnectorWorkItem.DependencyObjectAPIName",
		"_System_RuntimePlatformCommand.DependencyConnectorSourceObject",
		"_System_RuntimePlatformCommand.DependencyObjectAPIName",
		"_System_RuntimeOutboundIntent.SourceObject",
		"_System_ConnectedDeliveryJob.SourceObjectApiName",
		"_System_ExternalDeliveryAttempt.SourceObjectApiName",
		"_System_File.ParentObjectApiName",
		"_System_FileUploadOperation.ParentObjectApiName",
		"_System_GroupMembershipClosure.GroupId",
		"_System_OAuthConsent.ConnectedAppId",
		"_System_OAuthRefreshToken.ConnectedAppId",
		"_System_Recent.ObjectApiName",
		"_System_RecordShare.ObjectApiName",
		"_System_RecordShare.ShareWithGroupId",
		"_System_RecycleBin.CascadeFieldApiName",
		"_System_RecycleBin.CascadeParentObjectApiName",
		"_System_RecycleBin.DeleteRootObjectApiName",
		"_System_RecycleBin.ObjectApiName",
		"_System_RuntimeRecordCommandOperation.OperationObjectId",
		"_System_RollupDelta.ParentObject",
		"_System_RollupDelta.SourceObject",
		"_System_Session.ConnectedAppId",
		"_System_SyncState.Object",
		"_System_TeamMember.ObjectApiName",
		"_System_UserObjectInteraction.ObjectApiName",
		"_System_UserRecentItem.ObjectApiName",
	)

	return out
}
