#include "HyperTwistRecognition/HyperTwistRecognitionTypes.h"

namespace HyperTwistRecognitionTypesInternal
{
	bool AreAllStringsPopulated(const TArray<FString>& Values)
	{
		for (const FString& Value : Values)
		{
			if (Value.IsEmpty())
			{
				return false;
			}
		}

		return true;
	}

	template <typename ItemType>
	bool AreAllItemsStructurallyValid(const TArray<ItemType>& Items)
	{
		for (const ItemType& Item : Items)
		{
			if (!Item.IsStructurallyValid())
			{
				return false;
			}
		}

		return true;
	}
}

bool FHyperTwistVisionBrowserShellProfile::IsStructurallyValid() const
{
	return !BrowserShellProfileId.IsEmpty()
		&& !TransportKind.IsEmpty()
		&& !TransportEndpoint.IsEmpty()
		&& CaptureIntervalMs > 0
		&& !BrowserAssetReviewProfileId.IsEmpty()
		&& BrowserAssetReviewProfileDefinition.IsStructurallyValid()
		&& !DefaultBrowserAssetReviewDescriptorId.IsEmpty()
		&& SupportedBrowserAssetReviews.Num() > 0
		&& OrderedStageIds.Num() > 0
		&& ActionBindings.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(OrderedStageIds)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(SupportedBrowserAssetReviews)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}

bool FHyperTwistSpeechMicrophoneShellProfile::IsStructurallyValid() const
{
	return !MicrophoneShellProfileId.IsEmpty()
		&& !ShellKind.IsEmpty()
		&& !CaptureMode.IsEmpty()
		&& StepWindowMs > 0
		&& CaptureWindowMs >= StepWindowMs
		&& KeepWindowMs >= 0
		&& KeepWindowMs <= CaptureWindowMs
		&& AudioContextTokens >= 0
		&& VadThreshold > 0.0f
		&& HighPassFrequencyHz >= 0.0f
		&& !PermissionContractId.IsEmpty()
		&& !CaptureRouteContractId.IsEmpty()
		&& !PermissionRequestActionId.IsEmpty()
		&& !CaptureRouteRetryActionId.IsEmpty()
		&& Panels.Num() > 0
		&& ActionBindings.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}

bool FHyperTwistSpeechProviderProfile::IsStructurallyValid() const
{
	return !ProviderProfileId.IsEmpty()
		&& !DisplayLabel.IsEmpty()
		&& !ProviderClass.IsEmpty()
		&& !EndpointClass.IsEmpty()
		&& !EndpointReferenceId.IsEmpty()
		&& !AuthMaterialSource.IsEmpty()
		&& !ModelSelectionMode.IsEmpty()
		&& SupportedModelIds.Num() > 0
		&& CapabilityFlags.Num() > 0
		&& (AuthMaterialSource.Equals(TEXT("not-required"), ESearchCase::CaseSensitive)
			|| !AuthReferenceId.IsEmpty())
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(SupportedModelIds)
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(CapabilityFlags);
}

bool FHyperTwistSpeechUsageCostAccountingProfile::IsStructurallyValid() const
{
	return !UsageCostAccountingProfileId.IsEmpty()
		&& !AccountingKind.IsEmpty()
		&& !UsageAggregationMode.IsEmpty()
		&& !CostAggregationMode.IsEmpty()
		&& !QuotaVisibilityMode.IsEmpty()
		&& !EscalationMode.IsEmpty()
		&& !UserOverridePosture.IsEmpty()
		&& NormalizedMeterKinds.Num() > 0
		&& NormalizedCurrencyCodes.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(NormalizedMeterKinds)
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(NormalizedCurrencyCodes);
}

bool FHyperTwistSpeechUsageCostHistoryExportShellProfile::IsStructurallyValid() const
{
	return !HistoryExportShellProfileId.IsEmpty()
		&& !ShellKind.IsEmpty()
		&& !HistorySurfaceMode.IsEmpty()
		&& !ExportSurfaceMode.IsEmpty()
		&& !RefreshActionId.IsEmpty()
		&& !ExportPreviewActionId.IsEmpty()
		&& !CopySummaryActionId.IsEmpty()
		&& !RouteInspectActionId.IsEmpty()
		&& !BudgetInspectActionId.IsEmpty()
		&& RetainedHistoryEntryLimit > 0
		&& Panels.Num() > 0
		&& ActionBindings.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}

bool FHyperTwistSpeechProviderReceiptReviewShellProfile::IsStructurallyValid() const
{
	return !ReceiptReviewShellProfileId.IsEmpty()
		&& !ShellKind.IsEmpty()
		&& !ReceiptSurfaceMode.IsEmpty()
		&& !VarianceSurfaceMode.IsEmpty()
		&& !RefreshActionId.IsEmpty()
		&& !PostedChargeInspectActionId.IsEmpty()
		&& !VarianceReviewActionId.IsEmpty()
		&& !RouteInspectActionId.IsEmpty()
		&& !BudgetInspectActionId.IsEmpty()
		&& RetainedReceiptEntryLimit > 0
		&& Panels.Num() > 0
		&& ActionBindings.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}

bool FHyperTwistSpeechProviderBillingSettlementShellProfile::IsStructurallyValid() const
{
	return !BillingSettlementShellProfileId.IsEmpty()
		&& !ShellKind.IsEmpty()
		&& !SettlementSurfaceMode.IsEmpty()
		&& !InvoiceReconciliationMode.IsEmpty()
		&& !RefreshActionId.IsEmpty()
		&& !InvoiceReconciliationActionId.IsEmpty()
		&& !SettlementReadinessActionId.IsEmpty()
		&& !RouteInspectActionId.IsEmpty()
		&& !BudgetInspectActionId.IsEmpty()
		&& RetainedSettlementEntryLimit > 0
		&& Panels.Num() > 0
		&& ActionBindings.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}

