/*
 *
 *    Copyright (c) 2021-2024 Project CHIP Authors
 *    All rights reserved.
 *
 *    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 <limits>

#include "network-commissioning.h"

#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/cluster-objects.h>
#include <app/AttributeAccessInterfaceRegistry.h>
#include <app/CommandHandlerInterface.h>
#include <app/InteractionModelEngine.h>
#include <app/clusters/general-commissioning-server/general-commissioning-server.h>
#include <app/data-model/Nullable.h>
#include <app/reporting/reporting.h>
#include <app/server/Server.h>
#include <app/util/attribute-storage.h>
#include <credentials/CHIPCert.h>
#include <lib/core/CHIPConfig.h>
#include <lib/support/SafeInt.h>
#include <lib/support/SortUtils.h>
#include <lib/support/ThreadOperationalDataset.h>
#include <platform/CHIPDeviceConfig.h>
#include <platform/ConnectivityManager.h>
#include <platform/DeviceControlServer.h>
#include <platform/PlatformManager.h>
#include <platform/internal/DeviceNetworkInfo.h>
#include <tracing/macros.h>

#include <array>
#include <utility>

namespace chip {
namespace app {
namespace Clusters {
namespace NetworkCommissioning {

using namespace Credentials;
using namespace DataModel;
using namespace DeviceLayer::NetworkCommissioning;

namespace {

// For WiFi and Thread scan results, each item will cost ~60 bytes in TLV, thus 15 is a safe upper bound of scan results.
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION || CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP || CHIP_DEVICE_CONFIG_ENABLE_THREAD
constexpr size_t kMaxNetworksInScanResponse = 15;
#endif

constexpr uint16_t kCurrentClusterRevision = 2;

#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
constexpr size_t kPossessionNonceSize = 32;
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC

// Note: CHIP_CONFIG_NETWORK_COMMISSIONING_DEBUG_TEXT_BUFFER_SIZE can be 0, this disables debug text
using DebugTextStorage = std::array<char, CHIP_CONFIG_NETWORK_COMMISSIONING_DEBUG_TEXT_BUFFER_SIZE>;

enum ValidWiFiCredentialLength
{
    kOpen      = 0,
    kWEP64     = 5,
    kMinWPAPSK = 8,
    kMaxWPAPSK = 63,
    kWPAPSKHex = 64,
};

template <typename T, typename Func>
static void EnumerateAndRelease(Iterator<T> * iterator, Func func)
{
    if (iterator != nullptr)
    {
        T element;
        while (iterator->Next(element) && func(element) == Loop::Continue)
        {
            /* continue */
        }
        iterator->Release();
    }
}

template <typename T>
static size_t CountAndRelease(Iterator<T> * iterator)
{
    size_t count = 0;
    if (iterator != nullptr)
    {
        count = iterator->Count();
        iterator->Release();
    }

    return count;
}

BitFlags<Feature> WiFiFeatures(WiFiDriver * driver)
{
    BitFlags<Feature> features = Feature::kWiFiNetworkInterface;
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
    features.Set(Feature::kPerDeviceCredentials, driver->SupportsPerDeviceCredentials());
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
    return features;
}

} // namespace

Instance::Instance(EndpointId aEndpointId, WiFiDriver * apDelegate) :
    CommandHandlerInterface(Optional<EndpointId>(aEndpointId), Id), AttributeAccessInterface(Optional<EndpointId>(aEndpointId), Id),
    mEndpointId(aEndpointId), mFeatureFlags(WiFiFeatures(apDelegate)), mpWirelessDriver(apDelegate), mpBaseDriver(apDelegate)
{
    mpDriver.Set<WiFiDriver *>(apDelegate);
}

Instance::Instance(EndpointId aEndpointId, ThreadDriver * apDelegate) :
    CommandHandlerInterface(Optional<EndpointId>(aEndpointId), Id), AttributeAccessInterface(Optional<EndpointId>(aEndpointId), Id),
    mEndpointId(aEndpointId), mFeatureFlags(Feature::kThreadNetworkInterface), mpWirelessDriver(apDelegate),
    mpBaseDriver(apDelegate)
{
    mpDriver.Set<ThreadDriver *>(apDelegate);
}

Instance::Instance(EndpointId aEndpointId, EthernetDriver * apDelegate) :
    CommandHandlerInterface(Optional<EndpointId>(aEndpointId), Id), AttributeAccessInterface(Optional<EndpointId>(aEndpointId), Id),
    mEndpointId(aEndpointId), mFeatureFlags(Feature::kEthernetNetworkInterface), mpWirelessDriver(nullptr), mpBaseDriver(apDelegate)
{}

CHIP_ERROR Instance::Init()
{
    ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this));
    VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast<intptr_t>(this)));
    ReturnErrorOnFailure(mpBaseDriver->Init(this));
    mLastNetworkingStatusValue.SetNull();
    mLastConnectErrorValue.SetNull();
    mLastNetworkIDLen = 0;
    return CHIP_NO_ERROR;
}

void Instance::Shutdown()
{
    mpBaseDriver->Shutdown();
}

#if !CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
void Instance::SendNonConcurrentConnectNetworkResponse()
{
    auto commandHandleRef = std::move(mAsyncCommandHandle);
    auto commandHandle    = commandHandleRef.Get();
    if (commandHandle == nullptr)
    {
        return;
    }

#if CONFIG_NETWORK_LAYER_BLE
    DeviceLayer::ConnectivityMgr().GetBleLayer()->IndicateBleClosing();
#endif // CONFIG_NETWORK_LAYER_BLE
    ChipLogProgress(NetworkProvisioning, "Non-concurrent mode. Send ConnectNetworkResponse(Success)");
    Commands::ConnectNetworkResponse::Type response;
    response.networkingStatus = NetworkCommissioning::Status::kSuccess;
    commandHandle->AddResponse(mPath, response);
}
#endif // CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION

void Instance::SetLastNetworkingStatusValue(Attributes::LastNetworkingStatus::TypeInfo::Type networkingStatusValue)
{
    if (mLastNetworkingStatusValue.Update(networkingStatusValue))
    {
        MatterReportingAttributeChangeCallback(mEndpointId, Clusters::NetworkCommissioning::Id,
                                               Attributes::LastNetworkingStatus::TypeInfo::GetAttributeId());
    }
}

void Instance::SetLastConnectErrorValue(Attributes::LastConnectErrorValue::TypeInfo::Type connectErrorValue)
{
    if (mLastConnectErrorValue.Update(connectErrorValue))
    {
        MatterReportingAttributeChangeCallback(mEndpointId, Clusters::NetworkCommissioning::Id,
                                               Attributes::LastConnectErrorValue::TypeInfo::GetAttributeId());
    }
}

