Attribute VB_Name = "TestPricingDemo"
Option Explicit

' 2026 PORTFOLIO-ONLY TEST HARNESS, not historical project UAT.
' Import both .bas files as standard VBA modules (Access or Excel VBA).
' In the VBA editor use Debug > Compile, then run RunPricingDemoTests.
' Manual double-click investigation is documented in docs/refresh_bug_investigation.md.

Public Sub RunPricingDemoTests()
    Dim costs As Variant
    Dim margins As Variant
    Dim result As Variant

    ' Input order: Material, Labour, Admin, Other, Panel. Total = 450.
    costs = Array(100, 200, 50, 20, 80)
    margins = Array(0.2, 0.25, 0.1, 0.05, 0.15)

    ' T-01: No category pricing, project 20%, discount 10%: 450/.8*.9 = 506.25
    result = CalculateSellingPrice(costs, 0.2, _
        Array(Empty, Empty, Empty, Empty, Empty), 0.1)
    AssertCurrencyEqual CCur(506.25), result, "T-01 project-wide after discount"

    ' T-02: Five category rates, project rate blank: approximately 506.15325.
    ' Demo rounds once at the end => 506.15; original Access rounding unverified.
    result = CalculateSellingPrice(costs, Empty, margins, 0.1)
    AssertCurrencyEqual CCur(506.15), result, "T-02 category after discount"

    ' T-03: Both available: category-specific wins over project-wide.
    result = CalculateSellingPrice(costs, 0.3, margins, 0.1)
    AssertCurrencyEqual CCur(506.15), result, "T-03 category priority"

    ' T-04: Missing a category margin falls back to available project-wide.
    result = CalculateSellingPrice(costs, 0.2, _
        Array(0.2, Empty, 0.1, 0.05, 0.15), 0.1)
    AssertCurrencyEqual CCur(506.25), result, "T-04 fallback"

    ' T-05: Missing category AND missing project margin => Null (blank).
    result = CalculateSellingPrice(costs, Null, _
        Array(0.2, Null, 0.1, 0.05, 0.15), 0.1)
    AssertIsNull result, "T-05 neither pricing method available"

    ' T-06: A blank discount acts as zero discount (Nz-like behaviour).
    result = CalculateSellingPrice(costs, 0.2, _
        Array(Null, Null, Null, Null, Null), Null)
    AssertCurrencyEqual CCur(562.5), result, "T-06 blank discount"

    ' T-07: Other and Panel missing => category expression unavailable;
    ' project-wide fallback uses zero for missing costs (CalCost Nz concept).
    result = CalculateSellingPrice(Array(100, 200, 50, Null, Null), 0.2, _
        margins, 0.1)
    AssertCurrencyEqual CCur(393.75), result, "T-07 missing optional cost fields fallback"

    ' T-08: Other and Panel missing, no project margin => Null.
    result = CalculateSellingPrice(Array(100, 200, 50, Null, Null), Empty, _
        margins, 0.1)
    AssertIsNull result, "T-08 missing Other/Panel blocks category"

    ' T-09: Explicit 0 rates and 0 costs are valid, not treated as blanks.
    result = CalculateSellingPrice(Array(100, 200, 50, 0, 0), Empty, _
        Array(0, 0, 0, 0, 0), 0)
    AssertCurrencyEqual CCur(350), result, "T-09 explicit zeros"

    ' T-10: All five rates supplied; missing Material cost uses 0 in demo.
    result = CalculateSellingPrice(Array(Null, 200, 50, 20, 80), Empty, _
        Array(0, 0, 0, 0, 0), 0)
    AssertCurrencyEqual CCur(350), result, "T-10 material Nz approximation"

    ' T-11: Safe demo rejects >=100% margin (unverified production check).
    AssertValidationError costs, 1, _
        Array(Empty, Empty, Empty, Empty, Empty), 0, _
        vbObjectError + 7102, "T-11 invalid project margin"

    ' T-12: Safe demo rejects negative cost (not a historical assertion).
    AssertValidationError Array(-1, 0, 0, 0, 0), 0.2, _
        Array(Null, Null, Null, Null, Null), 0, _
        vbObjectError + 7101, "T-12 negative cost"

    ' T-13: Safe demo rejects invalid discount (not a historical assertion).
    AssertValidationError costs, 0.2, _
        Array(Empty, Empty, Empty, Empty, Empty), 1.2, _
        vbObjectError + 7103, "T-13 invalid discount"

    ' T-14: Pure demo calculation is idempotent for repeated SAME inputs.
    ' This does not replicate the original Access form double-click defect.
    result = CalculateSellingPrice(costs, 0.2, _
        Array(Null, Null, Null, Null, Null), 0.1)
    AssertCurrencyEqual CCur(506.25), result, "T-14 first invocation"
    result = CalculateSellingPrice(costs, 0.2, _
        Array(Null, Null, Null, Null, Null), 0.1)
    AssertCurrencyEqual CCur(506.25), result, "T-14 repeated invocation"

    Debug.Print "PASS: 14 clean-room test scenarios (Access form bug NOT tested)"
End Sub

Private Sub AssertCurrencyEqual(ByVal expected As Currency, _
                                ByVal actual As Variant, ByVal testName As String)
    If IsNull(actual) Then
        Err.Raise vbObjectError + 7201, "TestPricingDemo", testName & ": unexpectedly Null"
    End If
    If CCur(actual) <> expected Then
        Err.Raise vbObjectError + 7202, "TestPricingDemo", _
            testName & ": expected " & CStr(expected) & ", received " & CStr(actual)
    End If
End Sub

Private Sub AssertIsNull(ByVal actual As Variant, ByVal testName As String)
    If Not IsNull(actual) Then
        Err.Raise vbObjectError + 7203, "TestPricingDemo", testName & ": expected Null"
    End If
End Sub

Private Sub AssertValidationError(ByVal costs As Variant, _
                                  ByVal projectMargin As Variant, _
                                  ByVal categoryMargins As Variant, _
                                  ByVal discountRate As Variant, _
                                  ByVal expectedNumber As Long, _
                                  ByVal testName As String)
    Dim result As Variant
    Dim actualNumber As Long
    On Error GoTo CaughtError
    result = CalculateSellingPrice(costs, projectMargin, categoryMargins, discountRate)
    On Error GoTo 0
    Err.Raise vbObjectError + 7204, "TestPricingDemo", testName & ": expected error"
    Exit Sub
CaughtError:
    actualNumber = Err.Number
    On Error GoTo 0
    If actualNumber <> expectedNumber Then
        Err.Raise vbObjectError + 7205, "TestPricingDemo", _
            testName & ": unexpected error number " & CStr(actualNumber)
    End If
End Sub