bool FHyperTwistSpeechProviderSettlementExceptionShellProfile::IsStructurallyValid() const
{
	return !SettlementExceptionShellProfileId.IsEmpty()
		&& !ShellKind.IsEmpty()
		&& !ExceptionSurfaceMode.IsEmpty()
		&& !ExternalPortalHandoffMode.IsEmpty()
		&& !RefreshActionId.IsEmpty()
		&& !ExceptionInspectActionId.IsEmpty()
		&& !ExternalPortalHandoffActionId.IsEmpty()
		&& !RouteInspectActionId.IsEmpty()
		&& !BudgetInspectActionId.IsEmpty()
		&& RetainedExceptionEntryLimit > 0
		&& Panels.Num() > 0
		&& ActionBindings.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}

bool FHyperTwistSpeechNativeCaptureRouteShellProfile::IsStructurallyValid() const
{
	return !NativeCaptureRouteShellProfileId.IsEmpty()
		&& !ShellKind.IsEmpty()
		&& !OwnershipSummarySurfaceMode.IsEmpty()
		&& !PreparationSurfaceMode.IsEmpty()
		&& !SessionReopenSurfaceMode.IsEmpty()
		&& !RouteInspectActionId.IsEmpty()
		&& !PreparationRetryActionId.IsEmpty()
		&& !SessionReopenActionId.IsEmpty()
		&& !PermissionDependencyActionId.IsEmpty()
		&& Panels.Num() > 0
		&& ActionBindings.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}

bool FHyperTwistSpeechNativeCaptureRouteShellState::IsStructurallyValid() const
{
	if (NativeCaptureRouteShellProfileId.IsEmpty()
		|| NativeCaptureRouteWorkflowProfileId.IsEmpty()
		|| ActiveProviderProfileId.IsEmpty()
		|| ActiveServiceLaneId.IsEmpty()
		|| WorkflowStateId.IsEmpty()
		|| CaptureRouteStateId.IsEmpty()
		|| PermissionStateId.IsEmpty()
		|| LatestSourceKind.IsEmpty()
		|| StatusLine.IsEmpty()
		|| DetailLine.IsEmpty()
		|| ActiveIssueCount < 0
		|| AvailableActionIds.Num() <= 0)
	{
		return false;
	}

	if (ActiveIssueCount != Issues.Num())
	{
		return false;
	}

	return (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Entries)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Issues)
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(AvailableActionIds);
}

bool FHyperTwistSpeechUsageCostDashboardShellProfile::IsStructurallyValid() const
{
	return !DashboardShellProfileId.IsEmpty()
		&& !ShellKind.IsEmpty()
		&& !UsageSurfaceMode.IsEmpty()
		&& !CostSurfaceMode.IsEmpty()
		&& !EscalationBannerMode.IsEmpty()
		&& !RefreshActionId.IsEmpty()
		&& !RouteInspectActionId.IsEmpty()
		&& !BudgetInspectActionId.IsEmpty()
		&& Panels.Num() > 0
		&& ActionBindings.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}

bool FHyperTwistSpeechUsageCostDashboardShellState::IsStructurallyValid() const
{
	if (DashboardShellProfileId.IsEmpty()
		|| ActiveProviderProfileId.IsEmpty()
		|| ActiveProviderDisplayLabel.IsEmpty()
		|| ActiveServiceLaneId.IsEmpty()
		|| ActiveRouteStateId.IsEmpty()
		|| UsageAggregationWindowId.IsEmpty()
		|| CostAggregationWindowId.IsEmpty()
		|| UsageMeterKind.IsEmpty()
		|| CurrencyCode.IsEmpty()
		|| StatusLine.IsEmpty()
		|| DetailLine.IsEmpty()
		|| LatestUsageEventId.IsEmpty()
		|| LatestCostEventId.IsEmpty()
		|| LatestQuotaStateId.IsEmpty()
		|| LatestRouteDecisionId.IsEmpty()
		|| DisplayedUsageQuantity < 0.0f
		|| DisplayedEstimatedCostUsd < 0.0f
		|| DisplayedReportedCostUsd < 0.0f
		|| RemainingEstimatedSpendUsd < 0.0f
		|| RemainingRequestCount < 0
		|| RemainingAudioSeconds < 0
		|| ActiveIssueCount < 0
		|| AvailableActionIds.Num() <= 0)
	{
		return false;
	}

	if (ActiveIssueCount != Issues.Num())
	{
		return false;
	}

	return (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Issues)
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(AvailableActionIds);
}

bool FHyperTwistVisionShellProfile::IsStructurallyValid() const
{
	return !ShellProfileId.IsEmpty()
		&& !ShellKind.IsEmpty()
		&& !DefaultLocaleCode.IsEmpty()
		&& !FontReviewProfileId.IsEmpty()
		&& FontReviewProfileDefinition.IsStructurallyValid()
		&& SupportedFontReviews.Num() > 0
		&& SupportedLocales.Num() > 0
		&& Panels.Num() > 0
		&& ActionBindings.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(SupportedLocales)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(SupportedFontReviews)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}

bool FHyperTwistVisionSolveExplanationProfile::IsStructurallyValid() const
{
	return !ExplanationProfileId.IsEmpty()
		&& !PuzzleId.IsEmpty()
		&& !RecommendationMode.IsEmpty()
		&& !LocaleGuidanceMode.IsEmpty()
		&& !DefaultLocaleCode.IsEmpty()
		&& !StartingOrientationHint.IsEmpty()
		&& !FontReviewProfileId.IsEmpty()
		&& FontReviewProfileDefinition.IsStructurallyValid()
		&& SupportedFontReviews.Num() > 0
		&& SupportedLocales.Num() > 0
		&& Steps.Num() > 0
		&& ActionBindings.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(SupportedLocales)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(SupportedFontReviews)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Steps)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}

bool FHyperTwistVisionCorrectionState::IsStructurallyValid() const
{
	if (CorrectionProfileId.IsEmpty()
		|| MissingFaceCount < 0
		|| ContradictionCount < 0
		|| ContradictionCount != Contradictions.Num()
		|| ResolvedCorrectionCount < 0
		|| ResolvedCorrectionCount != ResolutionLedger.Num())
	{
		return false;
	}

	if (bCorrectionRequired
		&& (ActiveTargetFaceId.IsEmpty()
			|| !ActiveTarget.IsStructurallyValid()
			|| ActiveTargetFaceId != ActiveTarget.FaceId))
	{
		return false;
	}

	return HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(PendingTargets)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Contradictions)
		&& (LastResolution.ResolutionId.IsEmpty() || LastResolution.IsStructurallyValid())
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ResolutionLedger);
}

