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

    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 (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, false);
    }
    else
    {
        ChipLogProgress(NotSpecified, "Device commissioning Failure: %s", ErrorStr(err));
    }

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

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

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

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
