Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Text
Imports Nexamas.UI.Diagnostics

Namespace Nexamas.UI.Quality

    ''' <summary>
    ''' Phase-13 residual diagnostics/quality proof for DIAG-R01..DIAG-R04.
    ''' </summary>
    ''' <remarks>
    ''' The gate targets SDK-launch blockers: retained fault windows must summarize overflow,
    ''' process-wide strictness switches must be scope-restored, release disk logs must rotate,
    ''' and release evidence must distinguish GATE-CERTIFIED from DECLARED-ONLY routes.
    ''' </remarks>
    Friend NotInheritable Class MASDiagnosticsQualityResidualReviewGate

        Private Const FaultStormCount As Integer = 320
        Private Const SilencerCounterStormCount As Integer = 1200
        Private Const FaultStormContextPrefix As String = "MASDiagnosticsQualityResidualReviewGate.FaultStorm."
        Private Const SilencerCounterStormContextPrefix As String = "MASDiagnosticsQualityResidualReviewGate.SilencerCounterStorm."

        Private Sub New()
        End Sub

        Friend Shared Function Passes() As Boolean
            Return RunProbe(AddressOf ProbeFaultStormRetentionCounters) AndAlso
                   RunProbe(AddressOf ProbeExceptionSilencerCounterRetentionBound) AndAlso
                   RunProbe(AddressOf ProbeStrictModeScopeRestoresProcessWideSwitches) AndAlso
                   RunProbe(AddressOf ProbeReleaseDiagnosticsDiskLogRotation) AndAlso
                   RunProbe(AddressOf ProbeEvidenceCertificationLabels)
        End Function

        Private Shared Function RunProbe(probe As Func(Of Boolean)) As Boolean
            Try
                Return probe.Invoke()
            Catch ex As Exception
                MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASDiagnosticsQualityResidualReviewGate")
                Return False
            End Try
        End Function

        Private Shared Function ProbeFaultStormRetentionCounters() As Boolean
            MASRuntimeFaultChannel.ResetForTests()

            For index As Integer = 0 To FaultStormCount - 1
                MASExceptionSilencer.SwallowDiagnosticOnly(
                    New InvalidOperationException("Fault storm retention probe " & index.ToString(Globalization.CultureInfo.InvariantCulture)),
                    FaultStormContextPrefix & index.ToString(Globalization.CultureInfo.InvariantCulture))
            Next

            Dim retention As MASRuntimeFaultRetentionSnapshot = MASRuntimeFaultChannel.GetRetentionSnapshot()
            If retention Is Nothing Then Return False
            If retention.PublishedFaultCount < FaultStormCount Then Return False
            If retention.RetainedFaultCount > retention.RecentWindowLimit Then Return False
            If retention.EvictedRecentFaultCount <= 0L Then Return False
            If Not retention.HasRetentionOverflow OrElse Not retention.LostRecentFaultsSummarized Then Return False
            If retention.EvictedCategoryCounts Is Nothing OrElse Not retention.EvictedCategoryCounts.ContainsKey(MASExceptionHandlingCategory.DiagnosticOnly.ToString()) Then Return False

            Dim records As IReadOnlyList(Of MASRuntimeFaultRecord) = MASRuntimeFaultChannel.GetRecentFaultsSnapshot()
            If records Is Nothing OrElse records.Count = 0 OrElse records.Count > retention.RecentWindowLimit Then Return False

            For Each record As MASRuntimeFaultRecord In records
                If record Is Nothing Then Continue For
                If Not String.Equals(record.Context, MASRuntimeFaultChannel.RecentFaultWindowOverflowContext, StringComparison.Ordinal) Then Continue For
                Return record.Message IsNot Nothing AndAlso
                       record.Message.IndexOf("LostRecentFaultsSummarized=True", StringComparison.Ordinal) >= 0 AndAlso
                       record.Message.IndexOf("EvictedRecentFaultCount=", StringComparison.Ordinal) >= 0
            Next

            Return False
        End Function

        Private Shared Function ProbeExceptionSilencerCounterRetentionBound() As Boolean
            Dim before As MASRuntimeFaultStrictnessSnapshot = MASExceptionSilencer.CaptureStrictnessSnapshot()

            MASRuntimeFaultChannel.ResetForTests()
            MASExceptionSilencer.ResetCountersForProof()
            MASExceptionSilencer.ConfigureStrictness(False, False, False)

            Try
                For index As Integer = 0 To SilencerCounterStormCount - 1
                    MASExceptionSilencer.SwallowDiagnosticOnly(
                        New InvalidOperationException("Silencer counter retention probe " & index.ToString(Globalization.CultureInfo.InvariantCulture)),
                        SilencerCounterStormContextPrefix & index.ToString(Globalization.CultureInfo.InvariantCulture))
                Next

                Dim counters As Dictionary(Of String, Integer) = MASExceptionSilencer.GetCountersSnapshot()
                If counters Is Nothing Then Return False

                Dim limit As Integer = MASExceptionSilencer.GetCounterRetentionLimitForProof()
                If limit <= 0 Then Return False
                If counters.Count > limit Then Return False
                If Not counters.ContainsKey(MASExceptionSilencer.CounterOverflowKeyForProof) Then Return False
                If MASExceptionSilencer.GetCounterOverflowCountForProof() <= 0L Then Return False

                Dim retention As MASRuntimeFaultRetentionSnapshot = MASRuntimeFaultChannel.GetRetentionSnapshot()
                If retention Is Nothing OrElse retention.PublishedFaultCount < SilencerCounterStormCount Then Return False

                Return True
            Finally
                MASExceptionSilencer.ResetCountersForProof()
                MASRuntimeFaultChannel.ResetForTests()
                MASExceptionSilencer.ApplyStrictnessSnapshot(before)
            End Try
        End Function

        Private Shared Function ProbeStrictModeScopeRestoresProcessWideSwitches() As Boolean
            Dim before As MASRuntimeFaultStrictnessSnapshot = MASExceptionSilencer.CaptureStrictnessSnapshot()
            If before Is Nothing OrElse Not before.IsReadOnlySnapshot Then Return False

            MASExceptionSilencer.ConfigureStrictness(False, False, False)
            Using scope As New MASRuntimeFaultStrictModeScope(True, False, True)
                Dim active As MASRuntimeFaultStrictnessSnapshot = MASExceptionSilencer.CaptureStrictnessSnapshot()
                If active Is Nothing Then Return False
                If Not active.ThrowOnAnySwallowedException Then Return False
                If active.ThrowOnLifecycleBreakingException Then Return False
                If Not active.TraceRepeatedBoundaryExceptions Then Return False
                If Not active.StrictModeEnabled Then Return False
            End Using

            Dim restored As MASRuntimeFaultStrictnessSnapshot = MASExceptionSilencer.CaptureStrictnessSnapshot()
            Dim scopeRestored As Boolean =
                restored IsNot Nothing AndAlso
                Not restored.ThrowOnAnySwallowedException AndAlso
                Not restored.ThrowOnLifecycleBreakingException AndAlso
                Not restored.TraceRepeatedBoundaryExceptions

            MASExceptionSilencer.ApplyStrictnessSnapshot(before)
            If Not scopeRestored Then Return False

            Dim finalSnapshot As MASRuntimeFaultStrictnessSnapshot = MASExceptionSilencer.CaptureStrictnessSnapshot()
            Return finalSnapshot IsNot Nothing AndAlso
                   finalSnapshot.ThrowOnAnySwallowedException = before.ThrowOnAnySwallowedException AndAlso
                   finalSnapshot.ThrowOnLifecycleBreakingException = before.ThrowOnLifecycleBreakingException AndAlso
                   finalSnapshot.TraceRepeatedBoundaryExceptions = before.TraceRepeatedBoundaryExceptions AndAlso
                   finalSnapshot.DiagnosticsDiskLoggingEnabled = before.DiagnosticsDiskLoggingEnabled
        End Function

        Private Shared Function ProbeReleaseDiagnosticsDiskLogRotation() As Boolean
            Dim policy As MASReleaseDiagnosticsLoggingPolicySnapshot = MASExceptionSilencer.GetReleaseDiagnosticLoggingPolicySnapshotForProof()
            If policy Is Nothing OrElse Not policy.HasRotationPolicy Then Return False
            If Not String.Equals(policy.LogFileName, "MASRuntimeDiagnostics.log", StringComparison.Ordinal) Then Return False

            Dim tempDir As String = Path.Combine(Path.GetTempPath(), "Nexamas UI-DiagRotation-" & Guid.NewGuid().ToString("N"))
            Directory.CreateDirectory(tempDir)
            Try
                Dim logFilePath As String = Path.Combine(tempDir, policy.LogFileName)
                Dim payload As String = New String("x"c, CInt(Math.Min(policy.MaxLogBytes + 64L, 1200000L)))
                File.WriteAllText(logFilePath, payload, New UTF8Encoding(False))

                MASExceptionSilencer.ApplyReleaseDiagnosticRetentionForProof(logFilePath, Encoding.UTF8.GetByteCount("next-line" & Environment.NewLine))

                Dim firstArchive As String = logFilePath & ".1"
                If Not File.Exists(firstArchive) Then Return False
                If File.Exists(logFilePath) AndAlso New FileInfo(logFilePath).Length > policy.MaxLogBytes Then Return False
                If New FileInfo(firstArchive).Length <= 0L Then Return False

                For index As Integer = policy.MaxArchiveCount + 1 To policy.MaxArchiveCount + 2
                    If File.Exists(logFilePath & "." & index.ToString(Globalization.CultureInfo.InvariantCulture)) Then Return False
                Next

                Return True
            Finally
                Try
                    Directory.Delete(tempDir, True)
                Catch cleanupException As Exception
                    MASExceptionSilencer.SwallowFileSystemBoundary(cleanupException, "MASDiagnosticsQualityResidualReviewGate.CleanupRotationProof")
                End Try
            End Try
        End Function

        Private Shared Function ProbeEvidenceCertificationLabels() As Boolean
            If Not String.Equals(MASQualityEvidenceCertificationLabels.Resolve(MASQualityEvidenceCertificationKind.GateCertified), MASQualityEvidenceCertificationLabels.GateCertifiedLabel, StringComparison.Ordinal) Then Return False
            If Not String.Equals(MASQualityEvidenceCertificationLabels.Resolve(MASQualityEvidenceCertificationKind.DeclaredOnly), MASQualityEvidenceCertificationLabels.DeclaredOnlyLabel, StringComparison.Ordinal) Then Return False

            Dim manifest As MASReleaseFreezeEvidenceManifest = MASReleaseFreezeEvidenceManifest.CreateDefault()
            If manifest Is Nothing OrElse Not manifest.ReadyForReleaseFreezeEvidence Then Return False
            If Not manifest.AllRecordsHaveCertificationLabels Then Return False

            For Each record As MASReleaseFreezeEvidenceRecord In manifest.Records
                If record Is Nothing Then Return False
                If String.IsNullOrWhiteSpace(record.CertificationLabel) Then Return False
                If record.CertificationKind <> MASQualityEvidenceCertificationKind.GateCertified AndAlso
                   record.CertificationKind <> MASQualityEvidenceCertificationKind.DeclaredOnly Then Return False
            Next

            Return True
        End Function

    End Class

End Namespace