bool FHyperTwistSpeechProviderRoutingPolicy::IsStructurallyValid() const
{
	return !ProviderRoutingPolicyId.IsEmpty()
		&& !PolicyKind.IsEmpty()
		&& !RouteSelectionMode.IsEmpty()
		&& !FallbackMode.IsEmpty()
		&& !WorkflowPolicyState.IsEmpty()
		&& !FailureEscalationMode.IsEmpty()
		&& !UserOverridePosture.IsEmpty()
		&& EligibleProviderClasses.Num() > 0
		&& EligibleEndpointClasses.Num() > 0
		&& RequiredCapabilityFlags.Num() > 0
		&& SupportedTaskKinds.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(EligibleProviderClasses)
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(EligibleEndpointClasses)
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(RequiredCapabilityFlags)
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(SupportedTaskKinds);
}

namespace HyperTwistRecognitionTypeValidation
{
	template <typename TStruct>
	bool AreStructurallyValidEntries(const TArray<TStruct>& Values)
	{
		return HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Values);
	}

	bool AreNonEmptyStrings(const TArray<FString>& Values)
	{
		return HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(Values);
	}

	bool AreSpeechModelPayloadsValid(const TArray<FHyperTwistSpeechModelPayloadDescriptor>& Payloads)
	{
		return AreStructurallyValidEntries(Payloads);
	}

	bool HasValidSpeechSessionCore(const FHyperTwistSpeechSessionConfig& Session)
	{
		return !Session.SessionId.IsEmpty()
			&& !Session.ListeningContractId.IsEmpty()
			&& !Session.InputRouteId.IsEmpty()
			&& !Session.AudioEncoding.IsEmpty()
			&& Session.SampleRateHz > 0
			&& Session.ChannelCount > 0
			&& !Session.TaskKind.IsEmpty()
			&& Session.RequiredModelPayloads.Num() > 0
			&& Session.VadPolicy.IsStructurallyValid()
			&& Session.OrchestrationProfile.IsStructurallyValid();
	}

	bool HasValidSpeechSessionProfiles(const FHyperTwistSpeechSessionConfig& Session)
	{
		return !Session.MicrophoneShellProfileId.IsEmpty()
			&& Session.MicrophoneShellProfileDefinition.IsStructurallyValid()
			&& !Session.DevicePermissionWorkflowProfileId.IsEmpty()
			&& Session.DevicePermissionWorkflowProfileDefinition.IsStructurallyValid()
			&& !Session.NativeCaptureRouteWorkflowProfileId.IsEmpty()
			&& Session.NativeCaptureRouteWorkflowProfileDefinition.IsStructurallyValid()
			&& !Session.NativeCaptureRouteShellProfileId.IsEmpty()
			&& Session.NativeCaptureRouteShellProfileDefinition.IsStructurallyValid()
			&& !Session.ExternalDictationShellProfileId.IsEmpty()
			&& Session.ExternalDictationShellProfileDefinition.IsStructurallyValid()
			&& !Session.ProviderProfileId.IsEmpty()
			&& Session.ProviderProfileDefinition.IsStructurallyValid()
			&& !Session.ByokCustodyProfileId.IsEmpty()
			&& Session.ByokCustodyProfileDefinition.IsStructurallyValid()
			&& !Session.ProviderRoutingPolicyId.IsEmpty()
			&& Session.ProviderRoutingPolicyDefinition.IsStructurallyValid()
			&& Session.ProviderRouteDecision.IsStructurallyValid()
			&& !Session.UsageCostAccountingProfileId.IsEmpty()
			&& Session.UsageCostAccountingProfileDefinition.IsStructurallyValid()
			&& Session.UsageEventTemplate.IsStructurallyValid()
			&& Session.CostEventTemplate.IsStructurallyValid()
			&& !Session.UsageCostDashboardShellProfileId.IsEmpty()
			&& Session.UsageCostDashboardShellProfileDefinition.IsStructurallyValid()
			&& !Session.UsageCostHistoryExportShellProfileId.IsEmpty()
			&& Session.UsageCostHistoryExportShellProfileDefinition.IsStructurallyValid()
			&& !Session.ProviderReceiptReviewShellProfileId.IsEmpty()
			&& Session.ProviderReceiptReviewShellProfileDefinition.IsStructurallyValid()
			&& !Session.ProviderBillingSettlementShellProfileId.IsEmpty()
			&& Session.ProviderBillingSettlementShellProfileDefinition.IsStructurallyValid()
			&& !Session.ProviderSettlementExceptionShellProfileId.IsEmpty()
			&& Session.ProviderSettlementExceptionShellProfileDefinition.IsStructurallyValid()
			&& !Session.PayloadCustodyProfileId.IsEmpty()
			&& Session.PayloadCustodyProfileDefinition.IsStructurallyValid();
	}

	bool HasValidTranscriptCore(const FHyperTwistSpeechTranscriptResult& Transcript)
	{
		return !Transcript.SessionId.IsEmpty()
			&& !Transcript.UtteranceId.IsEmpty()
			&& !Transcript.TaskKind.IsEmpty()
			&& (!Transcript.TranscriptText.IsEmpty() || Transcript.Segments.Num() > 0)
			&& !Transcript.OrchestrationProfileId.IsEmpty()
			&& !Transcript.ServiceLaneId.IsEmpty()
			&& Transcript.RequestedBatchSize > 0
			&& Transcript.ProcessedClipCount > 0
			&& Transcript.AppliedBatchCollectionWindowMs > 0
			&& Transcript.LanguageProbability >= 0.0f
			&& !Transcript.AppliedPromptRoutingModeId.IsEmpty()
			&& !Transcript.AppliedRetrievalContextLaneId.IsEmpty();
	}

	bool AreTranscriptSegmentsValid(const TArray<FHyperTwistSpeechTranscriptSegment>& Segments)
	{
		return AreStructurallyValidEntries(Segments);
	}

	bool HasValidSpeechServiceHealthCore(const FHyperTwistSpeechServiceHealth& Health)
	{
		return !Health.ProviderLabel.IsEmpty()
			&& !Health.ServiceVersion.IsEmpty()
			&& !Health.ProviderProfileId.IsEmpty()
			&& Health.ProviderProfileDefinition.IsStructurallyValid()
			&& !Health.ByokCustodyProfileId.IsEmpty()
			&& Health.ByokCustodyProfileDefinition.IsStructurallyValid()
			&& !Health.ProviderRoutingPolicyId.IsEmpty()
			&& Health.ProviderRoutingPolicyDefinition.IsStructurallyValid()
			&& Health.ProviderRouteDecision.IsStructurallyValid()
			&& !Health.UsageCostAccountingProfileId.IsEmpty()
			&& Health.UsageCostAccountingProfileDefinition.IsStructurallyValid()
			&& Health.LatestUsageEvent.IsStructurallyValid()
			&& Health.LatestCostEvent.IsStructurallyValid()
			&& Health.QuotaRateLimitState.IsStructurallyValid()
			&& !Health.PayloadCustodyProfileId.IsEmpty()
			&& Health.PayloadCustodyProfileDefinition.IsStructurallyValid();
	}

	bool HasValidExternalDictationShellProfileCore(
		const FHyperTwistSpeechExternalDictationShellProfile& Profile)
	{
		return !Profile.ExternalDictationShellProfileId.IsEmpty()
			&& !Profile.ShellKind.IsEmpty()
			&& !Profile.TranscriptHistorySurfaceMode.IsEmpty()
			&& !Profile.OutputRoutingSurfaceMode.IsEmpty()
			&& !Profile.PostProcessOverlaySurfaceMode.IsEmpty()
			&& !Profile.GlobalHotkeySurfaceMode.IsEmpty()
			&& !Profile.InputDeviceSurfaceMode.IsEmpty()
			&& !Profile.OutputDeviceSurfaceMode.IsEmpty()
			&& !Profile.MuteSurfaceMode.IsEmpty()
			&& !Profile.MicrophoneModeSurfaceMode.IsEmpty()
			&& !Profile.LocalModelCatalogSurfaceMode.IsEmpty()
			&& !Profile.ModelIntegritySurfaceMode.IsEmpty()
			&& !Profile.ModelUnloadSurfaceMode.IsEmpty()
			&& !Profile.StartCaptureActionId.IsEmpty()
			&& !Profile.CancelCaptureActionId.IsEmpty()
			&& !Profile.CycleOutputRouteActionId.IsEmpty()
			&& !Profile.CopyTranscriptActionId.IsEmpty()
			&& !Profile.PasteTranscriptActionId.IsEmpty()
			&& !Profile.ScriptDispatchActionId.IsEmpty()
			&& !Profile.TogglePostProcessOverlayActionId.IsEmpty()
			&& !Profile.ReopenSpeechSessionActionId.IsEmpty()
			&& !Profile.RouteInspectActionId.IsEmpty()
			&& !Profile.InspectGlobalHotkeyActionId.IsEmpty()
			&& !Profile.CycleInputDeviceActionId.IsEmpty()
			&& !Profile.CycleOutputDeviceActionId.IsEmpty()
			&& !Profile.ToggleMuteWhileRecordingActionId.IsEmpty()
			&& !Profile.ToggleMicrophoneModeActionId.IsEmpty()
			&& !Profile.InspectLocalModelCatalogActionId.IsEmpty()
			&& !Profile.ReviewLocalModelIntegrityActionId.IsEmpty()
			&& !Profile.ReviewLocalModelUnloadPolicyActionId.IsEmpty()
			&& !Profile.PrimaryHotkeyBindingLabel.IsEmpty()
			&& !Profile.PostProcessHotkeyBindingLabel.IsEmpty()
			&& Profile.RetainedHistoryEntryLimit > 0
			&& Profile.Panels.Num() > 0
			&& Profile.ActionBindings.Num() > 0;
	}

	bool HasValidExternalDictationShellStateCore(const FHyperTwistSpeechExternalDictationShellState& State)
	{
		return !State.ExternalDictationShellProfileId.IsEmpty()
			&& !State.ActiveProviderProfileId.IsEmpty()
			&& !State.ActiveServiceLaneId.IsEmpty()
			&& !State.SelectedOutputRouteId.IsEmpty()
			&& !State.TranscriptHistorySurfaceModeId.IsEmpty()
			&& !State.OutputRoutingSurfaceModeId.IsEmpty()
			&& !State.PostProcessOverlaySurfaceModeId.IsEmpty()
			&& !State.GlobalHotkeySurfaceModeId.IsEmpty()
			&& !State.InputDeviceSurfaceModeId.IsEmpty()
			&& !State.OutputDeviceSurfaceModeId.IsEmpty()
			&& !State.MuteSurfaceModeId.IsEmpty()
			&& !State.MicrophoneModeSurfaceModeId.IsEmpty()
			&& !State.LocalModelCatalogSurfaceModeId.IsEmpty()
			&& !State.ModelIntegritySurfaceModeId.IsEmpty()
			&& !State.ModelUnloadSurfaceModeId.IsEmpty()
			&& !State.LatestSourceKind.IsEmpty()
			&& !State.StatusLine.IsEmpty()
			&& !State.DetailLine.IsEmpty()
			&& !State.PrimaryHotkeyBindingLabel.IsEmpty()
			&& !State.PostProcessHotkeyBindingLabel.IsEmpty()
			&& !State.SelectedInputDeviceId.IsEmpty()
			&& !State.SelectedInputDeviceLabel.IsEmpty()
			&& !State.SelectedOutputDeviceId.IsEmpty()
			&& !State.SelectedOutputDeviceLabel.IsEmpty()
			&& !State.MicrophoneModeId.IsEmpty()
			&& !State.PayloadCustodyProfileId.IsEmpty()
			&& !State.SelectedPrimaryPayloadId.IsEmpty()
			&& State.HistoryEntryCount >= 0
			&& State.PostProcessedEntryCount >= 0
			&& State.SavedEntryCount >= 0
			&& State.ModelCatalogEntryCount >= 0
			&& State.OptionalModelCatalogEntryCount >= 0
			&& State.DownloadDeferredModelEntryCount >= 0
			&& State.IntegrityReviewRequiredEntryCount >= 0
			&& State.ActiveIssueCount >= 0
			&& State.OutputRouteOptions.Num() > 0
			&& State.InputDeviceOptions.Num() > 0
			&& State.OutputDeviceOptions.Num() > 0
			&& State.ModelCatalogEntries.Num() > 0
			&& State.AvailableActionIds.Num() > 0;
	}

	bool HasConsistentExternalDictationShellStateCounts(const FHyperTwistSpeechExternalDictationShellState& State)
	{
		return State.HistoryEntryCount == State.HistoryEntries.Num()
			&& State.PostProcessedEntryCount <= State.HistoryEntryCount
			&& State.SavedEntryCount <= State.HistoryEntryCount
			&& State.ModelCatalogEntryCount == State.ModelCatalogEntries.Num()
			&& State.OptionalModelCatalogEntryCount <= State.ModelCatalogEntryCount
			&& State.DownloadDeferredModelEntryCount <= State.ModelCatalogEntryCount
			&& State.IntegrityReviewRequiredEntryCount <= State.ModelCatalogEntryCount;
	}

	bool HasConsistentExternalDictationShellStateLatestEntry(const FHyperTwistSpeechExternalDictationShellState& State)
	{
		return State.HistoryEntryCount <= 0
			|| (!State.LatestHistoryEntryId.IsEmpty() && !State.LatestTranscriptText.IsEmpty());
	}

	bool HasConsistentExternalDictationShellStateActiveIssue(const FHyperTwistSpeechExternalDictationShellState& State)
	{
		return State.ActiveIssueCount == State.Issues.Num()
			&& (State.ActiveIssueCount <= 0 || State.ActiveIssue.IsStructurallyValid());
	}
}