void Instance::SetLastNetworkId(ByteSpan lastNetworkId)
{
    ByteSpan prevLastNetworkId{ mLastNetworkID, mLastNetworkIDLen };
    VerifyOrReturn(lastNetworkId.size() <= kMaxNetworkIDLen);
    VerifyOrReturn(!prevLastNetworkId.data_equal(lastNetworkId));

    memcpy(mLastNetworkID, lastNetworkId.data(), lastNetworkId.size());
    mLastNetworkIDLen = static_cast<uint8_t>(lastNetworkId.size());
    MatterReportingAttributeChangeCallback(mEndpointId, Clusters::NetworkCommissioning::Id,
                                           Attributes::LastNetworkID::TypeInfo::GetAttributeId());
}

void Instance::ReportNetworksListChanged() const
{
    MatterReportingAttributeChangeCallback(mEndpointId, Clusters::NetworkCommissioning::Id,
                                           Attributes::Networks::TypeInfo::GetAttributeId());
}

void Instance::InvokeCommand(HandlerContext & ctxt)
{
    if (mAsyncCommandHandle.Get() != nullptr)
    {
        // We have a command processing in the backend, reject all incoming commands.
        ctxt.mCommandHandler.AddStatus(ctxt.mRequestPath, Protocols::InteractionModel::Status::Busy);
        ctxt.SetCommandHandled();
        return;
    }

    // Since mPath is used for building the response command, and we have checked that we are not pending the response of another
    // command above. So it is safe to set the mPath here and not clear it when return.
    mPath = ctxt.mRequestPath;

    switch (ctxt.mRequestPath.mCommandId)
    {
    case Commands::ScanNetworks::Id:
        VerifyOrReturn(mFeatureFlags.Has(Feature::kWiFiNetworkInterface) || mFeatureFlags.Has(Feature::kThreadNetworkInterface));
        HandleCommand<Commands::ScanNetworks::DecodableType>(
            ctxt, [this](HandlerContext & ctx, const auto & req) { HandleScanNetworks(ctx, req); });
        return;

    case Commands::AddOrUpdateWiFiNetwork::Id:
        VerifyOrReturn(mFeatureFlags.Has(Feature::kWiFiNetworkInterface));
        HandleCommand<Commands::AddOrUpdateWiFiNetwork::DecodableType>(
            ctxt, [this](HandlerContext & ctx, const auto & req) { HandleAddOrUpdateWiFiNetwork(ctx, req); });
        return;

    case Commands::AddOrUpdateThreadNetwork::Id:
        VerifyOrReturn(mFeatureFlags.Has(Feature::kThreadNetworkInterface));
        HandleCommand<Commands::AddOrUpdateThreadNetwork::DecodableType>(
            ctxt, [this](HandlerContext & ctx, const auto & req) { HandleAddOrUpdateThreadNetwork(ctx, req); });
        return;

    case Commands::RemoveNetwork::Id:
        VerifyOrReturn(mFeatureFlags.Has(Feature::kWiFiNetworkInterface) || mFeatureFlags.Has(Feature::kThreadNetworkInterface));
        HandleCommand<Commands::RemoveNetwork::DecodableType>(
            ctxt, [this](HandlerContext & ctx, const auto & req) { HandleRemoveNetwork(ctx, req); });
        return;

    case Commands::ConnectNetwork::Id: {
        VerifyOrReturn(mFeatureFlags.Has(Feature::kWiFiNetworkInterface) || mFeatureFlags.Has(Feature::kThreadNetworkInterface));

        HandleCommand<Commands::ConnectNetwork::DecodableType>(
            ctxt, [this](HandlerContext & ctx, const auto & req) { HandleConnectNetwork(ctx, req); });
        return;
    }

    case Commands::ReorderNetwork::Id:
        VerifyOrReturn(mFeatureFlags.Has(Feature::kWiFiNetworkInterface) || mFeatureFlags.Has(Feature::kThreadNetworkInterface));
        HandleCommand<Commands::ReorderNetwork::DecodableType>(
            ctxt, [this](HandlerContext & ctx, const auto & req) { HandleReorderNetwork(ctx, req); });
        return;
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
    case Commands::QueryIdentity::Id:
        VerifyOrReturn(mFeatureFlags.Has(Feature::kPerDeviceCredentials));
        HandleCommand<Commands::QueryIdentity::DecodableType>(
            ctxt, [this](HandlerContext & ctx, const auto & req) { HandleQueryIdentity(ctx, req); });
        return;
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
    }
}

CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
    switch (aPath.mAttributeId)
    {
    case Attributes::MaxNetworks::Id:
        return aEncoder.Encode(mpBaseDriver->GetMaxNetworks());

    case Attributes::Networks::Id:
        return aEncoder.EncodeList([this](const auto & encoder) {
            CHIP_ERROR err = CHIP_NO_ERROR;
            Structs::NetworkInfoStruct::Type networkForEncode;
            EnumerateAndRelease(mpBaseDriver->GetNetworks(), [&](const Network & network) {
                networkForEncode.networkID = ByteSpan(network.networkID, network.networkIDLen);
                networkForEncode.connected = network.connected;

#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
                // These fields are both optional and nullable in NetworkInfoStruct.
                // If PDC is supported, the fields are always present but may be null.
                if (mFeatureFlags.Has(Feature::kPerDeviceCredentials))
                {
                    networkForEncode.networkIdentifier = MakeOptional(Nullable<ByteSpan>(network.networkIdentifier));
                    networkForEncode.clientIdentifier  = MakeOptional(Nullable<ByteSpan>(network.clientIdentifier));
                }
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC

                err = encoder.Encode(networkForEncode);
                return (err == CHIP_NO_ERROR) ? Loop::Continue : Loop::Break;
            });
            return err;
        });

    case Attributes::ScanMaxTimeSeconds::Id:
        if (mpWirelessDriver != nullptr)
        {
            return aEncoder.Encode(mpWirelessDriver->GetScanNetworkTimeoutSeconds());
        }
        return CHIP_NO_ERROR;

    case Attributes::ConnectMaxTimeSeconds::Id:
        if (mpWirelessDriver != nullptr)
        {
            return aEncoder.Encode(mpWirelessDriver->GetConnectNetworkTimeoutSeconds());
        }
        return CHIP_NO_ERROR;

    case Attributes::InterfaceEnabled::Id:
        return aEncoder.Encode(mpBaseDriver->GetEnabled());

    case Attributes::LastNetworkingStatus::Id:
        return aEncoder.Encode(mLastNetworkingStatusValue);

    case Attributes::LastNetworkID::Id:
        if (mLastNetworkIDLen == 0)
        {
            return aEncoder.EncodeNull();
        }
        else
        {
            return aEncoder.Encode(ByteSpan(mLastNetworkID, mLastNetworkIDLen));
        }

    case Attributes::LastConnectErrorValue::Id:
        return aEncoder.Encode(mLastConnectErrorValue);

    case Attributes::FeatureMap::Id:
        return aEncoder.Encode(mFeatureFlags);

    case Attributes::ClusterRevision::Id:
        return aEncoder.Encode(kCurrentClusterRevision);

    case Attributes::SupportedWiFiBands::Id: {
#if (CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION || CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP)
        // TODO https://github.com/project-chip/connectedhomeip/issues/31431
        // This is a case of shared zap config where mandatory wifi attributes are enabled for a thread platform (e.g
        // all-cluster-app). Real world product must only enable the attributes tied to the network technology supported by their
        // product. Temporarily return an list of 1 element of value 0 when wifi is not supported or WiFiNetworkInterface is not
        // enabled until a solution is implemented with the attribute list.
        // Final implementation will return UnsupportedAttribute if we get here without the needed WiFi support .
        // VerifyOrReturnError(mFeatureFlags.Has(Feature::kWiFiNetworkInterface), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute));
        if (mFeatureFlags.Has(Feature::kWiFiNetworkInterface))
        {
            return aEncoder.EncodeList([this](const auto & encoder) {
                uint32_t bands = mpDriver.Get<WiFiDriver *>()->GetSupportedWiFiBandsMask();

                // Extract every band from the bitmap of supported bands, starting positionally on the right.
                for (uint32_t band_bit_pos = 0; band_bit_pos < std::numeric_limits<uint32_t>::digits; ++band_bit_pos)
                {
                    uint32_t band_mask = static_cast<uint32_t>(1UL << band_bit_pos);
                    if ((bands & band_mask) != 0)
                    {
                        ReturnErrorOnFailure(encoder.Encode(static_cast<WiFiBandEnum>(band_bit_pos)));
                    }
                }
                return CHIP_NO_ERROR;
            });
        }
#endif
        return aEncoder.EncodeList([](const auto & encoder) {
            WiFiBandEnum bands = WiFiBandEnum::k2g4;
            ReturnErrorOnFailure(encoder.Encode(bands));
            return CHIP_NO_ERROR;
        });
    }
    break;
    case Attributes::SupportedThreadFeatures::Id: {
        // TODO https://github.com/project-chip/connectedhomeip/issues/31431
        BitMask<ThreadCapabilities> ThreadCapabilities = 0;
#if (CHIP_DEVICE_CONFIG_ENABLE_THREAD)
        // This is a case of shared zap config where mandatory thread attributes are enabled for a wifi platform (e.g
        // all-cluster-app). Real world product must only enable the attributes tied to the network technology supported by their
        // product. Temporarily encode a value of 0 reflecting no thread capabilities hen CHIP_DEVICE_CONFIG_ENABLE_THREAD or
        // ThreadNetworkInterface are not enabled until a solution is implemented with the attribute list.
        // Final implementation will return UnsupportedAttribute if we get here without the needed thread support
        // VerifyOrReturnError(mFeatureFlags.Has(Feature::kThreadNetworkInterface), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute));
        if (mFeatureFlags.Has(Feature::kThreadNetworkInterface))
        {
            ThreadCapabilities = mpDriver.Get<ThreadDriver *>()->GetSupportedThreadFeatures();
        }
#endif
        return aEncoder.Encode(ThreadCapabilities);
    }
    break;
    case Attributes::ThreadVersion::Id: {
        // TODO https://github.com/project-chip/connectedhomeip/issues/31431ß
        uint16_t threadVersion = 0;
#if (CHIP_DEVICE_CONFIG_ENABLE_THREAD)
        // This is a case of shared zap config where mandatory thread attributes are enabled for a wifi platform (e.g
        // all-cluster-app) Real world product must only enable the attributes tied to the network technology supported by their
        // product. Temporarily encode a value of 0 reflecting no thread version when CHIP_DEVICE_CONFIG_ENABLE_THREAD or
        // ThreadNetworkInterface are not enabled until a solution is implemented with the attribute list.
        // Final implementation will return UnsupportedAttribute if we get here without the needed thread support
        // VerifyOrReturnError(mFeatureFlags.Has(Feature::kThreadNetworkInterface), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute));
        if (mFeatureFlags.Has(Feature::kThreadNetworkInterface))
        {
            threadVersion = mpDriver.Get<ThreadDriver *>()->GetThreadVersion();
        }
#endif
        return aEncoder.Encode(threadVersion);
    }
    break;
    default:
        return CHIP_NO_ERROR;
    }
}

CHIP_ERROR Instance::Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder)
{
    switch (aPath.mAttributeId)
    {
    case Attributes::InterfaceEnabled::Id:
        bool value;
        ReturnErrorOnFailure(aDecoder.Decode(value));
        return mpBaseDriver->SetEnabled(value);
    default:
        return CHIP_IM_GLOBAL_STATUS(InvalidAction);
    }
}

void Instance::OnNetworkingStatusChange(Status aCommissioningError, Optional<ByteSpan> aNetworkId, Optional<int32_t> aConnectStatus)
{
    if (aNetworkId.HasValue())
    {
        if (aNetworkId.Value().size() > kMaxNetworkIDLen)
        {
            ChipLogError(DeviceLayer, "Overly large network ID received when calling OnNetworkingStatusChange");
        }
        else
        {
            SetLastNetworkId(aNetworkId.Value());
        }
    }

    SetLastNetworkingStatusValue(MakeNullable(aCommissioningError));
    if (aConnectStatus.HasValue())
    {
        SetLastConnectErrorValue(MakeNullable(aConnectStatus.Value()));
    }
    else
    {
        SetLastConnectErrorValue(NullNullable);
    }
}

