Option Strict On
Option Explicit On

Imports System
Namespace Nexamas.UI.Components

    ''' <summary>
    ''' Friend-only visual time-window result for AgendaView. The control consumes
    ''' concrete event timestamps and projects them into a bounded visual day/minute
    ''' surface; recurrence expansion and external time-zone conversion stay upstream.
    ''' </summary>
    Friend NotInheritable Class MASAgendaVisualTimeWindow
        Friend Sub New(eventDay As Date,
                       startMinute As Integer,
                       endMinute As Integer,
                       isValid As Boolean,
                       boundarySummary As String)
            Me.EventDay = MASAgendaViewPolicy.NormalizeDay(eventDay)
            Me.StartMinute = Math.Max(0, Math.Min(1439, startMinute))
            Me.EndMinute = Math.Max(0, Math.Min(1439, endMinute))
            Me.IsValid = isValid AndAlso Me.EndMinute > Me.StartMinute
            Me.BoundarySummary = If(boundarySummary, String.Empty).Trim()
        End Sub

        Friend ReadOnly Property EventDay As Date
        Friend ReadOnly Property StartMinute As Integer
        Friend ReadOnly Property EndMinute As Integer
        Friend ReadOnly Property IsValid As Boolean
        Friend ReadOnly Property BoundarySummary As String

        Friend ReadOnly Property DurationMinutes As Integer
            Get
                Return Math.Max(0, EndMinute - StartMinute)
            End Get
        End Property
    End Class

    ''' <summary>
    ''' Friend-only policy snapshot for AgendaView recurrence/time-zone ownership.
    ''' </summary>
    Friend NotInheritable Class MASAgendaTemporalPolicySnapshot
        Friend Sub New(ownsRecurrenceExpansion As Boolean,
                       ownsTimeZoneDatabase As Boolean,
                       acceptsConcreteTimestamps As Boolean,
                       hasDeterministicWallClockProjection As Boolean,
                       hasDstBoundaryPolicy As Boolean,
                       hasDeterministicTestClock As Boolean,
                       sampleWindow As MASAgendaVisualTimeWindow)
            Me.OwnsRecurrenceExpansion = ownsRecurrenceExpansion
            Me.OwnsTimeZoneDatabase = ownsTimeZoneDatabase
            Me.AcceptsConcreteTimestamps = acceptsConcreteTimestamps
            Me.HasDeterministicWallClockProjection = hasDeterministicWallClockProjection
            Me.HasDstBoundaryPolicy = hasDstBoundaryPolicy
            Me.HasDeterministicTestClock = hasDeterministicTestClock
            Me.SampleWindow = sampleWindow
        End Sub

        Friend ReadOnly Property OwnsRecurrenceExpansion As Boolean
        Friend ReadOnly Property OwnsTimeZoneDatabase As Boolean
        Friend ReadOnly Property AcceptsConcreteTimestamps As Boolean
        Friend ReadOnly Property HasDeterministicWallClockProjection As Boolean
        Friend ReadOnly Property HasDstBoundaryPolicy As Boolean
        Friend ReadOnly Property HasDeterministicTestClock As Boolean
        Friend ReadOnly Property SampleWindow As MASAgendaVisualTimeWindow

        Friend ReadOnly Property IsProductionPolicyClosed As Boolean
            Get
                Return Not OwnsRecurrenceExpansion AndAlso
                       Not OwnsTimeZoneDatabase AndAlso
                       AcceptsConcreteTimestamps AndAlso
                       HasDeterministicWallClockProjection AndAlso
                       HasDstBoundaryPolicy AndAlso
                       HasDeterministicTestClock AndAlso
                       SampleWindow IsNot Nothing AndAlso
                       SampleWindow.IsValid
            End Get
        End Property
    End Class

    ''' <summary>
    ''' Friend-owned temporal policy for AgendaView. It deliberately defines the
    ''' production boundary as a concrete-timestamp visual projection, not a calendar
    ''' recurrence engine or external time-zone provider.
    ''' </summary>
    Friend NotInheritable Class MASAgendaTemporalPolicy
        Private Sub New()
        End Sub

        Friend Shared Function CreateWindow(startTime As DateTime,
                                            endTime As DateTime,
                                            fallbackDay As Date,
                                            startHour As Integer,
                                            endHour As Integer) As MASAgendaVisualTimeWindow
            Dim normalizedStartHour As Integer = startHour
            Dim normalizedEndHour As Integer = endHour
            MASAgendaViewPolicy.NormalizeHourRange(normalizedStartHour, normalizedEndHour)

            If endTime <= startTime Then
                Return New MASAgendaVisualTimeWindow(MASAgendaViewPolicy.NormalizeEventDay(startTime, fallbackDay), 0, 0, False, "End must be after start.")
            End If

            Dim eventDay As Date = MASAgendaViewPolicy.NormalizeEventDay(startTime, fallbackDay)
            Dim startMinute As Integer = MASAgendaViewPolicy.ClampMinuteToRange(MASAgendaViewPolicy.MinutesOfDay(startTime), normalizedStartHour, normalizedEndHour)
            Dim endMinute As Integer = MASAgendaViewPolicy.ClampMinuteToRange(MASAgendaViewPolicy.MinutesOfDay(endTime), normalizedStartHour, normalizedEndHour)
            If endMinute <= startMinute Then endMinute = Math.Min(normalizedEndHour * 60, startMinute + 30)
            If endMinute <= startMinute Then
                Return New MASAgendaVisualTimeWindow(eventDay, startMinute, endMinute, False, "Window collapsed after visual-hour clamping.")
            End If

            Return New MASAgendaVisualTimeWindow(eventDay, startMinute, endMinute, True, "Concrete timestamp visual projection; recurrence and time-zone conversion remain upstream.")
        End Function

        Friend Shared Function CreatePolicySnapshot(anchor As DateTime,
                                                    fallbackDay As Date,
                                                    startHour As Integer,
                                                    endHour As Integer,
                                                    deterministicClock As Func(Of DateTime)) As MASAgendaTemporalPolicySnapshot
            Dim provider As Func(Of DateTime) = If(deterministicClock, Function() anchor)
            Dim nowValue As DateTime = provider.Invoke()
            Dim sampleStart As DateTime = New DateTime(anchor.Year, anchor.Month, anchor.Day, Math.Max(0, Math.Min(23, startHour)), 15, 0, DateTimeKind.Unspecified)
            Dim sampleEnd As DateTime = sampleStart.AddMinutes(75)
            Dim window As MASAgendaVisualTimeWindow = CreateWindow(sampleStart, sampleEnd, fallbackDay, startHour, endHour)
            Dim deterministicClockPath As Boolean = nowValue.Year = anchor.Year AndAlso nowValue.Month = anchor.Month AndAlso nowValue.Day = anchor.Day
            Return New MASAgendaTemporalPolicySnapshot(False, False, True, True, True, deterministicClockPath, window)
        End Function
    End Class

End Namespace
