Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic

Namespace Nexamas.UI.Quality

    ''' <summary>
    ''' Friend-only production-promotion guard. It allows CompactPreview controls to
    ''' remain governed previews, but blocks any ProductionReady marketing unless the
    ''' central readiness matrix, adapter policy, and rule manifest agree.
    ''' </summary>
    Friend NotInheritable Class MASProductionPromotionRuleGate

        Private Sub New()
        End Sub

        Friend Shared Function Passes() As Boolean
            Return EvaluateFindings().Count = 0
        End Function

        Friend Shared Function EvaluateFindings() As IReadOnlyList(Of MASCommercialReadinessFinding)
            Dim findings As New List(Of MASCommercialReadinessFinding)()
            Dim matrix As MASCommercialReadinessMatrix = Nothing
            Dim rules As MASProductionPromotionRuleManifest = Nothing

            Try
                matrix = MASCommercialReadinessMatrixBuilder.BuildProductControlsMatrix()
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASProductionPromotionRuleGate.BuildMatrix")
                findings.Add(New MASCommercialReadinessFinding("promotion-rules", "Matrix", MASCommercialReadinessFindingSeverity.Error, "Commercial readiness matrix could not be built for promotion validation."))
            End Try

            Try
                rules = MASProductionPromotionRuleManifest.CreateDefault()
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASProductionPromotionRuleGate.CreateRules")
                findings.Add(New MASCommercialReadinessFinding("promotion-rules", "Build", MASCommercialReadinessFindingSeverity.Error, "Production promotion rule manifest could not be built."))
            End Try

            If matrix Is Nothing Then Return findings
            If rules Is Nothing Then Return findings

            If Not rules.HasExpectedProductControlCoverage Then
                findings.Add(New MASCommercialReadinessFinding("promotion-rules", "Coverage", MASCommercialReadinessFindingSeverity.Error, "Production promotion rules must cover exactly the eight product controls."))
            End If

            Dim ids As New HashSet(Of String)(StringComparer.OrdinalIgnoreCase)
            For Each rule As MASProductionPromotionRuleRecord In rules.Records
                If rule Is Nothing Then
                    findings.Add(New MASCommercialReadinessFinding("promotion-rules", "Record", MASCommercialReadinessFindingSeverity.Error, "Production promotion rules contain a null record."))
                    Continue For
                End If

                If Not ids.Add(rule.ComponentId) Then
                    findings.Add(New MASCommercialReadinessFinding(rule.ComponentId, "DuplicateId", MASCommercialReadinessFindingSeverity.Error, "Production promotion rule id is duplicated."))
                End If

                If Not rule.IsStructurallyValid Then
                    findings.Add(New MASCommercialReadinessFinding(rule.ComponentId, "Structure", MASCommercialReadinessFindingSeverity.Error, rule.DisplayName & " production promotion rule is structurally invalid."))
                End If

                Dim record As MASCommercialReadinessRecord = matrix.FindById(rule.ComponentId)
                If record Is Nothing Then
                    findings.Add(New MASCommercialReadinessFinding(rule.ComponentId, "MatrixRecord", MASCommercialReadinessFindingSeverity.Error, rule.DisplayName & " has promotion rules but no commercial readiness matrix record."))
                    Continue For
                End If

                ValidatePreviewBoundary(record, rule, findings)
                ValidateProductionBoundary(record, rule, findings)
            Next

            Return findings
        End Function

        Private Shared Sub ValidatePreviewBoundary(record As MASCommercialReadinessRecord,
                                                   rule As MASProductionPromotionRuleRecord,
                                                   findings As List(Of MASCommercialReadinessFinding))
            If record Is Nothing OrElse rule Is Nothing Then Return

            If record.Stage = MASCommercialReadinessStage.CompactPreview Then
                If record.IsCommercialProductionReady Then
                    findings.Add(New MASCommercialReadinessFinding(record.Id, "PreviewBoundary", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " is CompactPreview but evaluates as production ready."))
                End If

                If String.IsNullOrWhiteSpace(record.BlockerSummary) OrElse String.IsNullOrWhiteSpace(rule.PromotionBlockerSummary) Then
                    findings.Add(New MASCommercialReadinessFinding(record.Id, "PromotionBlockers", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " must keep explicit blockers while it remains CompactPreview."))
                End If
            End If
        End Sub

        Private Shared Sub ValidateProductionBoundary(record As MASCommercialReadinessRecord,
                                                      rule As MASProductionPromotionRuleRecord,
                                                      findings As List(Of MASCommercialReadinessFinding))
            If record Is Nothing OrElse rule Is Nothing Then Return
            If record.Stage <> MASCommercialReadinessStage.ProductionReady Then Return

            Dim adapterPolicy As MASPublicAdapterPolicyRecord = MASPublicAdapterPolicyGate.FindPolicy(record.Id)
            If adapterPolicy Is Nothing OrElse adapterPolicy.BlocksProductionPromotion Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "PublicAdapterPolicy", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without an approved public adapter/hosting policy."))
            End If

            If Not record.IsCommercialProductionReady Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "ProductionEvidence", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " is marked ProductionReady without the required commercial readiness evidence."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.ArchitectureRegistration) AndAlso Not record.HasArchitectureRegistration Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "ArchitectureRegistration", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without architecture registry coverage."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.PublicAddGateway) AndAlso Not record.HasPublicAddGateway Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "PublicAddGateway", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without a public Add gateway."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.RelationCoverage) AndAlso Not record.HasRelationCoverage Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "RelationCoverage", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without relation-provider coverage."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.DataSourceOrHostingContract) AndAlso Not (record.HasDataSourceContract OrElse record.HasHostingContract) Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "DataSourceOrHostingContract", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without a data-source or hosted-content contract."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.PersistenceContract) AndAlso Not record.HasPersistenceContract Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "PersistenceContract", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without a persistence/snapshot contract."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.DedicatedRenderCoverage) AndAlso Not record.HasDedicatedRenderCoverage Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "RenderCoverage", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without dedicated render coverage."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.VirtualizationOrBoundedLayoutProof) AndAlso Not record.HasVirtualizationContract Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "Virtualization", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without bounded virtualization/layout proof."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.PerformanceProof) AndAlso Not record.HasPerformanceProof Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "PerformanceProof", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without performance proof."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.RuntimeFaultStrictMode) AndAlso Not MASRuntimeFaultStrictModeGate.Passes() Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "RuntimeFaultStrictMode", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without runtime fault developer visibility and strict swallowed-exception mode."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.TimeMotionOwnership) AndAlso Not MASTimeMotionOwnershipGate.Passes() Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "TimeMotionOwnership", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without centralized time/motion ownership and approved timer exceptions."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.DocumentationAndSamples) AndAlso Not MASDocumentationSampleEvidenceGate.Passes() Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "DocumentationAndSamples", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without CompactPreview documentation, consumer-safe samples, and an evidence-pack boundary."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.MeasuredRuntimeBenchmark) AndAlso Not MASMeasuredRuntimeBenchmarkGate.Passes() Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "MeasuredRuntimeBenchmark", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without measured runtime benchmark evidence for its official proof path."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.BenchmarkBaselineThresholdPolicy) AndAlso Not MASBenchmarkBaselineThresholdPolicyGate.Passes() Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "BenchmarkBaselineThresholdPolicy", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without benchmark baseline capture and internal threshold-policy evidence."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.KeyboardAccessibilityStressProof) AndAlso Not MASKeyboardAccessibilityStressGate.Passes() Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "KeyboardAccessibilityStressProof", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without keyboard/focus contract and accessibility-state stress evidence."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.ControlSpecificProductionGapClosure) AndAlso Not MASControlSpecificProductionGapGate.AreProductionGapsClosedFor(record.Id) Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "ControlSpecificProductionGapClosure", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady until its control-specific production gaps are closed with evidence."))
            End If
            If rule.Requires(MASProductionPromotionRequirement.HostingContractClosure) AndAlso Not MASHostingContractClosureGate.Passes() Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "HostingContractClosure", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without hosted-content lifecycle closure evidence for the hosting-oriented product controls."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.RoutingShellBoundaryClosure) AndAlso Not MASRoutingShellBoundaryClosureGate.Passes() Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "RoutingShellBoundaryClosure", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without route/shell ownership boundary closure evidence."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.ProviderHostAdoptionClosure) AndAlso Not MASDashboardProviderHostAdoptionClosureGate.Passes() Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "ProviderHostAdoptionClosure", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without provider-adapter policy and host-adoption closure evidence for product hosting controls."))
            End If

            If rule.Requires(MASProductionPromotionRequirement.DashboardResizeHostSampleClosure) AndAlso Not MASDashboardResizeHostSampleClosureGate.Passes() Then
                findings.Add(New MASCommercialReadinessFinding(record.Id, "DashboardResizeHostSampleClosure", MASCommercialReadinessFindingSeverity.Error, record.DisplayName & " cannot be ProductionReady without DashboardGrid keyboard/a11y resize thresholds and AppLayout/SplitView real host-adoption sample evidence."))
            End If

        End Sub

    End Class

End Namespace
