/*
 *    Copyright (c) 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 "PairingManager.h"
#include "DeviceManager.h"
#include "DeviceSynchronization.h"
#include "FabricAdmin.h"

#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>

#include <lib/support/logging/CHIPLogging.h>
#include <setup_payload/ManualSetupPayloadParser.h>
#include <setup_payload/QRCodeSetupPayloadParser.h>

using namespace ::chip;
using namespace ::chip::Controller;

namespace admin {

namespace {

CHIP_ERROR GetPayload(const char * setUpCode, SetupPayload & payload)
{
    VerifyOrReturnValue(setUpCode, CHIP_ERROR_INVALID_ARGUMENT);
    bool isQRCode = strncmp(setUpCode, kQRCodePrefix, strlen(kQRCodePrefix)) == 0;
    if (isQRCode)
    {
        ReturnErrorOnFailure(QRCodeSetupPayloadParser(setUpCode).populatePayload(payload));
        VerifyOrReturnError(payload.isValidQRCodePayload(), CHIP_ERROR_INVALID_ARGUMENT);
    }
    else
    {
        ReturnErrorOnFailure(ManualSetupPayloadParser(setUpCode).populatePayload(payload));
        VerifyOrReturnError(payload.isValidManualCode(), CHIP_ERROR_INVALID_ARGUMENT);
    }

    return CHIP_NO_ERROR;
}

bool ParseAddressWithInterface(const char * addressString, Inet::IPAddress & address, Inet::InterfaceId & interfaceId)
{
    struct addrinfo hints;
    struct addrinfo * result;
    int ret;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family   = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;
    ret               = getaddrinfo(addressString, nullptr, &hints, &result);
    if (ret < 0)
    {
        ChipLogError(NotSpecified, "Invalid address: %s", addressString);
        return false;
    }

    if (result->ai_family == AF_INET6)
    {
        struct sockaddr_in6 * addr = reinterpret_cast<struct sockaddr_in6 *>(result->ai_addr);
        address                    = Inet::IPAddress::FromSockAddr(*addr);
        interfaceId                = Inet::InterfaceId(addr->sin6_scope_id);
    }
#if INET_CONFIG_ENABLE_IPV4
    else if (result->ai_family == AF_INET)
    {
        address     = Inet::IPAddress::FromSockAddr(*reinterpret_cast<struct sockaddr_in *>(result->ai_addr));
        interfaceId = Inet::InterfaceId::Null();
    }
#endif // INET_CONFIG_ENABLE_IPV4
    else
    {
        ChipLogError(NotSpecified, "Unsupported address: %s", addressString);
        freeaddrinfo(result);
        return false;
    }

    freeaddrinfo(result);
    return true;
}

} // namespace

PairingManager::PairingManager() :
    mOnOpenCommissioningWindowCallback(OnOpenCommissioningWindowResponse, this),
    mOnOpenCommissioningWindowVerifierCallback(OnOpenCommissioningWindowVerifierResponse, this),
    mCurrentFabricRemoveCallback(OnCurrentFabricRemove, this)
{}

CHIP_ERROR PairingManager::Init(Controller::DeviceCommissioner * commissioner)
{
    VerifyOrReturnError(commissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
    FabricAdmin::Instance().GetDefaultICDClientStorage().UpdateFabricList(commissioner->GetFabricIndex());
    mCommissioner = commissioner;

    return CHIP_NO_ERROR;
}

CHIP_ERROR PairingManager::OpenCommissioningWindow(NodeId nodeId, EndpointId endpointId, uint16_t commissioningTimeoutSec,
                                                   uint32_t iterations, uint16_t discriminator, const ByteSpan & salt,
                                                   const ByteSpan & verifier)
{
    if (mCommissioner == nullptr)
    {
        ChipLogError(NotSpecified, "Commissioner is null, cannot open commissioning window");
        return CHIP_ERROR_INCORRECT_STATE;
    }

    // Check if a window is already open
    if (mWindowOpener != nullptr)
    {
        ChipLogError(NotSpecified, "A commissioning window is already open");
        return CHIP_ERROR_INCORRECT_STATE;
    }

    // Ensure salt and verifier sizes are valid
    if (!salt.empty() && salt.size() > chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length)
    {
        ChipLogError(NotSpecified, "Salt size exceeds buffer capacity");
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }

    if (!verifier.empty() && verifier.size() > chip::Crypto::kSpake2p_VerifierSerialized_Length)
    {
        ChipLogError(NotSpecified, "Verifier size exceeds buffer capacity");
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }

    if (!salt.empty())
    {
        memcpy(mSaltBuffer, salt.data(), salt.size());
        mSalt = ByteSpan(mSaltBuffer, salt.size());
    }
    else
    {
        mSalt = ByteSpan();
    }

    if (!verifier.empty())
    {
        memcpy(mVerifierBuffer, verifier.data(), verifier.size());
        mVerifier = ByteSpan(mVerifierBuffer, verifier.size());
    }
    else
    {
        mVerifier = ByteSpan();
    }

    return DeviceLayer::SystemLayer().ScheduleLambda([nodeId, endpointId, commissioningTimeoutSec, iterations, discriminator]() {
        PairingManager & self = PairingManager::Instance();

        if (self.mCommissioner == nullptr)
        {
            ChipLogError(NotSpecified, "Commissioner is null, cannot open commissioning window");
            return;
        }

        self.mWindowOpener = Platform::MakeUnique<Controller::CommissioningWindowOpener>(self.mCommissioner);

        if (!self.mVerifier.empty())
        {
            if (self.mSalt.empty())
            {
                ChipLogError(NotSpecified, "Salt is required when verifier is set");
                self.mWindowOpener.reset();
                return;
            }

            // Open the commissioning window with verifier parameters
            CHIP_ERROR err =
                self.mWindowOpener->OpenCommissioningWindow(Controller::CommissioningWindowVerifierParams()
                                                                .SetNodeId(nodeId)
                                                                .SetEndpointId(endpointId)
                                                                .SetTimeout(commissioningTimeoutSec)
                                                                .SetIteration(iterations)
                                                                .SetDiscriminator(discriminator)
                                                                .SetVerifier(self.mVerifier)
                                                                .SetSalt(self.mSalt)
                                                                .SetCallback(&self.mOnOpenCommissioningWindowVerifierCallback));
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(NotSpecified, "Failed to open commissioning window with verifier: %s", ErrorStr(err));
                self.mWindowOpener.reset();
            }
        }
        else
        {
            SetupPayload ignored;
            // Open the commissioning window with passcode parameters
            CHIP_ERROR err = self.mWindowOpener->OpenCommissioningWindow(Controller::CommissioningWindowPasscodeParams()
                                                                             .SetNodeId(nodeId)
                                                                             .SetEndpointId(endpointId)
                                                                             .SetTimeout(commissioningTimeoutSec)
                                                                             .SetIteration(iterations)
                                                                             .SetDiscriminator(discriminator)
                                                                             .SetSetupPIN(NullOptional)
                                                                             .SetSalt(NullOptional)
                                                                             .SetCallback(&self.mOnOpenCommissioningWindowCallback),
                                                                         ignored);
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(NotSpecified, "Failed to open commissioning window with passcode: %s", ErrorStr(err));
                self.mWindowOpener.reset();
            }
        }
    });
}

void PairingManager::OnOpenCommissioningWindowResponse(void * context, NodeId remoteId, CHIP_ERROR err, SetupPayload payload)
{
    VerifyOrDie(context != nullptr);
    PairingManager * self = static_cast<PairingManager *>(context);
    if (self->mCommissioningWindowDelegate)
    {
        self->mCommissioningWindowDelegate->OnCommissioningWindowOpened(remoteId, err, payload);
        self->SetOpenCommissioningWindowDelegate(nullptr);
    }

    OnOpenCommissioningWindowVerifierResponse(context, remoteId, err);
}

void PairingManager::OnOpenCommissioningWindowVerifierResponse(void * context, NodeId remoteId, CHIP_ERROR err)
{
    VerifyOrDie(context != nullptr);
    PairingManager * self = static_cast<PairingManager *>(context);
    LogErrorOnFailure(err);

    // Reset the window opener once the window operation is complete
    self->mWindowOpener.reset();
}

void PairingManager::OnStatusUpdate(DevicePairingDelegate::Status status)
{
    switch (status)
    {
    case DevicePairingDelegate::Status::SecurePairingSuccess:
        ChipLogProgress(NotSpecified, "CASE establishment successful");
        break;
    case DevicePairingDelegate::Status::SecurePairingFailed:
        ChipLogError(NotSpecified, "Secure Pairing Failed");
        break;
    }
}

void PairingManager::OnPairingComplete(CHIP_ERROR err)
{
    if (err == CHIP_NO_ERROR)
    {
        ChipLogProgress(NotSpecified, "PASE establishment successful");
    }
    else
    {
        ChipLogProgress(NotSpecified, "Pairing Failure: %s", ErrorStr(err));
    }
}

void PairingManager::OnPairingDeleted(CHIP_ERROR err)
{
    if (err == CHIP_NO_ERROR)
    {
        ChipLogProgress(NotSpecified, "Pairing Deleted Success");
    }
    else
    {
        ChipLogProgress(NotSpecified, "Pairing Deleted Failure: %s", ErrorStr(err));
    }
}

void PairingManager::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err)
{
    if (mPairingDelegate)
    {
        mPairingDelegate->OnCommissioningComplete(nodeId, err);
        SetPairingDelegate(nullptr);
    }

    if (err == CHIP_NO_ERROR)
    {
        // print to console
        fprintf(stderr, "New device with Node ID: " ChipLogFormatX64 " has been successfully added.\n", ChipLogValueX64(nodeId));

        // mCommissioner has a lifetime that is the entire life of the application itself
        // so it is safe to provide to StartDeviceSynchronization.
        DeviceSynchronizer::Instance().StartDeviceSynchronization(mCommissioner, nodeId, mDeviceIsICD);
    }
    else
    {
        // When ICD device commissioning fails, the ICDClientInfo stored in OnICDRegistrationComplete needs to be removed.
        if (mDeviceIsICD)
        {
            CHIP_ERROR deleteEntryError = FabricAdmin::Instance().GetDefaultICDClientStorage().DeleteEntry(
                ScopedNodeId(nodeId, mCommissioner->GetFabricIndex()));
            if (deleteEntryError != CHIP_NO_ERROR)
            {
                ChipLogError(NotSpecified, "Failed to delete ICD entry: %s", ErrorStr(err));
            }
        }
        ChipLogProgress(NotSpecified, "Device commissioning Failure: %s", ErrorStr(err));
    }
}

void PairingManager::OnReadCommissioningInfo(const Controller::ReadCommissioningInfo & info)
{
    ChipLogProgress(AppServer, "OnReadCommissioningInfo - vendorId=0x%04X productId=0x%04X", info.basic.vendorId,
                    info.basic.productId);

    // The string in CharSpan received from the device is not null-terminated, we use std::string here for coping and
    // appending a null-terminator at the end of the string.
    std::string userActiveModeTriggerInstruction;

    // Note: the callback doesn't own the buffer, should make a copy if it will be used it later.
    if (info.icd.userActiveModeTriggerInstruction.size() != 0)
    {
        userActiveModeTriggerInstruction =
            std::string(info.icd.userActiveModeTriggerInstruction.data(), info.icd.userActiveModeTriggerInstruction.size());
    }

    if (info.icd.userActiveModeTriggerHint.HasAny())
    {
        ChipLogProgress(AppServer, "OnReadCommissioningInfo - LIT UserActiveModeTriggerHint=0x%08x",
                        info.icd.userActiveModeTriggerHint.Raw());
        ChipLogProgress(AppServer, "OnReadCommissioningInfo - LIT UserActiveModeTriggerInstruction=%s",
                        userActiveModeTriggerInstruction.c_str());
    }
    ChipLogProgress(AppServer, "OnReadCommissioningInfo ICD - IdleModeDuration=%u activeModeDuration=%u activeModeThreshold=%u",
                    info.icd.idleModeDuration, info.icd.activeModeDuration, info.icd.activeModeThreshold);
}

void PairingManager::OnICDRegistrationComplete(ScopedNodeId nodeId, uint32_t icdCounter)
{
    char icdSymmetricKeyHex[Crypto::kAES_CCM128_Key_Length * 2 + 1];

    Encoding::BytesToHex(mICDSymmetricKey.Value().data(), mICDSymmetricKey.Value().size(), icdSymmetricKeyHex,
                         sizeof(icdSymmetricKeyHex), Encoding::HexFlags::kNullTerminate);

    app::ICDClientInfo clientInfo;
    clientInfo.peer_node         = nodeId;
    clientInfo.monitored_subject = mICDMonitoredSubject.Value();
    clientInfo.start_icd_counter = icdCounter;
    auto & ICDClientStorage      = FabricAdmin::Instance().GetDefaultICDClientStorage();

    CHIP_ERROR err = ICDClientStorage.SetKey(clientInfo, mICDSymmetricKey.Value());
    if (err == CHIP_NO_ERROR)
    {
        err = ICDClientStorage.StoreEntry(clientInfo);
    }

    if (err != CHIP_NO_ERROR)
    {
        ICDClientStorage.RemoveKey(clientInfo);
        ChipLogError(NotSpecified, "Failed to persist symmetric key for " ChipLogFormatX64 ": %s",
                     ChipLogValueX64(nodeId.GetNodeId()), err.AsString());
        return;
    }

    mDeviceIsICD = true;

    ChipLogProgress(NotSpecified, "Saved ICD Symmetric key for " ChipLogFormatX64, ChipLogValueX64(nodeId.GetNodeId()));
    ChipLogProgress(NotSpecified,
                    "ICD Registration Complete for device " ChipLogFormatX64 " / Check-In NodeID: " ChipLogFormatX64
                    " / Monitored Subject: " ChipLogFormatX64 " / Symmetric Key: %s / ICDCounter %u",
                    ChipLogValueX64(nodeId.GetNodeId()), ChipLogValueX64(mICDCheckInNodeId.Value()),
                    ChipLogValueX64(mICDMonitoredSubject.Value()), icdSymmetricKeyHex, icdCounter);
}

void PairingManager::OnICDStayActiveComplete(ScopedNodeId deviceId, uint32_t promisedActiveDuration)
{
    ChipLogProgress(NotSpecified, "ICD Stay Active Complete for device " ChipLogFormatX64 " / promisedActiveDuration: %u",
                    ChipLogValueX64(deviceId.GetNodeId()), promisedActiveDuration);
}

void PairingManager::OnDiscoveredDevice(const Dnssd::CommissionNodeData & nodeData)
{
    // Ignore nodes with closed commissioning window
    VerifyOrReturn(nodeData.commissioningMode != 0);

    auto & resolutionData = nodeData;

    const uint16_t port = resolutionData.port;
    char buf[Inet::IPAddress::kMaxStringLength];
    resolutionData.ipAddress[0].ToString(buf);
    ChipLogProgress(NotSpecified, "Discovered Device: %s:%u", buf, port);

    // Stop Mdns discovery.
    auto err = mCommissioner->StopCommissionableDiscovery();

    // Some platforms does not implement a mechanism to stop mdns browse, so
    // we just ignore CHIP_ERROR_NOT_IMPLEMENTED instead of bailing out.
    if (CHIP_NO_ERROR != err && CHIP_ERROR_NOT_IMPLEMENTED != err)
    {
        return;
    }

    mCommissioner->RegisterDeviceDiscoveryDelegate(nullptr);

    auto interfaceId = resolutionData.ipAddress[0].IsIPv6LinkLocal() ? resolutionData.interfaceId : Inet::InterfaceId::Null();
    auto peerAddress = Transport::PeerAddress::UDP(resolutionData.ipAddress[0], port, interfaceId);
    err              = Pair(mNodeId, peerAddress);
    if (CHIP_NO_ERROR != err)
    {
        ChipLogProgress(NotSpecified, "Failed to pair device: " ChipLogFormatX64 " %s", ChipLogValueX64(mNodeId), ErrorStr(err));
    }
}

Optional<uint16_t> PairingManager::FailSafeExpiryTimeoutSecs() const
{
    // No manual input, so do not need to extend.
    return Optional<uint16_t>();
}

bool PairingManager::ShouldWaitAfterDeviceAttestation()
{
    // If there is a vendor ID and product ID, request OnDeviceAttestationCompleted().
    // Currently this is added in the case that the example is performing reverse commissioning,
    // but it would be an improvement to store that explicitly.
    // TODO: Issue #35297 - [Fabric Sync] Improve where we get VID and PID when validating CCTRL CommissionNode command
    SetupPayload payload;
    CHIP_ERROR err = GetPayload(mOnboardingPayload, payload);
    return err == CHIP_NO_ERROR && (payload.vendorID != 0 || payload.productID != 0);
}

void PairingManager::OnDeviceAttestationCompleted(Controller::DeviceCommissioner * deviceCommissioner, DeviceProxy * device,
                                                  const Credentials::DeviceAttestationVerifier::AttestationDeviceInfo & info,
                                                  Credentials::AttestationVerificationResult attestationResult)
{
    SetupPayload payload;
    CHIP_ERROR parse_error = GetPayload(mOnboardingPayload, payload);
    if (parse_error == CHIP_NO_ERROR && (payload.vendorID != 0 || payload.productID != 0))
    {
        if (payload.vendorID == 0 || payload.productID == 0)
        {
            ChipLogProgress(NotSpecified,
                            "Failed validation: vendorID or productID must not be 0."
                            "Requested VID: %u, Requested PID: %u.",
                            payload.vendorID, payload.productID);
            deviceCommissioner->ContinueCommissioningAfterDeviceAttestation(
                device, Credentials::AttestationVerificationResult::kInvalidArgument);
            return;
        }

        if (payload.vendorID != info.BasicInformationVendorId() || payload.productID != info.BasicInformationProductId())
        {
            ChipLogProgress(NotSpecified,
                            "Failed validation of vendorID or productID."
                            "Requested VID: %u, Requested PID: %u,"
                            "Detected VID: %u, Detected PID %u.",
                            payload.vendorID, payload.productID, info.BasicInformationVendorId(), info.BasicInformationProductId());
            deviceCommissioner->ContinueCommissioningAfterDeviceAttestation(
                device,
                payload.vendorID == info.BasicInformationVendorId()
                    ? Credentials::AttestationVerificationResult::kDacProductIdMismatch
                    : Credentials::AttestationVerificationResult::kDacVendorIdMismatch);
            return;
        }

        // NOTE: This will log errors even if the attestion was successful.
        CHIP_ERROR err = deviceCommissioner->ContinueCommissioningAfterDeviceAttestation(device, attestationResult);
        if (CHIP_NO_ERROR != err)
        {
            ChipLogError(NotSpecified, "Failed to continue commissioning after device attestation, error: %s", ErrorStr(err));
        }
        return;
    }

    // Don't bypass attestation, continue with error.
    CHIP_ERROR err = deviceCommissioner->ContinueCommissioningAfterDeviceAttestation(device, attestationResult);
    if (CHIP_NO_ERROR != err)
    {
        ChipLogError(NotSpecified, "Failed to continue commissioning after device attestation, error: %s", ErrorStr(err));
    }
}

CommissioningParameters PairingManager::GetCommissioningParameters()
{
    auto params = CommissioningParameters();
    params.SetSkipCommissioningComplete(false);
    params.SetDeviceAttestationDelegate(this);

    if (mICDRegistration.ValueOr(false))
    {
        params.SetICDRegistrationStrategy(ICDRegistrationStrategy::kBeforeComplete);

        if (!mICDSymmetricKey.HasValue())
        {
            Crypto::DRBG_get_bytes(mRandomGeneratedICDSymmetricKey, sizeof(mRandomGeneratedICDSymmetricKey));
            mICDSymmetricKey.SetValue(ByteSpan(mRandomGeneratedICDSymmetricKey));
        }
        if (!mICDCheckInNodeId.HasValue())
        {
            mICDCheckInNodeId.SetValue(mCommissioner->GetNodeId());
        }
        if (!mICDMonitoredSubject.HasValue())
        {
            mICDMonitoredSubject.SetValue(mICDCheckInNodeId.Value());
        }
        if (!mICDClientType.HasValue())
        {
            mICDClientType.SetValue(app::Clusters::IcdManagement::ClientTypeEnum::kPermanent);
        }
        // These Optionals must have values now.
        // The commissioner will verify these values.
        params.SetICDSymmetricKey(mICDSymmetricKey.Value());
        if (mICDStayActiveDurationMsec.HasValue())
        {
            params.SetICDStayActiveDurationMsec(mICDStayActiveDurationMsec.Value());
        }
        params.SetICDCheckInNodeId(mICDCheckInNodeId.Value());
        params.SetICDMonitoredSubject(mICDMonitoredSubject.Value());
        params.SetICDClientType(mICDClientType.Value());
    }

    return params;
}

CHIP_ERROR PairingManager::Pair(NodeId remoteId, Transport::PeerAddress address)
{
    auto params = RendezvousParameters().SetSetupPINCode(mSetupPINCode).SetDiscriminator(mDiscriminator).SetPeerAddress(address);

    CHIP_ERROR err           = CHIP_NO_ERROR;
    auto commissioningParams = GetCommissioningParameters();
    err                      = CurrentCommissioner().PairDevice(remoteId, params, commissioningParams);

    return err;
}

void PairingManager::OnCurrentFabricRemove(void * context, NodeId nodeId, CHIP_ERROR err)
{
    PairingManager * self = reinterpret_cast<PairingManager *>(context);
    VerifyOrReturn(self != nullptr, ChipLogError(NotSpecified, "OnCurrentFabricRemove: context is null"));

    ChipLogProgress(NotSpecified, "PairingManager::OnCurrentFabricRemove");

    if (err == CHIP_NO_ERROR)
    {
        // print to console
        fprintf(stderr, "Device with Node ID: " ChipLogFormatX64 " has been successfully removed.\n", ChipLogValueX64(nodeId));

        if (self->mPairingDelegate)
        {
            self->mPairingDelegate->OnDeviceRemoved(nodeId, err);
            self->SetPairingDelegate(nullptr);
        }

        FabricIndex fabricIndex = self->CurrentCommissioner().GetFabricIndex();
        app::InteractionModelEngine::GetInstance()->ShutdownSubscriptions(fabricIndex, nodeId);
        ScopedNodeId scopedNodeId(nodeId, fabricIndex);
        DeviceManager::Instance().RemoveSyncedDevice(scopedNodeId);
    }
    else
    {
        ChipLogProgress(NotSpecified, "Device unpair Failure: " ChipLogFormatX64 " %s", ChipLogValueX64(nodeId), ErrorStr(err));
    }
}

void PairingManager::InitPairingCommand()
{
    mCommissioner->RegisterPairingDelegate(this);
    mDeviceIsICD = false;
}

CHIP_ERROR PairingManager::PairDeviceWithCode(NodeId nodeId, const char * payload)
{
    if (payload == nullptr || strlen(payload) > kMaxManualCodeLength + 1)
    {
        ChipLogError(NotSpecified, "PairDeviceWithCode failed: Invalid pairing payload");
        return CHIP_ERROR_INVALID_STRING_LENGTH;
    }

    Platform::CopyString(mOnboardingPayload, sizeof(mOnboardingPayload), payload);

    return DeviceLayer::SystemLayer().ScheduleLambda([nodeId]() {
        PairingManager & self = PairingManager::Instance();

        self.InitPairingCommand();

        CommissioningParameters commissioningParams = self.GetCommissioningParameters();
        auto discoveryType                          = DiscoveryType::kDiscoveryNetworkOnly;

        self.mNodeId = nodeId;

        CHIP_ERROR err = self.mCommissioner->PairDevice(nodeId, self.mOnboardingPayload, commissioningParams, discoveryType);
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(NotSpecified, "Failed to pair device with code, error: %s", ErrorStr(err));
        }
    });
}

CHIP_ERROR PairingManager::PairDevice(chip::NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp,
                                      uint16_t deviceRemotePort)
{
    if (deviceRemoteIp == nullptr || strlen(deviceRemoteIp) > Inet::IPAddress::kMaxStringLength)
    {
        ChipLogError(NotSpecified, "PairDevice failed: Invalid device remote IP address");
        return CHIP_ERROR_INVALID_STRING_LENGTH;
    }

    Platform::CopyString(mRemoteIpAddr, sizeof(mRemoteIpAddr), deviceRemoteIp);

    return DeviceLayer::SystemLayer().ScheduleLambda([nodeId, setupPINCode, deviceRemotePort]() {
        PairingManager & self = PairingManager::Instance();

        self.InitPairingCommand();
        self.mSetupPINCode = setupPINCode;

        Inet::IPAddress address;
        Inet::InterfaceId interfaceId;

        if (!ParseAddressWithInterface(self.mRemoteIpAddr, address, interfaceId))
        {
            ChipLogError(NotSpecified, "Invalid IP address: %s", self.mRemoteIpAddr);
            return;
        }

        CHIP_ERROR err = self.Pair(nodeId, Transport::PeerAddress::UDP(address, deviceRemotePort, interfaceId));
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(NotSpecified, "Failed to pair device, error: %s", ErrorStr(err));
        }
    });
}

CHIP_ERROR PairingManager::UnpairDevice(NodeId nodeId)
{
    return DeviceLayer::SystemLayer().ScheduleLambda([nodeId]() {
        PairingManager & self = PairingManager::Instance();

        self.InitPairingCommand();

        self.mCurrentFabricRemover = Platform::MakeUnique<Controller::CurrentFabricRemover>(self.mCommissioner);

        if (!self.mCurrentFabricRemover)
        {
            ChipLogError(NotSpecified, "Failed to unpair device, mCurrentFabricRemover is null");
            return;
        }

        CHIP_ERROR err = self.mCurrentFabricRemover->RemoveCurrentFabric(nodeId, &self.mCurrentFabricRemoveCallback);
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(NotSpecified, "Failed to unpair device, error: %s", ErrorStr(err));
        }
    });
}

} // namespace admin