void Instance::HandleScanNetworks(HandlerContext & ctx, const Commands::ScanNetworks::DecodableType & req)
{
    MATTER_TRACE_SCOPE("HandleScanNetwork", "NetworkCommissioning");

    mScanningWasDirected = false;
    if (mFeatureFlags.Has(Feature::kWiFiNetworkInterface))
    {
        ByteSpan ssid;
        if (req.ssid.HasValue())
        {
            const auto & nullableSSID = req.ssid.Value();
            if (!nullableSSID.IsNull())
            {
                ssid = nullableSSID.Value();
                if (ssid.empty())
                {
                    // Normalize empty span value to null ByteSpan.
                    // Spec 7.17.1. Empty string is an equivalent of null.
                    ssid = ByteSpan();
                }
            }
        }
        if (ssid.size() > DeviceLayer::Internal::kMaxWiFiSSIDLength)
        {
            // Clients should never use too large a SSID.
            ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError);
            SetLastNetworkingStatusValue(MakeNullable(Status::kUnknownError));
            return;
        }

        mScanningWasDirected        = !ssid.empty();
        mCurrentOperationBreadcrumb = req.breadcrumb;
        mAsyncCommandHandle         = CommandHandler::Handle(&ctx.mCommandHandler);
        ctx.mCommandHandler.FlushAcksRightAwayOnSlowCommand();
        mpDriver.Get<WiFiDriver *>()->ScanNetworks(ssid, this);
    }
    else if (mFeatureFlags.Has(Feature::kThreadNetworkInterface))
    {
        // NOTE: the following lines were commented out due to issue #32875. In short, a popular
        // commissioner is passing a null SSID argument and this logic breaks interoperability as a result.
        // The spec has some inconsistency on this which also needs to be fixed. The commissioner maker is
        // fixing its code and will return to un-comment this code, with that work tracked by Issue #32887.
        //
        // SSID present on Thread violates the `[WI]` conformance.
        // if (req.ssid.HasValue())
        // {
        //     ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::InvalidCommand);
        //     return;
        // }

        mCurrentOperationBreadcrumb = req.breadcrumb;
        mAsyncCommandHandle         = CommandHandler::Handle(&ctx.mCommandHandler);
        ctx.mCommandHandler.FlushAcksRightAwayOnSlowCommand();
        mpDriver.Get<ThreadDriver *>()->ScanNetworks(this);
    }
    else
    {
        ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::UnsupportedCommand);
    }
}

namespace {
void FillDebugTextAndNetworkIndex(Commands::NetworkConfigResponse::Type & response, MutableCharSpan debugText, uint8_t networkIndex)
{
    if (!debugText.empty())
    {
        response.debugText.SetValue(debugText);
    }
    if (response.networkingStatus == Status::kSuccess)
    {
        response.networkIndex.SetValue(networkIndex);
    }
}

bool CheckFailSafeArmed(CommandHandlerInterface::HandlerContext & ctx)
{
    auto & failSafeContext = chip::Server::GetInstance().GetFailSafeContext();

    if (failSafeContext.IsFailSafeArmed(ctx.mCommandHandler.GetAccessingFabricIndex()))
    {
        return true;
    }

    ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::FailsafeRequired);
    return false;
}

} // namespace

void Instance::HandleAddOrUpdateWiFiNetwork(HandlerContext & ctx, const Commands::AddOrUpdateWiFiNetwork::DecodableType & req)
{
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION || CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
    MATTER_TRACE_SCOPE("HandleAddOrUpdateWiFiNetwork", "NetworkCommissioning");

    VerifyOrReturn(CheckFailSafeArmed(ctx));

    if (req.ssid.empty() || req.ssid.size() > DeviceLayer::Internal::kMaxWiFiSSIDLength)
    {
        ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError, "ssid");
        return;
    }

    // Presence of a Network Identity indicates we're configuring for Per-Device Credentials
    if (req.networkIdentity.HasValue())
    {
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
        if (mFeatureFlags.Has(Feature::kWiFiNetworkInterface))
        {
            HandleAddOrUpdateWiFiNetworkWithPDC(ctx, req);
            return;
        }
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
        ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::InvalidCommand);
        return;
    }

    // Spec 11.8.8.4
    // Valid Credentials length are:
    // - 0 bytes: Unsecured (open) connection
    // - 5 bytes: WEP-64 passphrase
    // - 10 hexadecimal ASCII characters: WEP-64 40-bit hex raw PSK
    // - 13 bytes: WEP-128 passphrase
    // - 26 hexadecimal ASCII characters: WEP-128 104-bit hex raw PSK
    // - 8..63 bytes: WPA/WPA2/WPA3 passphrase
    // - 64 bytes: WPA/WPA2/WPA3 raw hex PSK
    // Note 10 hex WEP64 and 13 bytes / 26 hex WEP128 passphrase are covered by 8~63 bytes WPA passphrase, so we don't check WEP64
    // hex and WEP128 passphrase.
    if (req.credentials.size() == ValidWiFiCredentialLength::kOpen || req.credentials.size() == ValidWiFiCredentialLength::kWEP64 ||
        (req.credentials.size() >= ValidWiFiCredentialLength::kMinWPAPSK &&
         req.credentials.size() <= ValidWiFiCredentialLength::kMaxWPAPSK))
    {
        // Valid length, the credentials can have any characters.
    }
    else if (req.credentials.size() == ValidWiFiCredentialLength::kWPAPSKHex)
    {
        for (size_t d = 0; d < req.credentials.size(); d++)
        {
            if (!isxdigit(req.credentials.data()[d]))
            {
                ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError);
                return;
            }
        }
    }
    else
    {
        // Invalid length
        ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError);
        return;
    }

    Commands::NetworkConfigResponse::Type response;
    DebugTextStorage debugTextBuffer;
    MutableCharSpan debugText(debugTextBuffer);
    uint8_t outNetworkIndex = 0;
    response.networkingStatus =
        mpDriver.Get<WiFiDriver *>()->AddOrUpdateNetwork(req.ssid, req.credentials, debugText, outNetworkIndex);
    FillDebugTextAndNetworkIndex(response, debugText, outNetworkIndex);
    ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
    if (response.networkingStatus == Status::kSuccess)
    {
        UpdateBreadcrumb(req.breadcrumb);
        ReportNetworksListChanged();
    }
#endif
}

