Option Strict On
Option Explicit On

Namespace Nexamas.UI.Rendering

    ''' <summary>
    ''' Final integrity audit for the Surface Material system. It composes the already-existing
    ''' routing, adoption, designer, and scope-boundary audits, then adds strict material/frame
    ''' identity checks. It does not draw, scan files, expose APIs, or mutate registries.
    ''' </summary>
    Friend NotInheritable Class MASSurfaceMaterialIntegrityAudit

        Private Sub New()
        End Sub

        Friend Shared Function BuildCommercialIntegrity() As MASSurfaceMaterialIntegrityReport
            Dim definitions As MASSurfaceMaterialDefinition() = MASSurfaceMaterialRegistry.RegisteredDefinitions()
            Dim publicDefinitions As MASSurfaceMaterialDefinition() = MASSurfaceMaterialRegistry.RegisteredPublicDefinitions()
            Dim slotProfiles As MASSurfaceMaterialSlotProfile() = MASSurfaceMaterialSlotProfileRegistry.RegisteredProfiles()

            Dim nativeVariantCount As Integer = CountNativeIdentityVariants(definitions)
            Dim slotAssignmentCount As Integer = CountSlotAssignments(slotProfiles)
            Dim canonicalMaterials As Boolean = HasCanonicalMaterialDefinitions(definitions)
            Dim canonicalFrames As Boolean = HasCanonicalFramePairing(definitions, slotProfiles)

            Dim slotRouting As MASSurfaceMaterialSlotRoutingReport = MASSurfaceMaterialSlotRoutingAudit.Build()
            Dim adoption As MASSurfaceMaterialAdoptionReport = MASSurfaceMaterialAdoptionAudit.Build(componentExplicitRuntimeBypassCount:=0)
            Dim designer As MASSurfaceMaterialDesignerIntegrationReport = MASSurfaceMaterialDesignerIntegrationAudit.Evaluate()
            Dim scope As MASSurfaceTreatmentScopeBoundaryReport = MASSurfaceTreatmentScopeBoundaryAudit.BuildSurfaceOnlyScopeBoundary()

            Dim genericSlotProfiles As Boolean = slotRouting IsNot Nothing AndAlso slotRouting.IsReady AndAlso adoption IsNot Nothing AndAlso adoption.IsReady
            Dim designerProjection As Boolean = designer IsNot Nothing AndAlso designer.IsReady
            Dim scopeLocked As Boolean = scope IsNot Nothing AndAlso scope.IsSurfaceOnlyScopeLocked
            Dim runtimeRoute As Boolean = HasRuntimeMaterialKeyRoute()

            Dim status As MASSurfaceMaterialIntegrityStatus = MASSurfaceMaterialIntegrityStatus.CommerciallyReady
            If Not canonicalMaterials Then status = MASSurfaceMaterialIntegrityStatus.BlockedByMaterialIdentity
            If Not canonicalFrames Then status = MASSurfaceMaterialIntegrityStatus.BlockedByFramePairing
            If Not genericSlotProfiles Then status = MASSurfaceMaterialIntegrityStatus.BlockedBySlotRouting
            If Not designerProjection Then status = MASSurfaceMaterialIntegrityStatus.BlockedByDesignerIntegration
            If Not scopeLocked Then status = MASSurfaceMaterialIntegrityStatus.BlockedByScopeBoundary
            If Not runtimeRoute Then status = MASSurfaceMaterialIntegrityStatus.BlockedByRuntimeRoute

            Return New MASSurfaceMaterialIntegrityReport(
                name:="Surface Material Integrity",
                status:=status,
                materialDefinitionCount:=If(definitions Is Nothing, 0, definitions.Length),
                publicSelectableMaterialCount:=If(publicDefinitions Is Nothing, 0, publicDefinitions.Length),
                identityPreservingNativeVariantCount:=nativeVariantCount,
                slotProfileCount:=If(slotProfiles Is Nothing, 0, slotProfiles.Length),
                slotAssignmentCount:=slotAssignmentCount,
                hasCanonicalMaterialDefinitions:=canonicalMaterials,
                hasCanonicalFramePairing:=canonicalFrames,
                hasGenericSlotProfiles:=genericSlotProfiles,
                hasDesignerProjection:=designerProjection,
                hasSurfaceOnlyScopeBoundary:=scopeLocked,
                hasRuntimeMaterialKeyRoute:=runtimeRoute,
                notes:="Canonical materials, native variants, frame pairings, generic slots, designer projection, and runtime material-key routing are checked from their official owners.")
        End Function

        Private Shared Function CountNativeIdentityVariants(definitions As MASSurfaceMaterialDefinition()) As Integer
            If definitions Is Nothing Then Return 0

            Dim count As Integer = 0
            For Each definition As MASSurfaceMaterialDefinition In definitions
                If definition Is Nothing Then Continue For
                If definition.IsNativeVariant AndAlso definition.PreservesMaterialIdentity Then count += 1
            Next

            Return count
        End Function

        Private Shared Function CountSlotAssignments(slotProfiles As MASSurfaceMaterialSlotProfile()) As Integer
            If slotProfiles Is Nothing Then Return 0

            Dim count As Integer = 0
            For Each profile As MASSurfaceMaterialSlotProfile In slotProfiles
                If profile Is Nothing Then Continue For
                count += profile.Assignments().Length
            Next

            Return count
        End Function

        Private Shared Function HasCanonicalMaterialDefinitions(definitions As MASSurfaceMaterialDefinition()) As Boolean
            If definitions Is Nothing OrElse definitions.Length < 8 Then Return False

            For Each definition As MASSurfaceMaterialDefinition In definitions
                If definition Is Nothing Then Return False
                If Not IsCanonicalMaterialKey(definition.Id) Then Return False
                If ContainsElementSpecificTerm(definition.Id) OrElse ContainsElementSpecificTerm(definition.DisplayName) Then Return False
                If definition.Material Is Nothing Then Return False
                If Not String.Equals(definition.Id, definition.Material.Id, System.StringComparison.OrdinalIgnoreCase) Then Return False
                If definition.Category = MASSurfaceMaterialCategory.Unknown Then Return False
                If definition.MaterialVariant = MASSurfaceMaterialVariant.Unknown Then Return False
                If definition.ThemeInfluenceMode = MASSurfaceTreatmentThemeInfluenceMode.Unknown Then Return False
            Next

            Return True
        End Function

        Private Shared Function HasCanonicalFramePairing(definitions As MASSurfaceMaterialDefinition(),
                                                         slotProfiles As MASSurfaceMaterialSlotProfile()) As Boolean
            If definitions Is Nothing OrElse definitions.Length = 0 Then Return False
            If slotProfiles Is Nothing OrElse slotProfiles.Length = 0 Then Return False

            For Each definition As MASSurfaceMaterialDefinition In definitions
                If definition Is Nothing Then Return False
                If Not MASSurfaceFrameIds.IsKnownFrameKey(definition.DefaultFrameKey) Then Return False
            Next

            For Each profile As MASSurfaceMaterialSlotProfile In slotProfiles
                If profile Is Nothing Then Return False
                If Not IsCanonicalProfileKey(profile.Id) Then Return False
                If ContainsElementSpecificTerm(profile.Id) OrElse ContainsElementSpecificTerm(profile.DisplayName) Then Return False

                For Each assignment As MASSurfaceMaterialSlotAssignment In profile.Assignments()
                    If assignment Is Nothing Then Return False
                    If Not MASSurfaceSlotCatalog.IsGenericSlotName(assignment.Slot) Then Return False
                    If Not MASSurfaceMaterialRegistry.Contains(assignment.MaterialKey) Then Return False
                    If Not MASSurfaceFrameIds.IsKnownFrameKey(assignment.FrameKey) Then Return False
                    If ContainsElementSpecificTerm(assignment.MaterialKey) OrElse ContainsElementSpecificTerm(assignment.FrameKey) Then Return False
                    If assignment.SurfaceStrengthLevel < 1 OrElse assignment.SurfaceStrengthLevel > 6 Then Return False
                Next
            Next

            Return True
        End Function

        Private Shared Function HasRuntimeMaterialKeyRoute() As Boolean
            Dim route As MASSurfaceMaterialSlotRoute = MASSurfaceMaterialSlotResolver.ResolveMaterialKey(
                consumerKind:=MASSurfaceTreatmentConsumerKind.CardSurface,
                materialKey:="crystal ice native",
                slot:=MASSurfaceSlot.Root,
                fallbackRole:=MASSurfaceRole.Card,
                frameStrength:=MASSurfaceFrameStrength.Level4)

            If route Is Nothing Then Return False
            If Not String.Equals(route.MaterialKey, MASSurfaceMaterialIds.CrystalIceNative, System.StringComparison.OrdinalIgnoreCase) Then Return False
            If Not route.IsRuntimeReady Then Return False

            Dim resolved As String = MASSurfaceTreatmentRuntimeSurfaceVisual.ResolveRuntimeMaterialKey(
                consumerKind:=MASSurfaceTreatmentConsumerKind.CardSurface,
                materialKey:="crystal ice native",
                requestedFrameStrength:=MASSurfaceFrameStrength.Level4,
                hasExplicitMaterialOverride:=True)

            Return String.Equals(resolved, MASSurfaceMaterialIds.CrystalIceNative, System.StringComparison.OrdinalIgnoreCase)
        End Function

        Private Shared Function IsCanonicalMaterialKey(value As String) As Boolean
            Dim key As String = If(value, String.Empty).Trim()
            Return key.StartsWith("surface.material.", System.StringComparison.OrdinalIgnoreCase)
        End Function

        Private Shared Function IsCanonicalProfileKey(value As String) As Boolean
            Dim key As String = If(value, String.Empty).Trim()
            Return key.StartsWith("surface.material-profile.", System.StringComparison.OrdinalIgnoreCase)
        End Function

        Private Shared Function ContainsElementSpecificTerm(value As String) As Boolean
            Dim text As String = If(value, String.Empty).Trim().ToLowerInvariant()
            If text.Length = 0 Then Return True

            Dim blockedTerms As String() = New String() {
                "accordion", "avatar", "badge", "button", "calendar", "checkbox", "chart", "combobox",
                "datagrid", "date", "drawer", "dropdown", "expander", "file", "grid", "imageviewer",
                "kanban", "listbox", "listview", "menu", "numeric", "password", "picker", "preview",
                "progressbar", "radiobutton", "rating", "slider", "tab", "taginput", "text",
                "time", "toast", "toolbar", "tooltip", "tree", "wizard"
            }

            For Each term As String In blockedTerms
                If text.IndexOf(term, System.StringComparison.Ordinal) >= 0 Then Return True
            Next

            Return False
        End Function

    End Class

End Namespace
