Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Globalization
Imports Nexamas.UI.Components
Imports Nexamas.UI.Controls

Namespace Nexamas.UI.Quality

    ''' <summary>
    ''' Friend-only gate for product-control keyboard and accessibility stress evidence.
    ''' It avoids public API expansion and does not claim screen-reader/provider completion.
    ''' The proof uses each control's official selection/state operations, architecture
    ''' keyboard/focus contract, and product-readable SummaryText/LayoutModeText surfaces.
    ''' </summary>
    Friend NotInheritable Class MASKeyboardAccessibilityStressGate

        Private Sub New()
        End Sub

        Friend Shared Function Passes() As Boolean
            Dim report As MASKeyboardAccessibilityStressReport = BuildReport()
            Return report IsNot Nothing AndAlso report.ReadyForCommercialEvidence
        End Function

        Friend Shared Function BuildReport() As MASKeyboardAccessibilityStressReport
            Dim records As New List(Of MASKeyboardAccessibilityStressRecord)()
            records.Add(ProbeTreeGrid())
            records.Add(ProbePivotTable())
            records.Add(ProbeKanbanBoard())
            records.Add(ProbeAgendaView())
            records.Add(ProbeDashboardGrid())
            records.Add(ProbeMasterDetailView())
            records.Add(ProbeAppLayout())
            records.Add(ProbeSplitView())
            Return New MASKeyboardAccessibilityStressReport(records)
        End Function

        Private Shared Function ProbeTreeGrid() As MASKeyboardAccessibilityStressRecord
            Dim operations As Integer = 0
            Dim itemCount As Integer = 0
            Dim failed As String = String.Empty
            Dim control As MASTreeGrid = Nothing

            Try
                control = MASTreeGrid.Create("Keyboard TreeGrid")
                control.AddColumn("state", "State") : operations += 1
                control.AddColumn("owner", "Owner") : operations += 1

                For i As Integer = 0 To 95
                    Dim key As String = "row-" & i.ToString(CultureInfo.InvariantCulture)
                    control.AddRootRow(key,
                                       "Row " & i.ToString(CultureInfo.InvariantCulture),
                                       New String() {If(i Mod 2 = 0, "Ready", "Review"), "Team"})
                    operations += 1
                Next

                itemCount = control.RowCount
                If itemCount <> 96 Then failed = AppendFailure(failed, "TreeGrid row stress population failed.")
                If Not control.SelectRow("row-0") Then failed = AppendFailure(failed, "TreeGrid could not select first row.")
                operations += 1
                If Not control.ScrollRows(12) Then failed = AppendFailure(failed, "TreeGrid could not scroll row window.")
                operations += 1
                If Not control.SelectRow("row-48") Then failed = AppendFailure(failed, "TreeGrid could not select middle row.")
                operations += 1
                If Not control.EnsureRowVisible("row-95") Then failed = AppendFailure(failed, "TreeGrid could not ensure final row visible.")
                operations += 1
                If Not control.SelectRow("row-95") Then failed = AppendFailure(failed, "TreeGrid could not select final row.")
                operations += 1
                If Not String.Equals(control.SelectedRowKey, "row-95", StringComparison.OrdinalIgnoreCase) Then failed = AppendFailure(failed, "TreeGrid final selection was not retained.")
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASKeyboardAccessibilityStressGate.TreeGrid")
                failed = AppendFailure(failed, "TreeGrid stress probe threw an exception.")
            End Try

            Return CreateRecord("treegrid", "TreeGrid", True, control, HasText(If(control Is Nothing, String.Empty, control.SummaryText)), itemCount >= 96 AndAlso operations >= 100 AndAlso If(control Is Nothing, False, control.SelectedRowKey.Length > 0), itemCount, operations, failed)
        End Function

        Private Shared Function ProbePivotTable() As MASKeyboardAccessibilityStressRecord
            Dim operations As Integer = 0
            Dim itemCount As Integer = 0
            Dim failed As String = String.Empty
            Dim control As MASPivotTable = Nothing

            Try
                control = MASPivotTable.Create("Keyboard Pivot")
                For columnIndex As Integer = 0 To 11
                    control.AddColumn(BuildColumnKey(columnIndex), "Column " & columnIndex.ToString(CultureInfo.InvariantCulture))
                    operations += 1
                Next

                For rowIndex As Integer = 0 To 31
                    control.AddRow(BuildRowKey(rowIndex), "Row " & rowIndex.ToString(CultureInfo.InvariantCulture))
                    operations += 1
                    For columnIndex As Integer = 0 To 11
                        control.SetCellValue(BuildRowKey(rowIndex), BuildColumnKey(columnIndex), CDec(rowIndex + columnIndex + 1))
                        operations += 1
                    Next
                Next

                itemCount = control.RowCount * control.ColumnCount
                If itemCount <> 384 Then failed = AppendFailure(failed, "PivotTable matrix stress population failed.")
                If Not control.SelectCell(BuildRowKey(0), BuildColumnKey(0)) Then failed = AppendFailure(failed, "PivotTable could not select first cell.")
                operations += 1
                If Not control.SelectCell(BuildRowKey(16), BuildColumnKey(6)) Then failed = AppendFailure(failed, "PivotTable could not select middle cell.")
                operations += 1
                If Not control.SelectCell(BuildRowKey(31), BuildColumnKey(11)) Then failed = AppendFailure(failed, "PivotTable could not select final cell.")
                operations += 1
                If Not String.Equals(control.SelectedRowKey, BuildRowKey(31), StringComparison.OrdinalIgnoreCase) OrElse
                   Not String.Equals(control.SelectedColumnKey, BuildColumnKey(11), StringComparison.OrdinalIgnoreCase) Then
                    failed = AppendFailure(failed, "PivotTable final selection was not retained.")
                End If
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASKeyboardAccessibilityStressGate.PivotTable")
                failed = AppendFailure(failed, "PivotTable stress probe threw an exception.")
            End Try

            Return CreateRecord("pivottable", "PivotTable", True, control, HasText(If(control Is Nothing, String.Empty, control.SummaryText)), itemCount >= 384 AndAlso operations >= 400 AndAlso If(control Is Nothing, False, control.SelectedRowKey.Length > 0 AndAlso control.SelectedColumnKey.Length > 0), itemCount, operations, failed)
        End Function

        Private Shared Function ProbeKanbanBoard() As MASKeyboardAccessibilityStressRecord
            Dim operations As Integer = 0
            Dim itemCount As Integer = 0
            Dim failed As String = String.Empty
            Dim control As MASKanbanBoard = Nothing

            Try
                control = MASKanbanBoard.Create("Keyboard Kanban")
                For columnIndex As Integer = 0 To 3
                    control.AddColumn(BuildColumnKey(columnIndex), "Column " & columnIndex.ToString(CultureInfo.InvariantCulture))
                    operations += 1
                    For cardIndex As Integer = 0 To 19
                        control.AddCard(BuildColumnKey(columnIndex), BuildCardKey(columnIndex, cardIndex), "Card " & cardIndex.ToString(CultureInfo.InvariantCulture), "Keyboard stress")
                        operations += 1
                    Next
                Next

                itemCount = control.CardCount
                If itemCount <> 80 Then failed = AppendFailure(failed, "KanbanBoard card stress population failed.")
                If Not control.SelectCard(BuildCardKey(0, 0)) Then failed = AppendFailure(failed, "KanbanBoard could not select first card.")
                operations += 1
                If Not control.SelectCard(BuildCardKey(2, 10)) Then failed = AppendFailure(failed, "KanbanBoard could not select middle card.")
                operations += 1
                If Not control.MoveSelectedCardBy(1) Then failed = AppendFailure(failed, "KanbanBoard could not perform keyboard-style reorder.")
                operations += 1
                If Not control.MoveSelectedCardToColumn(BuildColumnKey(3)) Then failed = AppendFailure(failed, "KanbanBoard could not perform keyboard-style column move.")
                operations += 1
                If control.SelectedCardKey.Length = 0 Then failed = AppendFailure(failed, "KanbanBoard selected card was not retained.")
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASKeyboardAccessibilityStressGate.KanbanBoard")
                failed = AppendFailure(failed, "KanbanBoard stress probe threw an exception.")
            End Try

            Return CreateRecord("kanban", "KanbanBoard", True, control, HasText(If(control Is Nothing, String.Empty, control.SummaryText)), itemCount >= 80 AndAlso operations >= 88 AndAlso If(control Is Nothing, False, control.SelectedCardKey.Length > 0), itemCount, operations, failed)
        End Function

        Private Shared Function ProbeAgendaView() As MASKeyboardAccessibilityStressRecord
            Dim operations As Integer = 0
            Dim itemCount As Integer = 0
            Dim failed As String = String.Empty
            Dim control As MASAgendaView = Nothing

            Try
                Dim dayValue As Date = New DateTime(2026, 7, 3)
                control = MASAgendaView.Create("Keyboard Agenda").WithDate(dayValue).WithHours(6, 22)
                For eventIndex As Integer = 0 To 23
                    Dim startTime As DateTime = dayValue.AddHours(6).AddMinutes(eventIndex * 30)
                    Dim endTime As DateTime = startTime.AddMinutes(25)
                    control.AddEvent(BuildEventKey(eventIndex), "Event " & eventIndex.ToString(CultureInfo.InvariantCulture), startTime, endTime, "Keyboard stress")
                    operations += 1
                Next

                itemCount = control.EventCount
                If itemCount <> 24 Then failed = AppendFailure(failed, "AgendaView event stress population failed.")
                If Not control.SelectEvent(BuildEventKey(0)) Then failed = AppendFailure(failed, "AgendaView could not select first event.")
                operations += 1
                If Not control.SelectEvent(BuildEventKey(12)) Then failed = AppendFailure(failed, "AgendaView could not select middle event.")
                operations += 1
                control.MoveNextRange() : operations += 1
                control.MovePreviousRange() : operations += 1
                If Not control.SelectEvent(BuildEventKey(23)) Then failed = AppendFailure(failed, "AgendaView could not select final event.")
                operations += 1
                If Not String.Equals(control.SelectedEventKey, BuildEventKey(23), StringComparison.OrdinalIgnoreCase) Then failed = AppendFailure(failed, "AgendaView final selection was not retained.")
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASKeyboardAccessibilityStressGate.AgendaView")
                failed = AppendFailure(failed, "AgendaView stress probe threw an exception.")
            End Try

            Return CreateRecord("agenda", "AgendaView", True, control, HasText(If(control Is Nothing, String.Empty, control.SummaryText)), itemCount >= 24 AndAlso operations >= 29 AndAlso If(control Is Nothing, False, control.SelectedEventKey.Length > 0), itemCount, operations, failed)
        End Function

        Private Shared Function ProbeDashboardGrid() As MASKeyboardAccessibilityStressRecord
            Dim operations As Integer = 0
            Dim itemCount As Integer = 0
            Dim failed As String = String.Empty
            Dim control As MASDashboardGrid = Nothing

            Try
                control = MASDashboardGrid.Create("Keyboard Dashboard")
                For widgetIndex As Integer = 0 To 47
                    control.AddWidget(BuildWidgetKey(widgetIndex), "Widget " & widgetIndex.ToString(CultureInfo.InvariantCulture), widgetIndex.ToString(CultureInfo.InvariantCulture), "Keyboard stress", 1 + (widgetIndex Mod 2), 1)
                    operations += 1
                Next

                itemCount = control.ItemCount
                If itemCount <> 48 Then failed = AppendFailure(failed, "DashboardGrid widget stress population failed.")
                If Not control.SelectWidget(BuildWidgetKey(0)) Then failed = AppendFailure(failed, "DashboardGrid could not select first widget.")
                operations += 1
                control.MoveNext() : operations += 1
                control.MoveNext() : operations += 1
                control.MovePrevious() : operations += 1
                If Not control.SelectWidget(BuildWidgetKey(47)) Then failed = AppendFailure(failed, "DashboardGrid could not select final widget.")
                operations += 1
                If Not String.Equals(control.SelectedWidgetKey, BuildWidgetKey(47), StringComparison.OrdinalIgnoreCase) Then failed = AppendFailure(failed, "DashboardGrid final selection was not retained.")
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASKeyboardAccessibilityStressGate.DashboardGrid")
                failed = AppendFailure(failed, "DashboardGrid stress probe threw an exception.")
            End Try

            Return CreateRecord("dashboardgrid", "DashboardGrid", True, control, HasText(If(control Is Nothing, String.Empty, control.SummaryText)), itemCount >= 48 AndAlso operations >= 53 AndAlso If(control Is Nothing, False, control.SelectedWidgetKey.Length > 0), itemCount, operations, failed)
        End Function

        Private Shared Function ProbeMasterDetailView() As MASKeyboardAccessibilityStressRecord
            Dim operations As Integer = 0
            Dim itemCount As Integer = 0
            Dim failed As String = String.Empty
            Dim control As MASMasterDetailView = Nothing

            Try
                control = MASMasterDetailView.Create("Keyboard Master Detail")
                For itemIndex As Integer = 0 To 39
                    control.AddItem(BuildItemKey(itemIndex), "Item " & itemIndex.ToString(CultureInfo.InvariantCulture), "Subtitle", "Detail", "Keyboard stress", If(itemIndex Mod 2 = 0, "A", "B"))
                    operations += 1
                Next

                itemCount = control.ItemCount
                If itemCount <> 40 Then failed = AppendFailure(failed, "MasterDetailView item stress population failed.")
                If Not control.SelectItem(BuildItemKey(0)) Then failed = AppendFailure(failed, "MasterDetailView could not select first item.")
                operations += 1
                control.MoveNext() : operations += 1
                control.MovePrevious() : operations += 1
                If Not control.SelectItem(BuildItemKey(39)) Then failed = AppendFailure(failed, "MasterDetailView could not select final item.")
                operations += 1
                If Not String.Equals(control.SelectedItemKey, BuildItemKey(39), StringComparison.OrdinalIgnoreCase) Then failed = AppendFailure(failed, "MasterDetailView final selection was not retained.")
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASKeyboardAccessibilityStressGate.MasterDetailView")
                failed = AppendFailure(failed, "MasterDetailView stress probe threw an exception.")
            End Try

            Return CreateRecord("masterdetail", "MasterDetailView", True, control, HasText(If(control Is Nothing, String.Empty, control.SummaryText)), itemCount >= 40 AndAlso operations >= 44 AndAlso If(control Is Nothing, False, control.SelectedItemKey.Length > 0), itemCount, operations, failed)
        End Function

        Private Shared Function ProbeAppLayout() As MASKeyboardAccessibilityStressRecord
            Dim operations As Integer = 0
            Dim failed As String = String.Empty
            Dim control As MASAppLayout = Nothing

            Try
                control = MASAppLayout.Create("Accessible AppLayout")
                control.SetNavigation("Navigation", "Keyboard/accessibility stress navigation slot") : operations += 1
                control.SetContent("Content", "Keyboard/accessibility stress content slot") : operations += 1
                control.SetDetails("Details", "Keyboard/accessibility stress details slot") : operations += 1
                control.ShowNavigation = False : operations += 1
                control.ShowNavigation = True : operations += 1
                control.ShowDetails = False : operations += 1
                control.ShowDetails = True : operations += 1
                control.ShowStatusBar = False : operations += 1
                control.ShowStatusBar = True : operations += 1
                If Not HasText(control.SummaryText) OrElse Not HasText(control.LayoutModeText) Then failed = AppendFailure(failed, "AppLayout accessible state text is missing.")
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASKeyboardAccessibilityStressGate.AppLayout")
                failed = AppendFailure(failed, "AppLayout stress probe threw an exception.")
            End Try

            Return CreateRecord("applayout", "AppLayout", False, control, HasText(If(control Is Nothing, String.Empty, control.SummaryText)) AndAlso HasText(If(control Is Nothing, String.Empty, control.LayoutModeText)), operations >= 9, 3, operations, failed)
        End Function

        Private Shared Function ProbeSplitView() As MASKeyboardAccessibilityStressRecord
            Dim operations As Integer = 0
            Dim failed As String = String.Empty
            Dim control As MASSplitView = Nothing

            Try
                control = MASSplitView.Create("Keyboard SplitView")
                control.SetPaneTexts("Left pane keyboard stress", "Content pane keyboard stress", "Right pane keyboard stress") : operations += 1
                control.LeftPaneRatio = 0.25F : operations += 1
                control.RightPaneRatio = 0.25F : operations += 1
                control.CollapseLeft(True) : operations += 1
                control.CollapseLeft(False) : operations += 1
                control.CollapseRight(True) : operations += 1
                control.CollapseRight(False) : operations += 1
                control.ExpandAll() : operations += 1
                If control.IsLeftPaneCollapsed OrElse control.IsRightPaneCollapsed Then failed = AppendFailure(failed, "SplitView panes were not restored after stress operations.")
                If control.LeftPaneRatio <= 0.0F OrElse control.RightPaneRatio <= 0.0F Then failed = AppendFailure(failed, "SplitView ratios were not retained after stress operations.")
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASKeyboardAccessibilityStressGate.SplitView")
                failed = AppendFailure(failed, "SplitView stress probe threw an exception.")
            End Try

            Return CreateRecord("splitview", "SplitView", True, control, HasText(If(control Is Nothing, String.Empty, control.SummaryText)), operations >= 8 AndAlso If(control Is Nothing, False, Not control.IsLeftPaneCollapsed AndAlso Not control.IsRightPaneCollapsed), 3, operations, failed)
        End Function

        Private Shared Function CreateRecord(componentId As String,
                                             displayName As String,
                                             expectsKeyboardNavigation As Boolean,
                                             control As MASControlBase,
                                             hasAccessibleStateText As Boolean,
                                             hasStateOrSelectionStressProof As Boolean,
                                             stressItemCount As Integer,
                                             stressOperationCount As Integer,
                                             failureSummary As String) As MASKeyboardAccessibilityStressRecord
            Return New MASKeyboardAccessibilityStressRecord(componentId,
                                                            displayName,
                                                            expectsKeyboardNavigation,
                                                            HasKeyboardContract(control),
                                                            HasFocusContract(control),
                                                            hasAccessibleStateText,
                                                            hasStateOrSelectionStressProof,
                                                            stressItemCount,
                                                            stressOperationCount,
                                                            failureSummary)
        End Function

        Private Shared Function HasKeyboardContract(control As MASControlBase) As Boolean
            If control Is Nothing Then Return False
            Try
                Return control.ArchitectureContract IsNot Nothing AndAlso control.ArchitectureContract.RequiresKeyboard
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASKeyboardAccessibilityStressGate.KeyboardContract")
                Return False
            End Try
        End Function

        Private Shared Function HasFocusContract(control As MASControlBase) As Boolean
            If control Is Nothing Then Return False
            Try
                Return control.ArchitectureContract IsNot Nothing AndAlso control.ArchitectureContract.RequiresFocusConsumption
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASKeyboardAccessibilityStressGate.FocusContract")
                Return False
            End Try
        End Function

        Private Shared Function HasText(value As String) As Boolean
            Return Not String.IsNullOrWhiteSpace(value)
        End Function

        Private Shared Function AppendFailure(existing As String,
                                              value As String) As String
            Dim normalized As String = If(value, String.Empty).Trim()
            If normalized.Length = 0 Then Return If(existing, String.Empty)
            If String.IsNullOrWhiteSpace(existing) Then Return normalized
            Return existing.Trim() & " " & normalized
        End Function

        Private Shared Function BuildRowKey(index As Integer) As String
            Return "row-" & index.ToString(CultureInfo.InvariantCulture)
        End Function

        Private Shared Function BuildColumnKey(index As Integer) As String
            Return "column-" & index.ToString(CultureInfo.InvariantCulture)
        End Function

        Private Shared Function BuildCardKey(columnIndex As Integer,
                                             cardIndex As Integer) As String
            Return "card-" & columnIndex.ToString(CultureInfo.InvariantCulture) & "-" & cardIndex.ToString(CultureInfo.InvariantCulture)
        End Function

        Private Shared Function BuildEventKey(index As Integer) As String
            Return "event-" & index.ToString(CultureInfo.InvariantCulture)
        End Function

        Private Shared Function BuildWidgetKey(index As Integer) As String
            Return "widget-" & index.ToString(CultureInfo.InvariantCulture)
        End Function

        Private Shared Function BuildItemKey(index As Integer) As String
            Return "item-" & index.ToString(CultureInfo.InvariantCulture)
        End Function

    End Class

End Namespace