#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
void Instance::HandleAddOrUpdateWiFiNetworkWithPDC(HandlerContext & ctx,
                                                   const Commands::AddOrUpdateWiFiNetwork::DecodableType & req)
{
    // Credentials must be empty when configuring for PDC, it's only present to keep the command shape compatible.
    if (!req.credentials.empty())
    {
        ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError, "credentials");
        return;
    }

    auto && networkIdentity = req.networkIdentity.Value(); // presence checked by caller
    if (networkIdentity.size() > kMaxCHIPCompactNetworkIdentityLength ||
        Credentials::ValidateChipNetworkIdentity(networkIdentity) != CHIP_NO_ERROR)
    {
        ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError, "networkIdentity");
        return;
    }

    if (req.clientIdentifier.HasValue() && req.clientIdentifier.Value().size() != CertificateKeyId::size())
    {
        ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError, "clientIdentifier");
        return;
    }

    bool provePossession = req.possessionNonce.HasValue();
    if (provePossession && req.possessionNonce.Value().size() != kPossessionNonceSize)
    {
        ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError, "possessionNonce");
        return;
    }

    auto err = CHIP_NO_ERROR;
    {
        auto driver = mpDriver.Get<WiFiDriver *>();

        // If the client is requesting re-use of a Client Identity, find the existing network it belongs to
        Optional<uint8_t> clientIdentityNetworkIndex;
        if (req.clientIdentifier.HasValue())
        {
            CertificateKeyId clientIdentifier(req.clientIdentifier.Value().data());
            uint8_t networkIndex = 0;
            EnumerateAndRelease(driver->GetNetworks(), [&](const Network & network) {
                if (network.clientIdentifier.HasValue() && clientIdentifier.data_equal(network.clientIdentifier.Value()))
                {
                    clientIdentityNetworkIndex.SetValue(networkIndex);
                    return Loop::Break;
                }
                networkIndex++;
                return Loop::Continue;
            });
            if (!clientIdentityNetworkIndex.HasValue())
            {
                ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::NotFound, "clientIdentifier");
                return;
            }
        }

        // Allocate a buffer to hold the client identity, and leave enough room to append the possession nonce if needed.
        chip::Platform::ScopedMemoryBuffer<uint8_t> identityBuffer;
        size_t identityBufferSize = kMaxCHIPCompactNetworkIdentityLength + (provePossession ? kPossessionNonceSize : 0);
        VerifyOrExit(identityBuffer.Alloc(identityBufferSize), /**/);

        // Add/Update the network at the driver level
        MutableByteSpan clientIdentity(identityBuffer.Get(), kMaxCHIPCompactNetworkIdentityLength);
        Optional<P256ECDSASignature> possessionSignature;
        Status status = Status::kUnknownError;
        DebugTextStorage debugTextBuffer;
        MutableCharSpan debugText(debugTextBuffer);
        uint8_t networkIndex;
        SuccessOrExit(err = driver->AddOrUpdateNetworkWithPDC(req.ssid, networkIdentity, clientIdentityNetworkIndex, status,
                                                              debugText, clientIdentity, networkIndex));

        Commands::NetworkConfigResponse::Type response;
        response.networkingStatus = status;
        FillDebugTextAndNetworkIndex(response, debugText, networkIndex);

        if (status == Status::kSuccess)
        {
            response.clientIdentity.SetValue(clientIdentity);

            if (provePossession)
            {
                // PossessionSignature TBS message = (NetworkClientIdentity || PossessionNonce)
                memcpy(clientIdentity.end(), req.possessionNonce.Value().data(), kPossessionNonceSize);
                ByteSpan tbsMessage(clientIdentity.data(), clientIdentity.size() + kPossessionNonceSize);
                SuccessOrExit(err = driver->SignWithClientIdentity(networkIndex, tbsMessage, possessionSignature.Emplace()));
                response.possessionSignature.SetValue(possessionSignature.Value().Span());
            }

            ReportNetworksListChanged();
            UpdateBreadcrumb(req.breadcrumb);
        }

        ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
    }

exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Zcl, "AddOrUpdateWiFiNetwork with PDC failed: %" CHIP_ERROR_FORMAT, err.Format());
        ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::Failure);
    }
}
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC

void Instance::HandleAddOrUpdateThreadNetwork(HandlerContext & ctx, const Commands::AddOrUpdateThreadNetwork::DecodableType & req)
{
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD

    MATTER_TRACE_SCOPE("HandleAddOrUpdateThreadNetwork", "NetworkCommissioning");

    VerifyOrReturn(CheckFailSafeArmed(ctx));

    Commands::NetworkConfigResponse::Type response;
    DebugTextStorage debugTextBuffer;
    MutableCharSpan debugText(debugTextBuffer);
    uint8_t outNetworkIndex = 0;
    response.networkingStatus =
        mpDriver.Get<ThreadDriver *>()->AddOrUpdateNetwork(req.operationalDataset, debugText, outNetworkIndex);
    FillDebugTextAndNetworkIndex(response, debugText, outNetworkIndex);
    ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
    if (response.networkingStatus == Status::kSuccess)
    {
        ReportNetworksListChanged();
        UpdateBreadcrumb(req.breadcrumb);
    }
#endif
}

void Instance::UpdateBreadcrumb(const Optional<uint64_t> & breadcrumb)
{
    VerifyOrReturn(breadcrumb.HasValue());
    GeneralCommissioning::SetBreadcrumb(breadcrumb.Value());
}

void Instance::CommitSavedBreadcrumb()
{
    // We rejected the command when there is another ongoing command, so mCurrentOperationBreadcrumb reflects the breadcrumb
    // argument in the only background command.
    UpdateBreadcrumb(mCurrentOperationBreadcrumb);
    mCurrentOperationBreadcrumb.ClearValue();
}

void Instance::HandleRemoveNetwork(HandlerContext & ctx, const Commands::RemoveNetwork::DecodableType & req)
{
    MATTER_TRACE_SCOPE("HandleRemoveNetwork", "NetworkCommissioning");

    VerifyOrReturn(CheckFailSafeArmed(ctx));

    Commands::NetworkConfigResponse::Type response;
    DebugTextStorage debugTextBuffer;
    MutableCharSpan debugText(debugTextBuffer);
    uint8_t outNetworkIndex   = 0;
    response.networkingStatus = mpWirelessDriver->RemoveNetwork(req.networkID, debugText, outNetworkIndex);
    FillDebugTextAndNetworkIndex(response, debugText, outNetworkIndex);
    ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
    if (response.networkingStatus == Status::kSuccess)
    {
        ReportNetworksListChanged();
        UpdateBreadcrumb(req.breadcrumb);

        // If no networks are left, clear-out errors;
        if (CountAndRelease(mpBaseDriver->GetNetworks()) == 0)
        {
            SetLastNetworkId(ByteSpan{});
            SetLastConnectErrorValue(NullNullable);
            SetLastNetworkingStatusValue(NullNullable);
        }
    }
}

void Instance::HandleConnectNetwork(HandlerContext & ctx, const Commands::ConnectNetwork::DecodableType & req)
{
    MATTER_TRACE_SCOPE("HandleConnectNetwork", "NetworkCommissioning");
    if (req.networkID.size() > kMaxNetworkIDLen)
    {
        ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError);
        return;
    }

    VerifyOrReturn(CheckFailSafeArmed(ctx));

    mConnectingNetworkIDLen = static_cast<uint8_t>(req.networkID.size());
    memcpy(mConnectingNetworkID, req.networkID.data(), mConnectingNetworkIDLen);
    mAsyncCommandHandle         = CommandHandler::Handle(&ctx.mCommandHandler);
    mCurrentOperationBreadcrumb = req.breadcrumb;

