Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports Nexamas.UI.Diagnostics
Imports Nexamas.UI.Host

Namespace Nexamas.UI.Quality

    ''' <summary>
    ''' Proves that persistent render-stage failures remain visible to the runtime fault channel.
    ''' Log/trace output may be rate-limited, but structured fault records and occurrence counters
    ''' must advance on every repeated render failure.
    ''' </summary>
    Friend NotInheritable Class MASRepeatedRenderFaultDiagnosticsGate

        Private Const RepeatCount As Integer = 10
        Private Const ProbeContext As String = "MASRepeatedRenderFaultDiagnosticsGate.RenderStage"

        Private Sub New()
        End Sub

        Friend Shared Function Passes() As Boolean
            Dim previousThrowOnAny As Boolean = MASExceptionSilencer.ThrowOnSwallowedException
            Dim previousThrowOnLifecycle As Boolean = MASExceptionSilencer.ThrowOnLifecycleBreakingException
            Dim previousTraceRepeated As Boolean = MASExceptionSilencer.TraceRepeatedBoundaryExceptions

            Try
                MASExceptionSilencer.ConfigureStrictness(False, False, True)
                Return ProbeRepeatedRenderFailuresPublishEveryOccurrence()
            Catch ex As Exception
                MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASRepeatedRenderFaultDiagnosticsGate")
                Return False
            Finally
                MASExceptionSilencer.ConfigureStrictness(previousThrowOnAny, previousThrowOnLifecycle, previousTraceRepeated)
            End Try
        End Function

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

            For i As Integer = 1 To RepeatCount
                MASSkiaHostRenderFailureDiagnostics.Report(
                    ProbeContext,
                    New InvalidOperationException("Synthetic repeated render-stage failure " & i.ToString(Globalization.CultureInfo.InvariantCulture)))
            Next

            Dim snapshot As IReadOnlyList(Of MASRuntimeFaultRecord) = MASRuntimeFaultChannel.GetRecentFaultsSnapshot()
            Dim matchingRecords As Integer = 0
            Dim firstOccurrenceCount As Integer = 0
            Dim maxOccurrenceCount As Integer = 0
            Dim firstRecord As MASRuntimeFaultRecord = Nothing
            Dim lastRecord As MASRuntimeFaultRecord = Nothing

            For Each record As MASRuntimeFaultRecord In snapshot
                If record Is Nothing Then Continue For

                If record.Context.Equals(ProbeContext, StringComparison.Ordinal) AndAlso
                   record.Category = MASExceptionHandlingCategory.RenderFallback Then

                    matchingRecords += 1
                    If firstRecord Is Nothing Then
                        firstRecord = record
                        firstOccurrenceCount = record.OccurrenceCount
                    End If

                    lastRecord = record
                    maxOccurrenceCount = Math.Max(maxOccurrenceCount, record.OccurrenceCount)
                End If
            Next

            Return matchingRecords = RepeatCount AndAlso
                   firstRecord IsNot Nothing AndAlso
                   lastRecord IsNot Nothing AndAlso
                   maxOccurrenceCount = lastRecord.OccurrenceCount AndAlso
                   lastRecord.OccurrenceCount - firstOccurrenceCount = RepeatCount - 1 AndAlso
                   lastRecord.OccurrenceCount > firstOccurrenceCount
        End Function

    End Class

End Namespace