bool FHyperTwistSpeechUsageCostHistoryExportShellState::IsStructurallyValid() const
{
	if (HistoryExportShellProfileId.IsEmpty()
		|| ActiveProviderProfileId.IsEmpty()
		|| ActiveProviderDisplayLabel.IsEmpty()
		|| ActiveServiceLaneId.IsEmpty()
		|| SelectedHistoryWindowId.IsEmpty()
		|| ExportPreviewFormatId.IsEmpty()
		|| LatestSourceKind.IsEmpty()
		|| StatusLine.IsEmpty()
		|| DetailLine.IsEmpty()
		|| HistoryEntryCount < 0
		|| EstimateOnlyEntryCount < 0
		|| ProviderReceiptEntryCount < 0
		|| TotalUsageQuantity < 0.0f
		|| TotalEstimatedCostUsd < 0.0f
		|| TotalReportedCostUsd < 0.0f
		|| LowestRemainingEstimatedSpendUsd < 0.0f
		|| ActiveIssueCount < 0
		|| AvailableActionIds.Num() <= 0)
	{
		return false;
	}

	return HistoryEntryCount == HistoryEntries.Num()
		&& (HistoryEntryCount <= 0 || !LatestHistoryEntryId.IsEmpty())
		&& (!bExportPreviewReady || !ExportPreviewText.IsEmpty())
		&& ActiveIssueCount == Issues.Num()
		&& (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(Issues)
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(HistoryEntries)
		&& HyperTwistRecognitionTypeValidation::AreNonEmptyStrings(AvailableActionIds);
}

bool FHyperTwistSpeechProviderReceiptReviewShellState::IsStructurallyValid() const
{
	if (ReceiptReviewShellProfileId.IsEmpty()
		|| ActiveProviderProfileId.IsEmpty()
		|| ActiveProviderDisplayLabel.IsEmpty()
		|| ActiveServiceLaneId.IsEmpty()
		|| SelectedChargeWindowId.IsEmpty()
		|| PostedChargeInspectionModeId.IsEmpty()
		|| LatestSourceKind.IsEmpty()
		|| StatusLine.IsEmpty()
		|| DetailLine.IsEmpty()
		|| ReceiptEntryCount < 0
		|| ProviderPostedChargeCount < 0
		|| EstimateOnlyEntryCount < 0
		|| VarianceReviewEntryCount < 0
		|| TotalEstimatedCostUsd < 0.0f
		|| TotalReportedCostUsd < 0.0f
		|| TotalAbsoluteVarianceUsd < 0.0f
		|| HighestAbsoluteVarianceUsd < 0.0f
		|| ActiveIssueCount < 0
		|| AvailableActionIds.Num() <= 0)
	{
		return false;
	}

	return ReceiptEntryCount == ReceiptEntries.Num()
		&& ProviderPostedChargeCount <= ReceiptEntryCount
		&& EstimateOnlyEntryCount <= ReceiptEntryCount
		&& VarianceReviewEntryCount <= ReceiptEntryCount
		&& (ReceiptEntryCount <= 0 || !LatestReceiptEntryId.IsEmpty())
		&& (!bReceiptSummaryReady || !ReceiptSummaryText.IsEmpty())
		&& ActiveIssueCount == Issues.Num()
		&& (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(Issues)
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(ReceiptEntries)
		&& HyperTwistRecognitionTypeValidation::AreNonEmptyStrings(AvailableActionIds);
}

bool FHyperTwistSpeechProviderBillingSettlementShellState::IsStructurallyValid() const
{
	if (BillingSettlementShellProfileId.IsEmpty()
		|| ActiveProviderProfileId.IsEmpty()
		|| ActiveProviderDisplayLabel.IsEmpty()
		|| ActiveServiceLaneId.IsEmpty()
		|| SelectedSettlementWindowId.IsEmpty()
		|| SettlementSurfaceModeId.IsEmpty()
		|| InvoiceReconciliationModeId.IsEmpty()
		|| LatestSourceKind.IsEmpty()
		|| StatusLine.IsEmpty()
		|| DetailLine.IsEmpty()
		|| SettlementEntryCount < 0
		|| ProviderPostedChargeCount < 0
		|| ReconciliationReadyEntryCount < 0
		|| EstimateOnlyEntryCount < 0
		|| ManualReviewEntryCount < 0
		|| BlockedSettlementEntryCount < 0
		|| TotalEstimatedCostUsd < 0.0f
		|| TotalReportedCostUsd < 0.0f
		|| TotalSettlementDeltaUsd < 0.0f
		|| HighestSettlementDeltaUsd < 0.0f
		|| ActiveIssueCount < 0
		|| AvailableActionIds.Num() <= 0)
	{
		return false;
	}

	return SettlementEntryCount == SettlementEntries.Num()
		&& ProviderPostedChargeCount <= SettlementEntryCount
		&& ReconciliationReadyEntryCount <= SettlementEntryCount
		&& EstimateOnlyEntryCount <= SettlementEntryCount
		&& ManualReviewEntryCount <= SettlementEntryCount
		&& BlockedSettlementEntryCount <= SettlementEntryCount
		&& (SettlementEntryCount <= 0 || !LatestSettlementEntryId.IsEmpty())
		&& (!bSettlementSummaryReady || !SettlementSummaryText.IsEmpty())
		&& ActiveIssueCount == Issues.Num()
		&& (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(Issues)
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(SettlementEntries)
		&& HyperTwistRecognitionTypeValidation::AreNonEmptyStrings(AvailableActionIds);
}

bool FHyperTwistSpeechProviderSettlementExceptionShellState::IsStructurallyValid() const
{
	if (SettlementExceptionShellProfileId.IsEmpty()
		|| ActiveProviderProfileId.IsEmpty()
		|| ActiveProviderDisplayLabel.IsEmpty()
		|| ActiveServiceLaneId.IsEmpty()
		|| SelectedSettlementWindowId.IsEmpty()
		|| ExceptionSurfaceModeId.IsEmpty()
		|| ExternalPortalHandoffModeId.IsEmpty()
		|| LatestSourceKind.IsEmpty()
		|| StatusLine.IsEmpty()
		|| DetailLine.IsEmpty()
		|| ExceptionEntryCount < 0
		|| ExternalPortalHandoffReadyEntryCount < 0
		|| PendingChargeEntryCount < 0
		|| ManualReviewEntryCount < 0
		|| RouteDegradedEntryCount < 0
		|| BlockedSettlementEntryCount < 0
		|| TotalEstimatedCostUsd < 0.0f
		|| TotalReportedCostUsd < 0.0f
		|| TotalSettlementDeltaUsd < 0.0f
		|| HighestSettlementDeltaUsd < 0.0f
		|| ActiveIssueCount < 0
		|| AvailableActionIds.Num() <= 0)
	{
		return false;
	}

		return ExceptionEntryCount == ExceptionEntries.Num()
			&& ExternalPortalHandoffReadyEntryCount <= ExceptionEntryCount
		&& PendingChargeEntryCount <= ExceptionEntryCount
		&& ManualReviewEntryCount <= ExceptionEntryCount
		&& RouteDegradedEntryCount <= ExceptionEntryCount
		&& BlockedSettlementEntryCount <= ExceptionEntryCount
		&& (ExceptionEntryCount <= 0 || !LatestExceptionEntryId.IsEmpty())
		&& (!bExceptionSummaryReady || !ExceptionSummaryText.IsEmpty())
		&& ActiveIssueCount == Issues.Num()
		&& (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(Issues)
			&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(ExceptionEntries)
			&& HyperTwistRecognitionTypeValidation::AreNonEmptyStrings(AvailableActionIds);
}

bool FHyperTwistSpeechExternalDictationShellProfile::IsStructurallyValid() const
{
	return HyperTwistRecognitionTypeValidation::HasValidExternalDictationShellProfileCore(*this)
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(Panels)
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(ActionBindings);
}

bool FHyperTwistSpeechExternalDictationShellState::IsStructurallyValid() const
{
	return HyperTwistRecognitionTypeValidation::HasValidExternalDictationShellStateCore(*this)
		&& HyperTwistRecognitionTypeValidation::HasConsistentExternalDictationShellStateCounts(*this)
		&& HyperTwistRecognitionTypeValidation::HasConsistentExternalDictationShellStateLatestEntry(*this)
		&& HyperTwistRecognitionTypeValidation::HasConsistentExternalDictationShellStateActiveIssue(*this)
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(Issues)
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(HistoryEntries)
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(OutputRouteOptions)
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(InputDeviceOptions)
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(OutputDeviceOptions)
		&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(ModelCatalogEntries)
		&& HyperTwistRecognitionTypeValidation::AreNonEmptyStrings(AvailableActionIds);
}

bool FHyperTwistSpeechSessionConfig::IsStructurallyValid() const
{
	return HyperTwistRecognitionTypeValidation::HasValidSpeechSessionCore(*this)
		&& HyperTwistRecognitionTypeValidation::HasValidSpeechSessionProfiles(*this)
		&& HyperTwistRecognitionTypeValidation::AreSpeechModelPayloadsValid(RequiredModelPayloads);
}

bool FHyperTwistSpeechTranscriptResult::IsStructurallyValid() const
{
	if (!HyperTwistRecognitionTypeValidation::HasValidTranscriptCore(*this)
		|| RetrievedHintCount < 0)
	{
		return false;
	}

	if (bUsedRetrievedHintAugmentation && RetrievedHintCount <= 0)
	{
		return false;
	}

	return RetrievedHintCount == AppliedRetrievedHints.Num()
		&& HyperTwistRecognitionTypeValidation::AreTranscriptSegmentsValid(Segments)
		&& HyperTwistRecognitionTypeValidation::AreNonEmptyStrings(AppliedRetrievedHints);
}

bool FHyperTwistSpeechServiceHealth::IsStructurallyValid() const
{
	return HyperTwistRecognitionTypeValidation::HasValidSpeechServiceHealthCore(*this)
		&& HyperTwistRecognitionTypeValidation::AreNonEmptyStrings(SupportedModelPayloadIds)
		&& HyperTwistRecognitionTypeValidation::AreSpeechModelPayloadsValid(SupportedModelPayloads);
}

bool FHyperTwistVoiceAssetDescriptor::IsStructurallyValid() const
{
	return !VoiceAssetId.IsEmpty()
		&& !VoiceProfileId.IsEmpty()
		&& !ArtifactName.IsEmpty()
		&& !RelativePathHint.IsEmpty()
		&& !SourceDocumentPath.IsEmpty()
		&& !ReviewDocumentPath.IsEmpty()
		&& !AcquisitionMode.IsEmpty()
		&& !ReviewPosture.IsEmpty()
		&& ApproximateSizeMiB > 0;
}

bool FHyperTwistVoiceAssetReviewProfile::IsStructurallyValid() const
{
	return !VoiceAssetReviewProfileId.IsEmpty()
		&& !VoiceAssetReviewPosture.IsEmpty()
		&& !ShippingPosture.IsEmpty()
		&& !DownloadWorkflowPosture.IsEmpty()
		&& !ProvisioningPosture.IsEmpty()
		&& !CodeLicenseBoundary.IsEmpty();
}

bool FHyperTwistVoiceModelReviewDescriptor::IsStructurallyValid() const
{
	return !VoiceModelReviewId.IsEmpty()
		&& !ModelBindingId.IsEmpty()
		&& !VocoderBindingId.IsEmpty()
		&& !VoiceProfileId.IsEmpty()
		&& !RegistryReferencePath.IsEmpty()
		&& !ReviewDocumentPath.IsEmpty()
		&& !ModelLicensePosture.IsEmpty()
		&& !PayloadLicensePosture.IsEmpty()
		&& !AcquisitionMode.IsEmpty();
}

bool FHyperTwistVoiceModelReviewProfile::IsStructurallyValid() const
{
	return !VoiceModelReviewProfileId.IsEmpty()
		&& !ReviewPosture.IsEmpty()
		&& !ShippingPosture.IsEmpty()
		&& !DownloadWorkflowPosture.IsEmpty()
		&& !CodeLicenseBoundary.IsEmpty();
}

bool FHyperTwistVoiceProfileSummary::IsStructurallyValid() const
{
	return !VoiceProfileId.IsEmpty()
		&& !VoiceName.IsEmpty()
		&& !LanguageCode.IsEmpty()
		&& !LanguageFamily.IsEmpty()
		&& !RegionCode.IsEmpty()
		&& !LanguageNameEnglish.IsEmpty()
		&& !Quality.IsEmpty()
		&& NumSpeakers > 0;
}

bool FHyperTwistVoiceProfileCatalog::IsStructurallyValid() const
{
	return Profiles.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Profiles);
}

bool FHyperTwistNarrationOrchestrationProfile::IsStructurallyValid() const
{
	return !OrchestrationProfileId.IsEmpty()
		&& !ServiceLaneId.IsEmpty()
		&& !ModelBindingId.IsEmpty()
		&& !VocoderBindingId.IsEmpty()
		&& !DefaultSpeakerProfileId.IsEmpty();
}

bool FHyperTwistNarrationSynthesisRequest::IsStructurallyValid() const
{
	return !RequestId.IsEmpty()
		&& !NarrationContractId.IsEmpty()
		&& !ServiceLaneId.IsEmpty()
		&& !OutputRouteId.IsEmpty()
		&& !VoiceProfileId.IsEmpty()
		&& !LanguageCode.IsEmpty()
		&& OrchestrationProfile.IsStructurallyValid()
		&& ServiceLaneId.Equals(OrchestrationProfile.ServiceLaneId, ESearchCase::CaseSensitive)
		&& !ScriptText.IsEmpty()
		&& !AudioEncodingHint.IsEmpty()
		&& LengthScale > 0.0f
		&& NoiseScale >= 0.0f
		&& NoiseW >= 0.0f
		&& SentenceSilenceSeconds >= 0.0f;
}

bool FHyperTwistNarrationSynthesisResult::IsStructurallyValid() const
{
	return !RequestId.IsEmpty()
		&& !NarrationContractId.IsEmpty()
		&& !ServiceLaneId.IsEmpty()
		&& !OutputRouteId.IsEmpty()
		&& !VoiceProfileId.IsEmpty()
		&& !LanguageCode.IsEmpty()
		&& !OrchestrationProfileId.IsEmpty()
		&& !ModelBindingId.IsEmpty()
		&& !VocoderBindingId.IsEmpty()
		&& !SubtitleText.IsEmpty()
		&& !AudioEncoding.IsEmpty()
		&& SampleRateHz > 0
		&& ChannelCount > 0
		&& DurationMs >= 0
		&& AudioBytes.Num() > 0
		&& AppliedLengthScale > 0.0f
		&& AppliedNoiseScale >= 0.0f
		&& AppliedNoiseW >= 0.0f
		&& AppliedSentenceSilenceSeconds >= 0.0f;
}

bool FHyperTwistVoiceServiceHealth::IsStructurallyValid() const
{
	if (ProviderLabel.IsEmpty() || ServiceVersion.IsEmpty())
	{
		return false;
	}

	if ((!VoiceAssetReviewProfileId.IsEmpty()
			|| VoiceAssetReviewProfileDefinition.IsStructurallyValid()
			|| SupportedVoiceAssetIds.Num() > 0
			|| SupportedVoiceAssets.Num() > 0)
		&& (VoiceAssetReviewProfileId.IsEmpty()
			|| !VoiceAssetReviewProfileDefinition.IsStructurallyValid()
			|| SupportedVoiceAssetIds.Num() != SupportedVoiceAssets.Num()))
	{
		return false;
	}

	if ((!VoiceModelReviewProfileId.IsEmpty()
			|| VoiceModelReviewProfileDefinition.IsStructurallyValid()
			|| SupportedVoiceModelReviewIds.Num() > 0
			|| SupportedVoiceModelReviews.Num() > 0)
		&& (VoiceModelReviewProfileId.IsEmpty()
			|| !VoiceModelReviewProfileDefinition.IsStructurallyValid()
			|| SupportedVoiceModelReviewIds.Num() != SupportedVoiceModelReviews.Num()))
	{
		return false;
	}

	return HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(SupportedVoiceAssetIds)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(SupportedVoiceAssets)
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(SupportedVoiceModelReviewIds)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(SupportedVoiceModelReviews);
}

bool FHyperTwistSpeechMicrophoneShellState::IsStructurallyValid() const
{
	if (MicrophoneShellProfileId.IsEmpty()
		|| CaptureMode.IsEmpty()
		|| ListeningContractId.IsEmpty()
		|| InputRouteId.IsEmpty()
		|| PermissionStateId.IsEmpty()
		|| CaptureRouteStateId.IsEmpty()
		|| LastLanguageCode.IsEmpty()
		|| StatusLine.IsEmpty()
		|| DetailLine.IsEmpty()
		|| StepWindowMs <= 0
		|| CaptureWindowMs < StepWindowMs
		|| KeepWindowMs < 0
		|| KeepWindowMs > CaptureWindowMs
		|| SubmittedUtteranceCount < 0
		|| FinalTranscriptCount < 0
		|| DetectedSpeechStartMs < 0
		|| DetectedSpeechEndMs < DetectedSpeechStartMs
		|| LastSilenceGapMs < 0
		|| VadThreshold <= 0.0f
		|| ActiveIssueCount < 0
		|| AvailableActionIds.Num() <= 0)
	{
		return false;
	}

	return ActiveIssueCount == Issues.Num()
		&& (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Issues)
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(AvailableActionIds);
}

bool FHyperTwistSpeechDevicePermissionWorkflowProfile::IsStructurallyValid() const
{
	return !DevicePermissionWorkflowProfileId.IsEmpty()
		&& !WorkflowKind.IsEmpty()
		&& !PermissionContractId.IsEmpty()
		&& !SettingsHandoffContractId.IsEmpty()
		&& !PermissionRecheckContractId.IsEmpty()
		&& !PermissionRequestActionId.IsEmpty()
		&& !OpenSettingsActionId.IsEmpty()
		&& !PermissionRecheckActionId.IsEmpty()
		&& Panels.Num() > 0
		&& ActionBindings.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}

bool FHyperTwistSpeechDevicePermissionWorkflowEntry::IsStructurallyValid() const
{
	return !EntryId.IsEmpty()
		&& !SourceKind.IsEmpty()
		&& !WorkflowStateId.IsEmpty()
		&& !StatusLine.IsEmpty()
		&& !DetailLine.IsEmpty()
		&& !RecommendedActionId.IsEmpty();
}

bool FHyperTwistSpeechDevicePermissionWorkflowIssue::IsStructurallyValid() const
{
	return !IssueId.IsEmpty()
		&& !IssueKind.IsEmpty()
		&& !StatusLine.IsEmpty()
		&& !DetailLine.IsEmpty()
		&& !RecommendedActionId.IsEmpty();
}

bool FHyperTwistSpeechDevicePermissionWorkflowState::IsStructurallyValid() const
{
	if (DevicePermissionWorkflowProfileId.IsEmpty()
		|| WorkflowStateId.IsEmpty()
		|| PermissionStateId.IsEmpty()
		|| LatestSourceKind.IsEmpty()
		|| StatusLine.IsEmpty()
		|| DetailLine.IsEmpty()
		|| WorkflowEntryCount < 0
		|| PermissionRequestEntryCount < 0
		|| SettingsHandoffEntryCount < 0
		|| PermissionRecheckEntryCount < 0
		|| ActiveIssueCount < 0
		|| AvailableActionIds.Num() <= 0)
	{
		return false;
	}

	if (WorkflowEntryCount != Entries.Num()
		|| ActiveIssueCount != Issues.Num()
		|| PermissionRequestEntryCount > WorkflowEntryCount
		|| SettingsHandoffEntryCount > WorkflowEntryCount
		|| PermissionRecheckEntryCount > WorkflowEntryCount)
	{
		return false;
	}

	return (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Entries)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Issues)
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(AvailableActionIds);
}

bool FHyperTwistSpeechNativeCaptureRouteWorkflowProfile::IsStructurallyValid() const
{
	return !NativeCaptureRouteWorkflowProfileId.IsEmpty()
		&& !WorkflowKind.IsEmpty()
		&& !OwnershipContractId.IsEmpty()
		&& !PreparationContractId.IsEmpty()
		&& !SessionReopenContractId.IsEmpty()
		&& !RouteInspectActionId.IsEmpty()
		&& !PreparationRetryActionId.IsEmpty()
		&& !SessionReopenActionId.IsEmpty()
		&& !PermissionDependencyActionId.IsEmpty()
		&& Panels.Num() > 0
		&& ActionBindings.Num() > 0
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}

bool FHyperTwistSpeechNativeCaptureRouteWorkflowEntry::IsStructurallyValid() const
{
	return !EntryId.IsEmpty()
		&& !SourceKind.IsEmpty()
		&& !WorkflowStateId.IsEmpty()
		&& !CaptureRouteStateId.IsEmpty()
		&& !StatusLine.IsEmpty()
		&& !DetailLine.IsEmpty()
		&& !RecommendedActionId.IsEmpty();
}

bool FHyperTwistSpeechNativeCaptureRouteWorkflowIssue::IsStructurallyValid() const
{
	return !IssueId.IsEmpty()
		&& !IssueKind.IsEmpty()
		&& !StatusLine.IsEmpty()
		&& !DetailLine.IsEmpty()
		&& !RecommendedActionId.IsEmpty();
}

bool FHyperTwistSpeechNativeCaptureRouteWorkflowState::IsStructurallyValid() const
{
	if (NativeCaptureRouteWorkflowProfileId.IsEmpty()
		|| WorkflowStateId.IsEmpty()
		|| CaptureRouteStateId.IsEmpty()
		|| PermissionStateId.IsEmpty()
		|| ActiveProviderProfileId.IsEmpty()
		|| ActiveServiceLaneId.IsEmpty()
		|| LatestSourceKind.IsEmpty()
		|| StatusLine.IsEmpty()
		|| DetailLine.IsEmpty()
		|| WorkflowEntryCount < 0
		|| PreparationEntryCount < 0
		|| RouteRetryEntryCount < 0
		|| SessionReopenEntryCount < 0
		|| PermissionDependencyEntryCount < 0
		|| ActiveIssueCount < 0
		|| AvailableActionIds.Num() <= 0)
	{
		return false;
	}

	if (WorkflowEntryCount != Entries.Num()
		|| ActiveIssueCount != Issues.Num()
		|| PreparationEntryCount > WorkflowEntryCount
		|| RouteRetryEntryCount > WorkflowEntryCount
		|| SessionReopenEntryCount > WorkflowEntryCount
		|| PermissionDependencyEntryCount > WorkflowEntryCount)
	{
		return false;
	}

	return (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Entries)
		&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Issues)
		&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(AvailableActionIds);
}