#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
    mpWirelessDriver->ConnectNetwork(req.networkID, this);
#else
    // In Non-concurrent mode postpone the final execution of ConnectNetwork until the operational
    // network has been fully brought up and kOperationalNetworkStarted is delivered.
    // mConnectingNetworkIDLen and mConnectingNetworkID contain the received SSID
    // As per spec, send the ConnectNetworkResponse(Success) prior to releasing the commissioning channel
    SendNonConcurrentConnectNetworkResponse();
#endif
}

void Instance::HandleNonConcurrentConnectNetwork()
{
    ByteSpan nonConcurrentNetworkID = ByteSpan(mConnectingNetworkID, mConnectingNetworkIDLen);
    ChipLogProgress(NetworkProvisioning, "Non-concurrent mode, Connect to Network SSID=%.*s", mConnectingNetworkIDLen,
                    mConnectingNetworkID);
    mpWirelessDriver->ConnectNetwork(nonConcurrentNetworkID, this);
}

void Instance::HandleReorderNetwork(HandlerContext & ctx, const Commands::ReorderNetwork::DecodableType & req)
{
    MATTER_TRACE_SCOPE("HandleReorderNetwork", "NetworkCommissioning");
    Commands::NetworkConfigResponse::Type response;
    DebugTextStorage debugTextBuffer;
    MutableCharSpan debugText(debugTextBuffer);
    response.networkingStatus = mpWirelessDriver->ReorderNetwork(req.networkID, req.networkIndex, debugText);
    FillDebugTextAndNetworkIndex(response, debugText, req.networkIndex);
    ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
    if (response.networkingStatus == Status::kSuccess)
    {
        ReportNetworksListChanged();
        UpdateBreadcrumb(req.breadcrumb);
    }
}

#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
void Instance::HandleQueryIdentity(HandlerContext & ctx, const Commands::QueryIdentity::DecodableType & req)
{
    MATTER_TRACE_SCOPE("HandleQueryIdentity", "NetworkCommissioning");

    if (req.keyIdentifier.size() != CertificateKeyId::size())
    {
        ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError, "keyIdentifier");
        return;
    }
    CertificateKeyId keyIdentifier(req.keyIdentifier.data());

    bool provePossession = req.possessionNonce.HasValue();
    if (provePossession && req.possessionNonce.Value().size() != kPossessionNonceSize)
    {
        ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError, "possessionNonce");
        return;
    }

    auto err      = CHIP_NO_ERROR;
    auto status   = Protocols::InteractionModel::Status::Success;
    auto driver   = mpDriver.Get<WiFiDriver *>();
    auto networks = driver->GetNetworks();
    VerifyOrExit(networks != nullptr && networks->Count() > 0, status = Protocols::InteractionModel::Status::NotFound);

    {
        // Allocate a buffer to hold the identity, and leave enough room to append the possession nonce if needed.
        chip::Platform::ScopedMemoryBuffer<uint8_t> identityBuffer;
        size_t identityBufferSize = kMaxCHIPCompactNetworkIdentityLength + (provePossession ? kPossessionNonceSize : 0);
        VerifyOrExit(identityBuffer.Alloc(identityBufferSize), /**/);

        MutableByteSpan identity(identityBuffer.Get(), kMaxCHIPCompactNetworkIdentityLength);
        Optional<P256ECDSASignature> possessionSignature;

        Network network;
        for (uint8_t networkIndex = 0;; networkIndex++)
        {
            VerifyOrExit(networks->Next(network), status = Protocols::InteractionModel::Status::NotFound);

            if (network.clientIdentifier.HasValue() && keyIdentifier.data_equal(network.clientIdentifier.Value()))
            {
                SuccessOrExit(err = driver->GetClientIdentity(networkIndex, identity));
                if (provePossession)
                {
                    // PossessionSignature TBS message = (NetworkClientIdentity || PossessionNonce)
                    memcpy(identity.end(), req.possessionNonce.Value().data(), kPossessionNonceSize);
                    ByteSpan tbsMessage(identity.data(), identity.size() + kPossessionNonceSize);
                    SuccessOrExit(err = driver->SignWithClientIdentity(networkIndex, tbsMessage, possessionSignature.Emplace()));
                }
                break;
            }
            if (!provePossession && // Proof-of-possession is not possible for network identities
                network.networkIdentifier.HasValue() && keyIdentifier.data_equal(network.networkIdentifier.Value()))
            {
                SuccessOrExit(err = driver->GetNetworkIdentity(networkIndex, identity));
                break;
            }
        }

        Commands::QueryIdentityResponse::Type response;
        response.identity = identity;
        if (possessionSignature.HasValue())
        {
            response.possessionSignature.SetValue(possessionSignature.Value().Span());
        }
        ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
    }

exit:
    if (networks != nullptr)
    {
        networks->Release();
    }
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Zcl, "QueryIdentity failed: %" CHIP_ERROR_FORMAT, err.Format());
        status = Protocols::InteractionModel::Status::Failure;
    }
    if (status != Protocols::InteractionModel::Status::Success)
    {
        ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
    }
}
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC

void Instance::OnResult(Status commissioningError, CharSpan debugText, int32_t interfaceStatus)
{
    auto commandHandleRef = std::move(mAsyncCommandHandle);

    // In Non-concurrent mode the commandHandle will be null here, the ConnectNetworkResponse
    // has already been sent and the BLE will have been stopped, however the other functionality
    // is still required
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
    auto commandHandle = commandHandleRef.Get();
    if (commandHandle == nullptr)
    {
        // When the platform shutted down, interaction model engine will invalidate all commandHandle to avoid dangling references.
        // We may receive the callback after it and should make it noop.
        return;
    }
#endif // CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION

    Commands::ConnectNetworkResponse::Type response;
    response.networkingStatus = commissioningError;
    if (!debugText.empty())
    {
        response.debugText.SetValue(debugText);
    }
    if (commissioningError == Status::kSuccess)
    {
        DeviceLayer::DeviceControlServer::DeviceControlSvr().PostConnectedToOperationalNetworkEvent(
            ByteSpan(mLastNetworkID, mLastNetworkIDLen));
        SetLastConnectErrorValue(NullNullable);
    }
    else
    {
        response.errorValue.SetNonNull(interfaceStatus);
        SetLastConnectErrorValue(MakeNullable(interfaceStatus));
    }

    SetLastNetworkId(ByteSpan{ mConnectingNetworkID, mConnectingNetworkIDLen });
    SetLastNetworkingStatusValue(MakeNullable(commissioningError));

#if CONFIG_NETWORK_LAYER_BLE && !CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
    ChipLogProgress(NetworkProvisioning, "Non-concurrent mode, ConnectNetworkResponse will NOT be sent");
    // Do not send the ConnectNetworkResponse if in non-concurrent mode
    // TODO(#30576) raised to modify CommandHandler to notify it if no response required
    // -----> Is this required here: commandHandle->FinishCommand();
#else
    commandHandle->AddResponse(mPath, response);
#endif // CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION

    if (commissioningError == Status::kSuccess)
    {
        CommitSavedBreadcrumb();
    }
}

