/*
 *
 *    Copyright (c) 2021-2022 Project CHIP Authors
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

#include <app/TestEventTriggerDelegate.h>
#include <app/clusters/administrator-commissioning-server/AdministratorCommissioningCluster.h>
#include <app/reporting/ReportSchedulerImpl.h>
#include <app/server/CommissioningWindowManager.h>
#include <app/server/Server.h>
#include <clusters/AdministratorCommissioning/Enums.h>
#include <clusters/AdministratorCommissioning/Metadata.h>
#include <crypto/RandUtils.h>
#include <data-model-providers/codegen/CodegenDataModelProvider.h>
#include <lib/dnssd/Advertiser.h>
#include <lib/support/Span.h>
#include <messaging/tests/echo/common.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/CommissionableDataProvider.h>
#include <platform/ConfigurationManager.h>
#include <platform/DefaultTimerDelegate.h>
#include <platform/PlatformManager.h>
#include <platform/TestOnlyCommissionableDataProvider.h>
#include <protocols/secure_channel/PASESession.h>
#include <system/RAIIMockClock.h>

#include <lib/core/StringBuilderAdapters.h>
#include <lib/support/tests/ExtraPwTestMacros.h>
#include <pw_unit_test/framework.h>

#include <lib/support/UnitTestUtils.h>
#include <messaging/tests/MessagingContext.h>

using namespace chip;
using namespace chip::app;
using namespace chip::Crypto;
using namespace chip::Messaging;
using namespace chip::Protocols;
using namespace System::Clock::Literals;

using chip::CommissioningWindowAdvertisement;
using chip::CommissioningWindowManager;
using chip::Server;

namespace {

// Test Set #01 of Spake2p Parameters (PIN Code, Iteration Count, Salt, and matching Verifier):
constexpr uint32_t sTestSpake2p01_PinCode        = 20202021;
constexpr uint32_t sTestSpake2p01_IterationCount = 1000;
constexpr uint8_t sTestSpake2p01_Salt[]          = { 0x53, 0x50, 0x41, 0x4B, 0x45, 0x32, 0x50, 0x20,
                                                     0x4B, 0x65, 0x79, 0x20, 0x53, 0x61, 0x6C, 0x74 };
Spake2pVerifier sTestSpake2p01_PASEVerifier = { .mW0 = {
    0xB9, 0x61, 0x70, 0xAA, 0xE8, 0x03, 0x34, 0x68, 0x84, 0x72, 0x4F, 0xE9, 0xA3, 0xB2, 0x87, 0xC3,
    0x03, 0x30, 0xC2, 0xA6, 0x60, 0x37, 0x5D, 0x17, 0xBB, 0x20, 0x5A, 0x8C, 0xF1, 0xAE, 0xCB, 0x35,
},
    .mL  = {
    0x04, 0x57, 0xF8, 0xAB, 0x79, 0xEE, 0x25, 0x3A, 0xB6, 0xA8, 0xE4, 0x6B, 0xB0, 0x9E, 0x54, 0x3A,
    0xE4, 0x22, 0x73, 0x6D, 0xE5, 0x01, 0xE3, 0xDB, 0x37, 0xD4, 0x41, 0xFE, 0x34, 0x49, 0x20, 0xD0,
    0x95, 0x48, 0xE4, 0xC1, 0x82, 0x40, 0x63, 0x0C, 0x4F, 0xF4, 0x91, 0x3C, 0x53, 0x51, 0x38, 0x39,
    0xB7, 0xC0, 0x7F, 0xCC, 0x06, 0x27, 0xA1, 0xB8, 0x57, 0x3A, 0x14, 0x9F, 0xCD, 0x1F, 0xA4, 0x66,
    0xCF
} };

bool sSimulateFailedSessionEstablishmentTaskCalled = false;

bool sAdminFabricIndexDirty = false;
bool sAdminVendorIdDirty    = false;
bool sWindowStatusDirty     = false;

void ResetDirtyFlags()
{
    sAdminFabricIndexDirty = false;
    sAdminVendorIdDirty    = false;
    sWindowStatusDirty     = false;
}

class TestCommissioningWindowManagerDataModelProvider : public chip::app::CodegenDataModelProvider
{
public:
    TestCommissioningWindowManagerDataModelProvider()  = default;
    ~TestCommissioningWindowManagerDataModelProvider() = default;

    void Temporary_ReportAttributeChanged(const chip::app::AttributePathParams & path) override
    {
        using namespace chip::app::Clusters;
        using namespace chip::app::Clusters::AdministratorCommissioning::Attributes;
        if (path.mEndpointId != chip::kRootEndpointId || path.mClusterId != AdministratorCommissioning::Id)
        {
            return;
        }

        switch (path.mAttributeId)
        {
        case WindowStatus::Id:
            sWindowStatusDirty = true;
            break;
        case AdminVendorId::Id:
            sAdminVendorIdDirty = true;
            break;
        case AdminFabricIndex::Id:
            sAdminFabricIndexDirty = true;
            break;
        default:
            break;
        }
    }
};

chip::app::DataModel::Provider * TestDataModelProviderInstance(chip::PersistentStorageDelegate * delegate)
{
    static TestCommissioningWindowManagerDataModelProvider gTestModel;

    if (delegate != nullptr)
    {
        gTestModel.SetPersistentStorageDelegate(delegate);
    }

    return &gTestModel;
}

} // namespace
namespace {

void TearDownTask(intptr_t context)
{
    chip::Server::GetInstance().Shutdown();
}

static void StopEventLoop(intptr_t context)
{
    EXPECT_SUCCESS(chip::DeviceLayer::PlatformMgr().StopEventLoopTask());
}

class TestSecurePairingDelegate : public SessionEstablishmentDelegate
{
public:
    void OnSessionEstablishmentError(CHIP_ERROR error) override { mNumPairingErrors++; }

    void OnSessionEstablished(const SessionHandle & session) override { mNumPairingComplete++; }

    uint32_t mNumPairingErrors   = 0;
    uint32_t mNumPairingComplete = 0;
};

class MockAppDelegate : public AppDelegate
{
public:
    void OnCommissioningWindowOpened() override { mOnCommissioningWindowOpenedCount++; }
    void OnCommissioningWindowClosed() override { mOnCommissioningWindowClosedCount++; }

    void OnCommissioningSessionEstablishmentError(CHIP_ERROR error) override
    {
        mOnCommissioningSessionEstablishmentErrorCount++;
        mError = error;
    }

    uint8_t mOnCommissioningWindowOpenedCount              = 0;
    uint8_t mOnCommissioningWindowClosedCount              = 0;
    uint8_t mOnCommissioningSessionEstablishmentErrorCount = 0;

    CHIP_ERROR mError = CHIP_NO_ERROR;
};

class TestCommissioningWindowManager : public chip::Testing::LoopbackMessagingContext
{
public:
    static void SetUpTestSuite()
    {
        LoopbackMessagingContext::SetUpTestSuite();

        ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
        ASSERT_EQ(chip::DeviceLayer::PlatformMgr().InitChipStack(), CHIP_NO_ERROR);

        static chip::DeviceLayer::TestOnlyCommissionableDataProvider commissionableDataProvider;
        chip::DeviceLayer::SetCommissionableDataProvider(&commissionableDataProvider);

        static chip::CommonCaseDeviceServerInitParams initParams;
        // Report scheduler and timer delegate instance
        static chip::app::DefaultTimerDelegate sTimerDelegate;
        static chip::app::reporting::ReportSchedulerImpl sReportScheduler(&sTimerDelegate);
        initParams.reportScheduler = &sReportScheduler;
        static chip::SimpleTestEventTriggerDelegate sSimpleTestEventTriggerDelegate;
        initParams.testEventTriggerDelegate = &sSimpleTestEventTriggerDelegate;
        (void) initParams.InitializeStaticResourcesBeforeServerInit();
        initParams.dataModelProvider = TestDataModelProviderInstance(initParams.persistentStorageDelegate);
        // Use whatever server port the kernel decides to give us.
        initParams.operationalServicePort = 0;

        ASSERT_EQ(chip::Server::GetInstance().Init(initParams), CHIP_NO_ERROR);

        Server::GetInstance().GetCommissioningWindowManager().CloseCommissioningWindow();
    }
    static void TearDownTestSuite()
    {

        // TODO: The platform memory was intentionally left not deinitialized so that minimal mdns can destruct
        EXPECT_SUCCESS(chip::DeviceLayer::PlatformMgr().ScheduleWork(TearDownTask, 0));
        EXPECT_SUCCESS(chip::DeviceLayer::PlatformMgr().ScheduleWork(StopEventLoop));
        chip::DeviceLayer::PlatformMgr().RunEventLoop();

        chip::DeviceLayer::PlatformMgr().Shutdown();

        auto & mdnsAdvertiser = chip::Dnssd::ServiceAdvertiser::Instance();
        RETURN_SAFELY_IGNORED mdnsAdvertiser.RemoveServices();
        mdnsAdvertiser.Shutdown();

        LoopbackMessagingContext::TearDownTestSuite();

        // Server shutdown will be called in TearDownTask

        // TODO: At this point UDP endpoits still seem leaked and the sanitizer
        // builds will attempt a memory free. As a result, we keep Memory initialized
        // so that the global UDPManager can still be destructed without a coredump.
        //
        // This is likely either a missing shutdown or an actual UDP endpoint leak
        // which I have not been able to track down yet.
        //
        // chip::Platform::MemoryShutdown();
    }

    void SetUp() override
    {
        ConfigInitializeNodes(false);
        chip::Testing::LoopbackMessagingContext::SetUp();

        sSimulateFailedSessionEstablishmentTaskCalled = false;
    }

    void EstablishPASEHandshake(SessionManager & sessionManager, PASESession & pairingCommissioner,
                                TestSecurePairingDelegate & delegateCommissioner);

    void ServiceEvents();
};

void TestCommissioningWindowManager::ServiceEvents()
{
    DrainAndServiceIO();

    ASSERT_SUCCESS(chip::DeviceLayer::PlatformMgr().ScheduleWork(
        [](intptr_t) -> void { EXPECT_SUCCESS(chip::DeviceLayer::PlatformMgr().StopEventLoopTask()); }, (intptr_t) nullptr));
    chip::DeviceLayer::PlatformMgr().RunEventLoop();
}

Clusters::AdministratorCommissioningLogic::Context CreateContext()
{
    return Clusters::AdministratorCommissioningLogic::Context{
        .commissioningWindowManager = Server::GetInstance().GetCommissioningWindowManager(),
        .fabricTable                = Server::GetInstance().GetFabricTable(),
        .failSafeContext            = Server::GetInstance().GetFailSafeContext(),
    };
}

void TestCommissioningWindowManager::EstablishPASEHandshake(SessionManager & sessionManager, PASESession & pairingCommissioner,
                                                            TestSecurePairingDelegate & delegateCommissioner)
{

    auto & loopback            = GetLoopback();
    loopback.mSentMessageCount = 0;

    ExchangeContext * contextCommissioner = NewUnauthenticatedExchangeToBob(&pairingCommissioner);

    EXPECT_EQ(GetExchangeManager().RegisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::PBKDFParamRequest,
                                                                            &Server::GetInstance().GetCommissioningWindowManager()),
              CHIP_NO_ERROR);

    DrainAndServiceIO();

    EXPECT_EQ(pairingCommissioner.Pair(sessionManager, sTestSpake2p01_PinCode, Optional<ReliableMessageProtocolConfig>::Missing(),
                                       contextCommissioner, &delegateCommissioner),
              CHIP_NO_ERROR);
    DrainAndServiceIO();

    EXPECT_EQ(delegateCommissioner.mNumPairingErrors, 0u);
    EXPECT_EQ(delegateCommissioner.mNumPairingComplete, 1u);
}

class TemporarySessionManager
{
public:
    TemporarySessionManager(TestCommissioningWindowManager & ctx) : mCtx(ctx)
    {
        EXPECT_EQ(CHIP_NO_ERROR,
                  mSessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &ctx.GetMessageCounterManager(), &mStorage,
                                       &ctx.GetFabricTable(), ctx.GetSessionKeystore()));
        // The setup here is really weird: we are using one session manager for
        // the actual messages we send (the PASE handshake, so the
        // unauthenticated sessions) and a different one for allocating the PASE
        // sessions.  Since our Init() set us up as the thing to handle messages
        // on the transport manager, undo that.
        mCtx.GetTransportMgr().SetSessionManager(&mCtx.GetSecureSessionManager());
    }

    ~TemporarySessionManager()
    {
        mSessionManager.Shutdown();
        // Reset the session manager on the transport again, just in case
        // shutdown messed with it.
        mCtx.GetTransportMgr().SetSessionManager(&mCtx.GetSecureSessionManager());
    }

    operator SessionManager &() { return mSessionManager; }

    TestCommissioningWindowManager & mCtx;

private:
    TestPersistentStorageDelegate mStorage;
    SessionManager mSessionManager;
};

TEST_F(TestCommissioningWindowManager, TestCheckCommissioningWindowManagerBasicWindowOpenClose)
{
    EXPECT_FALSE(sWindowStatusDirty);
    EXPECT_FALSE(sAdminFabricIndexDirty);
    EXPECT_FALSE(sAdminVendorIdDirty);

    CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();

    EXPECT_EQ(commissionMgr.OpenBasicCommissioningWindow(commissionMgr.MaxCommissioningTimeout(),
                                                         CommissioningWindowAdvertisement::kDnssdOnly),
              CHIP_NO_ERROR);
    EXPECT_TRUE(commissionMgr.IsCommissioningWindowOpen());
    EXPECT_EQ(commissionMgr.CommissioningWindowStatusForCluster(),
              chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kWindowNotOpen);
    EXPECT_TRUE(commissionMgr.GetOpenerFabricIndex().IsNull());
    EXPECT_TRUE(commissionMgr.GetOpenerVendorId().IsNull());
    EXPECT_FALSE(chip::DeviceLayer::ConnectivityMgr().IsBLEAdvertisingEnabled());
    EXPECT_FALSE(sWindowStatusDirty);
    EXPECT_FALSE(sAdminFabricIndexDirty);
    EXPECT_FALSE(sAdminVendorIdDirty);

    commissionMgr.CloseCommissioningWindow();
    EXPECT_FALSE(commissionMgr.IsCommissioningWindowOpen());
    EXPECT_FALSE(sWindowStatusDirty);
    EXPECT_FALSE(sAdminFabricIndexDirty);
    EXPECT_FALSE(sAdminVendorIdDirty);
}

TEST_F(TestCommissioningWindowManager, TestCheckCommissioningWindowManagerBasicWindowOpenCloseFromCluster)
{
    EXPECT_FALSE(sWindowStatusDirty);
    EXPECT_FALSE(sAdminFabricIndexDirty);
    EXPECT_FALSE(sAdminVendorIdDirty);

    CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();
    constexpr auto fabricIndex                 = static_cast<chip::FabricIndex>(1);
    constexpr auto vendorId                    = static_cast<chip::VendorId>(0xFFF3);
    EXPECT_EQ(commissionMgr.OpenBasicCommissioningWindowForAdministratorCommissioningCluster(
                  commissionMgr.MaxCommissioningTimeout(), fabricIndex, vendorId),
              CHIP_NO_ERROR);
    EXPECT_TRUE(commissionMgr.IsCommissioningWindowOpen());
    EXPECT_EQ(commissionMgr.CommissioningWindowStatusForCluster(),
              chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kBasicWindowOpen);
    EXPECT_FALSE(commissionMgr.GetOpenerFabricIndex().IsNull());
    EXPECT_EQ(commissionMgr.GetOpenerFabricIndex().Value(), fabricIndex);
    EXPECT_FALSE(commissionMgr.GetOpenerVendorId().IsNull());
    EXPECT_EQ(commissionMgr.GetOpenerVendorId().Value(), vendorId);
    EXPECT_FALSE(chip::DeviceLayer::ConnectivityMgr().IsBLEAdvertisingEnabled());
    EXPECT_TRUE(sWindowStatusDirty);
    EXPECT_TRUE(sAdminFabricIndexDirty);
    EXPECT_TRUE(sAdminVendorIdDirty);

    ResetDirtyFlags();
    EXPECT_FALSE(sWindowStatusDirty);
    EXPECT_FALSE(sAdminFabricIndexDirty);
    EXPECT_FALSE(sAdminVendorIdDirty);

    commissionMgr.CloseCommissioningWindow();
    EXPECT_FALSE(commissionMgr.IsCommissioningWindowOpen());
    EXPECT_TRUE(commissionMgr.GetOpenerFabricIndex().IsNull());
    EXPECT_TRUE(commissionMgr.GetOpenerVendorId().IsNull());
    EXPECT_TRUE(sWindowStatusDirty);
    EXPECT_TRUE(sAdminFabricIndexDirty);
    EXPECT_TRUE(sAdminVendorIdDirty);

    ResetDirtyFlags();
}

void VerifyCommissioningWindowManagerWindowClosed()
{
    CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();
    EXPECT_FALSE(commissionMgr.IsCommissioningWindowOpen());
    EXPECT_EQ(commissionMgr.CommissioningWindowStatusForCluster(),
              chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kWindowNotOpen);
    EXPECT_FALSE(sWindowStatusDirty);
    EXPECT_FALSE(sAdminFabricIndexDirty);
    EXPECT_FALSE(sAdminVendorIdDirty);
}

TEST_F(TestCommissioningWindowManager, TestCheckCommissioningWindowManagerWindowTimeout)
{
    System::Clock::Internal::RAIIMockClock clock;

    EXPECT_FALSE(sWindowStatusDirty);
    EXPECT_FALSE(sAdminFabricIndexDirty);
    EXPECT_FALSE(sAdminVendorIdDirty);

    CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();
    MockAppDelegate delegateApp;
    commissionMgr.SetAppDelegate(&delegateApp);

    constexpr auto kTimeoutSeconds   = chip::System::Clock::Seconds32(1);
    constexpr uint16_t kTimeoutMs    = 1000;
    constexpr unsigned kSleepPadding = 100;
    commissionMgr.OverrideMinCommissioningTimeout(kTimeoutSeconds);
    EXPECT_SUCCESS(commissionMgr.OpenBasicCommissioningWindow(kTimeoutSeconds, CommissioningWindowAdvertisement::kDnssdOnly));

    EXPECT_TRUE(commissionMgr.IsCommissioningWindowOpen());
    EXPECT_EQ(commissionMgr.CommissioningWindowStatusForCluster(),
              chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kWindowNotOpen);
    EXPECT_EQ(delegateApp.mOnCommissioningWindowOpenedCount, 1u);
    EXPECT_EQ(delegateApp.mOnCommissioningWindowClosedCount, 0u);

    EXPECT_FALSE(chip::DeviceLayer::ConnectivityMgr().IsBLEAdvertisingEnabled());
    EXPECT_FALSE(sWindowStatusDirty);
    EXPECT_FALSE(sAdminFabricIndexDirty);
    EXPECT_FALSE(sAdminVendorIdDirty);

    // Advance time so that the commissioning window times out
    clock.AdvanceMonotonic(chip::System::Clock::Milliseconds64(kTimeoutMs + kSleepPadding));
    ServiceEvents();

    VerifyCommissioningWindowManagerWindowClosed();
    EXPECT_EQ(delegateApp.mOnCommissioningWindowClosedCount, 1u);

    commissionMgr.SetAppDelegate(nullptr);
}

void SimulateFailedSessionEstablishmentTask(chip::System::Layer *, void *)
{

    CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();
    EXPECT_TRUE(commissionMgr.IsCommissioningWindowOpen());
    EXPECT_EQ(commissionMgr.CommissioningWindowStatusForCluster(),
              chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kWindowNotOpen);
    EXPECT_FALSE(sWindowStatusDirty);
    EXPECT_FALSE(sAdminFabricIndexDirty);
    EXPECT_FALSE(sAdminVendorIdDirty);

    commissionMgr.OnSessionEstablishmentStarted();
    commissionMgr.OnSessionEstablishmentError(CHIP_ERROR_INTERNAL);
    EXPECT_TRUE(commissionMgr.IsCommissioningWindowOpen());
    EXPECT_EQ(commissionMgr.CommissioningWindowStatusForCluster(),
              chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kWindowNotOpen);
    EXPECT_FALSE(sWindowStatusDirty);
    EXPECT_FALSE(sAdminFabricIndexDirty);
    EXPECT_FALSE(sAdminVendorIdDirty);

    sSimulateFailedSessionEstablishmentTaskCalled = true;
}

TEST_F(TestCommissioningWindowManager, CheckCommissioningWindowManagerWindowTimeoutWithSessionEstablishmentErrors)
{
    System::Clock::Internal::RAIIMockClock clock;

    EXPECT_FALSE(sWindowStatusDirty);
    EXPECT_FALSE(sAdminFabricIndexDirty);
    EXPECT_FALSE(sAdminVendorIdDirty);
    EXPECT_FALSE(sSimulateFailedSessionEstablishmentTaskCalled);

    CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();
    MockAppDelegate delegateApp;
    commissionMgr.SetAppDelegate(&delegateApp);

    constexpr auto kTimeoutSeconds                          = chip::System::Clock::Seconds16(1);
    constexpr uint16_t kTimeoutMs                           = 1000;
    constexpr unsigned kSleepPadding                        = 100;
    constexpr uint16_t kFailedSessionEstablishmentTimeoutMs = kTimeoutMs / 4 * 3;

    commissionMgr.OverrideMinCommissioningTimeout(kTimeoutSeconds);
    EXPECT_EQ(commissionMgr.OpenBasicCommissioningWindow(kTimeoutSeconds, CommissioningWindowAdvertisement::kDnssdOnly),
              CHIP_NO_ERROR);

    EXPECT_TRUE(commissionMgr.IsCommissioningWindowOpen());
    EXPECT_EQ(commissionMgr.CommissioningWindowStatusForCluster(),
              chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kWindowNotOpen);

    EXPECT_FALSE(chip::DeviceLayer::ConnectivityMgr().IsBLEAdvertisingEnabled());
    EXPECT_FALSE(sWindowStatusDirty);
    EXPECT_FALSE(sAdminFabricIndexDirty);
    EXPECT_FALSE(sAdminVendorIdDirty);

    EXPECT_EQ(delegateApp.mOnCommissioningWindowOpenedCount, 1u);
    EXPECT_EQ(delegateApp.mOnCommissioningWindowClosedCount, 0u);
    EXPECT_EQ(delegateApp.mOnCommissioningSessionEstablishmentErrorCount, 0u);

    // Simulate a session establishment error during that window, such that the
    // delay for the error plus the window size exceeds the "timeout + padding" needed to result in Commissioning Window Closing.
    EXPECT_SUCCESS(DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kFailedSessionEstablishmentTimeoutMs),
                                                         SimulateFailedSessionEstablishmentTask, nullptr));

    // Advance time so that SimulateFailedSessionEstablishmentTask is fired
    clock.AdvanceMonotonic(chip::System::Clock::Milliseconds64(kFailedSessionEstablishmentTimeoutMs));
    ServiceEvents();

    EXPECT_TRUE(sSimulateFailedSessionEstablishmentTaskCalled);
    EXPECT_EQ(delegateApp.mOnCommissioningSessionEstablishmentErrorCount, 1u);

    // Advance time so that the Commissioning Window times out and closes
    clock.AdvanceMonotonic(chip::System::Clock::Milliseconds64(kTimeoutMs + kSleepPadding - kFailedSessionEstablishmentTimeoutMs));
    ServiceEvents();

    VerifyCommissioningWindowManagerWindowClosed();
    EXPECT_EQ(delegateApp.mOnCommissioningWindowClosedCount, 1u);

    commissionMgr.SetAppDelegate(nullptr);
}

TEST_F(TestCommissioningWindowManager, TestCheckCommissioningWindowManagerEnhancedWindow)
{
    CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();
    uint16_t originDiscriminator;
    EXPECT_EQ(chip::DeviceLayer::GetCommissionableDataProvider()->GetSetupDiscriminator(originDiscriminator), CHIP_NO_ERROR);
    uint16_t newDiscriminator = static_cast<uint16_t>(originDiscriminator + 1);
    Spake2pVerifier verifier;
    constexpr uint32_t kIterations = kSpake2p_Min_PBKDF_Iterations;
    uint8_t salt[kSpake2p_Min_PBKDF_Salt_Length];
    chip::ByteSpan saltData(salt);

    EXPECT_FALSE(sWindowStatusDirty);
    EXPECT_FALSE(sAdminFabricIndexDirty);
    EXPECT_FALSE(sAdminVendorIdDirty);

    constexpr auto fabricIndex = static_cast<chip::FabricIndex>(1);
    constexpr auto vendorId    = static_cast<chip::VendorId>(0xFFF3);
    EXPECT_EQ(commissionMgr.OpenEnhancedCommissioningWindow(commissionMgr.MaxCommissioningTimeout(), newDiscriminator, verifier,
                                                            kIterations, saltData, fabricIndex, vendorId),
              CHIP_NO_ERROR);
    EXPECT_TRUE(commissionMgr.IsCommissioningWindowOpen());
    EXPECT_EQ(commissionMgr.CommissioningWindowStatusForCluster(),
              chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kEnhancedWindowOpen);
    EXPECT_FALSE(chip::DeviceLayer::ConnectivityMgr().IsBLEAdvertisingEnabled());
    EXPECT_FALSE(commissionMgr.GetOpenerFabricIndex().IsNull());
    EXPECT_EQ(commissionMgr.GetOpenerFabricIndex().Value(), fabricIndex);
    EXPECT_FALSE(commissionMgr.GetOpenerVendorId().IsNull());
    EXPECT_EQ(commissionMgr.GetOpenerVendorId().Value(), vendorId);
    EXPECT_TRUE(sWindowStatusDirty);
    EXPECT_TRUE(sAdminFabricIndexDirty);
    EXPECT_TRUE(sAdminVendorIdDirty);

    ResetDirtyFlags();
    EXPECT_FALSE(sWindowStatusDirty);
    EXPECT_FALSE(sAdminFabricIndexDirty);
    EXPECT_FALSE(sAdminVendorIdDirty);

    commissionMgr.CloseCommissioningWindow();
    EXPECT_FALSE(commissionMgr.IsCommissioningWindowOpen());
    EXPECT_EQ(commissionMgr.CommissioningWindowStatusForCluster(),
              chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kWindowNotOpen);
    EXPECT_TRUE(commissionMgr.GetOpenerFabricIndex().IsNull());
    EXPECT_TRUE(commissionMgr.GetOpenerVendorId().IsNull());
    EXPECT_TRUE(sWindowStatusDirty);
    EXPECT_TRUE(sAdminFabricIndexDirty);
    EXPECT_TRUE(sAdminVendorIdDirty);

    ResetDirtyFlags();
}

TEST_F(TestCommissioningWindowManager, RevokeCommissioningClearsPASESession)
{
    TemporarySessionManager sessionManager(*this);

    TestSecurePairingDelegate delegateCommissioner;
    PASESession pairingCommissioner;
    auto & loopback = GetLoopback();
    loopback.Reset();

    // Open an Enhanced Commissioning Window
    uint16_t originDiscriminator;
    EXPECT_EQ(chip::DeviceLayer::GetCommissionableDataProvider()->GetSetupDiscriminator(originDiscriminator), CHIP_NO_ERROR);
    uint16_t newDiscriminator = static_cast<uint16_t>(originDiscriminator + 1);

    constexpr auto fabricIndex = static_cast<chip::FabricIndex>(1);
    constexpr auto vendorId    = static_cast<chip::VendorId>(0xFFF3);

    CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();
    EXPECT_EQ(commissionMgr.OpenEnhancedCommissioningWindow(commissionMgr.MaxCommissioningTimeout(), newDiscriminator,
                                                            sTestSpake2p01_PASEVerifier, sTestSpake2p01_IterationCount,
                                                            ByteSpan(sTestSpake2p01_Salt), fabricIndex, vendorId),
              CHIP_NO_ERROR);

    EXPECT_TRUE(commissionMgr.IsCommissioningWindowOpen());

    // Establish PASE Handshake to the server's CommissioningWindowManager
    EstablishPASEHandshake(sessionManager, pairingCommissioner, delegateCommissioner);

    // Ensure that a PASE Session exists for pairingCommissioner
    auto commissionerSession = pairingCommissioner.CopySecureSession();
    EXPECT_TRUE(commissionerSession.HasValue());
    EXPECT_TRUE(commissionerSession.Value()->AsSecureSession()->IsPASESession());

    // Ensure that a PASE Session exists for the CommissioningWindowManager
    EXPECT_TRUE(commissionMgr.GetPASESession().HasValue());
    EXPECT_TRUE(commissionMgr.GetPASESession().Value()->AsSecureSession()->IsPASESession());

    Clusters::AdministratorCommissioningLogic logic(CreateContext());
    Clusters::AdministratorCommissioning::Commands::RevokeCommissioning::DecodableType unused;

    ASSERT_EQ(logic.RevokeCommissioning(unused), Protocols::InteractionModel::Status::Success);

    // We need to service events here to allow the Async Events to be processed and make sure that the CommissioningWindowManager
    // successfully shutdown the PASESession
    ServiceEvents();

    EXPECT_FALSE(commissionMgr.IsCommissioningWindowOpen());

    // This asserts that the CommissioningWindowManager has cleared the PASESession
    EXPECT_FALSE(commissionMgr.GetPASESession().HasValue());

    // Asserting that PASESession is still present on the Commissioner side
    commissionerSession = pairingCommissioner.CopySecureSession();
    EXPECT_TRUE(commissionerSession.HasValue());
}

// In this test-case RevokeCommissioning is called after commissioning Window times out but BEFORE fail-safe timer expires.
// The aim is to ensure that Revoke Commissioning forces Fail-Safe expiry and clears PASESession EVEN when Commissioning Window is
// Closed.

// This Test will fail if RevokeCommissioning ONLY forces Fail-safe expiry when Commissioning Window is Open.
// This is a corner case that was not covered in Spec, that could happen if we establish PASE towards the end of the commissioning
// window, and then the administrator calls RevokeCommissioning; in that case, we would need to wait for fail-safe timer to expire
// --> The call to RevokeCommissioning should still clear the PASESession without having to wait for fail-safe timer expiry.
TEST_F(TestCommissioningWindowManager, RevokeCommissioningAfterCommissioningTimeoutClearsPASESession)
{
    System::Clock::Internal::RAIIMockClock clock;

    TemporarySessionManager sessionManager(*this);

    TestSecurePairingDelegate delegateCommissioner;
    PASESession pairingCommissioner;
    auto & loopback = GetLoopback();
    loopback.Reset();

    // Open an Enhanced Commissioning Window
    uint16_t originDiscriminator;
    EXPECT_EQ(chip::DeviceLayer::GetCommissionableDataProvider()->GetSetupDiscriminator(originDiscriminator), CHIP_NO_ERROR);
    uint16_t newDiscriminator = static_cast<uint16_t>(originDiscriminator + 1);

    constexpr auto fabricIndex = static_cast<chip::FabricIndex>(1);
    constexpr auto vendorId    = static_cast<chip::VendorId>(0xFFF3);

    CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();
    EXPECT_EQ(commissionMgr.OpenEnhancedCommissioningWindow(commissionMgr.MinCommissioningTimeout(), newDiscriminator,
                                                            sTestSpake2p01_PASEVerifier, sTestSpake2p01_IterationCount,
                                                            ByteSpan(sTestSpake2p01_Salt), fabricIndex, vendorId),
              CHIP_NO_ERROR);

    EXPECT_TRUE(commissionMgr.IsCommissioningWindowOpen());

    auto commissioningTimeout = commissionMgr.MinCommissioningTimeout();

    // Advance time to just before the commissioning window times out (300 ms remaining)
    clock.AdvanceMonotonic(commissioningTimeout - 300_ms);
    ServiceEvents();

    // Establish PASE Handshake to the server's CommissioningWindowManager
    EstablishPASEHandshake(sessionManager, pairingCommissioner, delegateCommissioner);

    // Ensure that a PASE Session exists for pairingCommissioner
    auto commissionerSession = pairingCommissioner.CopySecureSession();
    EXPECT_TRUE(commissionerSession.HasValue());
    EXPECT_TRUE(commissionerSession.Value()->AsSecureSession()->IsPASESession());

    // Ensure that a PASE Session exists for the CommissioningWindowManager
    EXPECT_TRUE(commissionMgr.GetPASESession().HasValue());
    EXPECT_TRUE(commissionMgr.GetPASESession().Value()->AsSecureSession()->IsPASESession());

    // Advance time to 1000 ms after the commissioning window times out, while still before fail-safe timer expiry
    clock.AdvanceMonotonic(1300_ms);
    ServiceEvents();

    // Ensuring that commissioning window did time out and that fail-safe did not expire yet
    ASSERT_FALSE(commissionMgr.IsCommissioningWindowOpen());
    ASSERT_TRUE(Server::GetInstance().GetFailSafeContext().IsFailSafeArmed());

    Clusters::AdministratorCommissioningLogic logic(CreateContext());
    Clusters::AdministratorCommissioning::Commands::RevokeCommissioning::DecodableType unused;

    // RevokeCommissioning is invoked after the commissioning window has timed out and therefore returns StatusCode::kWindowNotOpen.
    // However, it still explicitly forces fail-safe timer expiry regardless of the commissioning window state.
    ASSERT_EQ(logic.RevokeCommissioning(unused),
              InteractionModel::ClusterStatusCode::ClusterSpecificFailure(
                  Clusters::AdministratorCommissioning::StatusCode::kWindowNotOpen));

    // We need to service events here to allow the Async Events to be processed and make sure that the CommissioningWindowManager
    // successfully shutdown the PASESession
    ServiceEvents();

    EXPECT_FALSE(Server::GetInstance().GetFailSafeContext().IsFailSafeArmed());
    EXPECT_FALSE(commissionMgr.IsCommissioningWindowOpen());
    // This asserts that the CommissioningWindowManager has cleared the PASESession
    EXPECT_FALSE(commissionMgr.GetPASESession().HasValue());

    // Asserting that PASESession is still present on the Commissioner side
    commissionerSession = pairingCommissioner.CopySecureSession();
    EXPECT_TRUE(commissionerSession.HasValue());
}

} // namespace
