/*
 *
 *    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/data-model-provider/AttributeChangeListener.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 GlobalAttributeChangeListener : public DataModel::AttributeChangeListener
{
public:
    void OnAttributeChanged(const ConcreteAttributePath & path, DataModel::AttributeChangeType type) 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;
        }
    }
};

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();

        mModel.SetPersistentStorageDelegate(initParams.persistentStorageDelegate);
        mModel.RegisterAttributeChangeListener(mListener);

        initParams.dataModelProvider = &mModel;
        // 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()
    {
        mModel.UnregisterAttributeChangeListener(mListener);

        // 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();

private:
    static chip::app::CodegenDataModelProvider mModel;
    static GlobalAttributeChangeListener mListener;
};

chip::app::CodegenDataModelProvider TestCommissioningWindowManager::mModel;
GlobalAttributeChangeListener TestCommissioningWindowManager::mListener;

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);
}

// Regression: ResetState must cancel HandleSessionEstablishmentTimeout.
// Otherwise the orphaned timer fires HandleFailedAttempt after window
// cleanup — detected here via the delegate's error-callback counter.
TEST_F(TestCommissioningWindowManager, WindowTimeoutCancelsPASEEstablishmentTimer)
{
    System::Clock::Internal::RAIIMockClock clock;

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

    constexpr auto kCommissioningWindowSeconds = chip::System::Clock::Seconds32(1);
    constexpr uint16_t kCommissioningWindowMs  = 1000;
    constexpr unsigned kSleepPadding           = 100;
    constexpr uint32_t kPASETimerSeconds       = 60;

    commissionMgr.OverrideMinCommissioningTimeout(kCommissioningWindowSeconds);
    EXPECT_SUCCESS(
        commissionMgr.OpenBasicCommissioningWindow(kCommissioningWindowSeconds, CommissioningWindowAdvertisement::kDnssdOnly));
    EXPECT_TRUE(commissionMgr.IsCommissioningWindowOpen());

    // Arm the 60s PASE-establishment timer (PBKDFParamRequest received).
    commissionMgr.OnSessionEstablishmentStarted();

    // Window times out: HandleCommissioningWindowTimeout -> CloseCommissioningWindow -> Cleanup -> ResetState.
    clock.AdvanceMonotonic(chip::System::Clock::Milliseconds64(kCommissioningWindowMs + kSleepPadding));
    ServiceEvents();
    EXPECT_FALSE(commissionMgr.IsCommissioningWindowOpen());

    const auto errorCallbacksBefore = delegateApp.mOnCommissioningSessionEstablishmentErrorCount;

    // Advance past the 60s PASE timer. Bug present -> stale callback fires; fix in place -> no callback.
    clock.AdvanceMonotonic(chip::System::Clock::Milliseconds64((kPASETimerSeconds + 1) * 1000));
    ServiceEvents();

    // If this fails: ResetState() did not cancel HandleSessionEstablishmentTimeout.
    EXPECT_EQ(delegateApp.mOnCommissioningSessionEstablishmentErrorCount, errorCallbacksBefore);

    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