void Instance::OnFinished(Status status, CharSpan debugText, ThreadScanResponseIterator * networks)
{
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
    CHIP_ERROR err        = CHIP_NO_ERROR;
    auto commandHandleRef = std::move(mAsyncCommandHandle);
    auto commandHandle    = commandHandleRef.Get();
    if (commandHandle == nullptr)
    {
        // When the platform shutted down, interaction model engine will invalidate all commandHandle to avoid dangling references.
        // We may receive the callback after it and should make it noop.
        return;
    }

    SetLastNetworkingStatusValue(MakeNullable(status));

    TLV::TLVWriter * writer;
    TLV::TLVType listContainerType;
    ThreadScanResponse scanResponse;
    Platform::ScopedMemoryBuffer<ThreadScanResponse> scanResponseArray;
    size_t scanResponseArrayLength = 0;
    uint8_t extendedAddressBuffer[Thread::kSizeExtendedPanId];

    const CommandHandler::InvokeResponseParameters prepareParams(mPath);
    SuccessOrExit(
        err = commandHandle->PrepareInvokeResponseCommand(
            ConcreteCommandPath(mPath.mEndpointId, NetworkCommissioning::Id, Commands::ScanNetworksResponse::Id), prepareParams));
    VerifyOrExit((writer = commandHandle->GetCommandDataIBTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE);

    SuccessOrExit(err = writer->Put(TLV::ContextTag(Commands::ScanNetworksResponse::Fields::kNetworkingStatus), status));
    if (debugText.size() != 0)
    {
        SuccessOrExit(
            err = DataModel::Encode(*writer, TLV::ContextTag(Commands::ScanNetworksResponse::Fields::kDebugText), debugText));
    }
    SuccessOrExit(err = writer->StartContainer(TLV::ContextTag(Commands::ScanNetworksResponse::Fields::kThreadScanResults),
                                               TLV::TLVType::kTLVType_Array, listContainerType));

    // If no network was found, we encode an empty list, don't call a zero-sized alloc.
    if ((status == Status::kSuccess) && (networks->Count() > 0))
    {
        VerifyOrExit(scanResponseArray.Alloc(chip::min(networks->Count(), kMaxNetworksInScanResponse)), err = CHIP_ERROR_NO_MEMORY);
        for (; networks != nullptr && networks->Next(scanResponse);)
        {
            if ((scanResponseArrayLength == kMaxNetworksInScanResponse) &&
                (scanResponseArray[scanResponseArrayLength - 1].rssi > scanResponse.rssi))
            {
                continue;
            }

            bool isDuplicated = false;

            for (size_t i = 0; i < scanResponseArrayLength; i++)
            {
                if ((scanResponseArray[i].panId == scanResponse.panId) &&
                    (scanResponseArray[i].extendedPanId == scanResponse.extendedPanId))
                {
                    if (scanResponseArray[i].rssi < scanResponse.rssi)
                    {
                        scanResponseArray[i] = scanResponseArray[--scanResponseArrayLength];
                    }
                    else
                    {
                        isDuplicated = true;
                    }
                    break;
                }
            }

            if (isDuplicated)
            {
                continue;
            }

            if (scanResponseArrayLength < kMaxNetworksInScanResponse)
            {
                scanResponseArrayLength++;
            }
            scanResponseArray[scanResponseArrayLength - 1] = scanResponse;
            Sorting::InsertionSort(
                scanResponseArray.Get(), scanResponseArrayLength,
                [](const ThreadScanResponse & a, const ThreadScanResponse & b) -> bool { return a.rssi > b.rssi; });
        }

        for (size_t i = 0; i < scanResponseArrayLength; i++)
        {
            Structs::ThreadInterfaceScanResultStruct::Type result;
            Encoding::BigEndian::Put64(extendedAddressBuffer, scanResponseArray[i].extendedAddress);
            result.panId           = scanResponseArray[i].panId;
            result.extendedPanId   = scanResponseArray[i].extendedPanId;
            result.networkName     = CharSpan(scanResponseArray[i].networkName, scanResponseArray[i].networkNameLen);
            result.channel         = scanResponseArray[i].channel;
            result.version         = scanResponseArray[i].version;
            result.extendedAddress = ByteSpan(extendedAddressBuffer);
            result.rssi            = scanResponseArray[i].rssi;
            result.lqi             = scanResponseArray[i].lqi;

            SuccessOrExit(err = DataModel::Encode(*writer, TLV::AnonymousTag(), result));
        }
    }

    SuccessOrExit(err = writer->EndContainer(listContainerType));
    SuccessOrExit(err = commandHandle->FinishCommand());

exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Zcl, "Failed to encode response: %" CHIP_ERROR_FORMAT, err.Format());
    }
    if (status == Status::kSuccess)
    {
        CommitSavedBreadcrumb();
    }
    networks->Release();
#endif
}

void Instance::OnFinished(Status status, CharSpan debugText, WiFiScanResponseIterator * networks)
{
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION || CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
    CHIP_ERROR err        = CHIP_NO_ERROR;
    auto commandHandleRef = std::move(mAsyncCommandHandle);
    auto commandHandle    = commandHandleRef.Get();
    if (commandHandle == nullptr)
    {
        // When the platform shutted down, interaction model engine will invalidate all commandHandle to avoid dangling references.
        // We may receive the callback after it and should make it noop.
        return;
    }

    // If drivers are failing to respond NetworkNotFound on empty results, force it for them.
    bool resultsMissing = !networks || (networks->Count() == 0);
    if ((status == Status::kSuccess) && mScanningWasDirected && resultsMissing)
    {
        status = Status::kNetworkNotFound;
    }

    SetLastNetworkingStatusValue(MakeNullable(status));

    TLV::TLVWriter * writer;
    TLV::TLVType listContainerType;
    WiFiScanResponse scanResponse;
    size_t networksEncoded = 0;

    const CommandHandler::InvokeResponseParameters prepareParams(mPath);
    SuccessOrExit(
        err = commandHandle->PrepareInvokeResponseCommand(
            ConcreteCommandPath(mPath.mEndpointId, NetworkCommissioning::Id, Commands::ScanNetworksResponse::Id), prepareParams));
    VerifyOrExit((writer = commandHandle->GetCommandDataIBTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE);

    SuccessOrExit(err = writer->Put(TLV::ContextTag(Commands::ScanNetworksResponse::Fields::kNetworkingStatus), status));
    if (debugText.size() != 0)
    {
        SuccessOrExit(
            err = DataModel::Encode(*writer, TLV::ContextTag(Commands::ScanNetworksResponse::Fields::kDebugText), debugText));
    }
    SuccessOrExit(err = writer->StartContainer(TLV::ContextTag(Commands::ScanNetworksResponse::Fields::kWiFiScanResults),
                                               TLV::TLVType::kTLVType_Array, listContainerType));

    // Only encode results on success, to avoid stale contents on partial failure.
    if ((status == Status::kSuccess) && (networks != nullptr))
    {
        while (networks->Next(scanResponse))
        {
            Structs::WiFiInterfaceScanResultStruct::Type result;
            result.security = scanResponse.security;
            result.ssid     = ByteSpan(scanResponse.ssid, scanResponse.ssidLen);
            result.bssid    = ByteSpan(scanResponse.bssid, sizeof(scanResponse.bssid));
            result.channel  = scanResponse.channel;
            result.wiFiBand = scanResponse.wiFiBand;
            result.rssi     = scanResponse.rssi;
            SuccessOrExit(err = DataModel::Encode(*writer, TLV::AnonymousTag(), result));

            ++networksEncoded;
            if (networksEncoded >= kMaxNetworksInScanResponse)
            {
                break;
            }
        }
    }

    SuccessOrExit(err = writer->EndContainer(listContainerType));
    SuccessOrExit(err = commandHandle->FinishCommand());
exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Zcl, "Failed to encode response: %" CHIP_ERROR_FORMAT, err.Format());
    }
    if (status == Status::kSuccess)
    {
        CommitSavedBreadcrumb();
    }
    if (networks != nullptr)
    {
        networks->Release();
    }
#endif
}

void Instance::OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg)
{
    Instance * this_ = reinterpret_cast<Instance *>(arg);

    if (event->Type == DeviceLayer::DeviceEventType::kCommissioningComplete)
    {
        this_->OnCommissioningComplete();
    }
    else if (event->Type == DeviceLayer::DeviceEventType::kFailSafeTimerExpired)
    {
        this_->OnFailSafeTimerExpired();
    }
    else if ((event->Type == DeviceLayer::DeviceEventType::kWiFiDeviceAvailable) ||
             (event->Type == DeviceLayer::DeviceEventType::kOperationalNetworkStarted))

    {
        // In Non-Concurrent mode connect the operational channel, as BLE has been stopped
        this_->HandleNonConcurrentConnectNetwork();
    }
}

void Instance::OnCommissioningComplete()
{
    VerifyOrReturn(mpWirelessDriver != nullptr);

    ChipLogDetail(Zcl, "Commissioning complete, notify platform driver to persist network credentials.");
    mpWirelessDriver->CommitConfiguration();
}

void Instance::OnFailSafeTimerExpired()
{
    VerifyOrReturn(mpWirelessDriver != nullptr);

    ChipLogDetail(Zcl, "Failsafe timeout, tell platform driver to revert network credentials.");
    mpWirelessDriver->RevertConfiguration();
    mAsyncCommandHandle.Release();

    // Mark the network list changed since `mpWirelessDriver->RevertConfiguration()` may have updated it.
    ReportNetworksListChanged();

    // If no networks are left, clear-out errors;
    if (mpBaseDriver && (CountAndRelease(mpBaseDriver->GetNetworks()) == 0))
    {
        SetLastNetworkId(ByteSpan{});
        SetLastConnectErrorValue(NullNullable);
        SetLastNetworkingStatusValue(NullNullable);
    }
}

CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)
{
    using namespace Clusters::NetworkCommissioning::Commands;

    if (mFeatureFlags.Has(Feature::kThreadNetworkInterface))
    {
        for (auto && cmd : {
                 ScanNetworks::Id,
                 AddOrUpdateThreadNetwork::Id,
                 RemoveNetwork::Id,
                 ConnectNetwork::Id,
                 ReorderNetwork::Id,
             })
        {
            VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/);
        }
    }
    else if (mFeatureFlags.Has(Feature::kWiFiNetworkInterface))
    {
        for (auto && cmd : {
                 ScanNetworks::Id,
                 AddOrUpdateWiFiNetwork::Id,
                 RemoveNetwork::Id,
                 ConnectNetwork::Id,
                 ReorderNetwork::Id,
             })
        {
            VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/);
        }
    }

    if (mFeatureFlags.Has(Feature::kPerDeviceCredentials))
    {
        VerifyOrExit(callback(QueryIdentity::Id, context) == Loop::Continue, /**/);
    }

exit:
    return CHIP_NO_ERROR;
}

CHIP_ERROR Instance::EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)
{
    using namespace Clusters::NetworkCommissioning::Commands;

    if (mFeatureFlags.HasAny(Feature::kWiFiNetworkInterface, Feature::kThreadNetworkInterface))
    {
        for (auto && cmd : { ScanNetworksResponse::Id, NetworkConfigResponse::Id, ConnectNetworkResponse::Id })
        {
            VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/);
        }
    }

    if (mFeatureFlags.Has(Feature::kPerDeviceCredentials))
    {
        VerifyOrExit(callback(QueryIdentityResponse::Id, context) == Loop::Continue, /**/);
    }

exit:
    return CHIP_NO_ERROR;
}

bool NullNetworkDriver::GetEnabled()
{
    // Disable the interface and it cannot be enabled since there are no physical interfaces.
    return false;
}

uint8_t NullNetworkDriver::GetMaxNetworks()
{
    // The minimal value of MaxNetworks should be 1 per spec.
    return 1;
}

NetworkIterator * NullNetworkDriver::GetNetworks()
{
    // Instance::Read accepts nullptr as an empty NetworkIterator.
    return nullptr;
}

} // namespace NetworkCommissioning
} // namespace Clusters
} // namespace app
} // namespace chip

void MatterNetworkCommissioningPluginServerInitCallback()
{
    // Nothing to do, the server init routine will be done in Instance::Init()
}
