/*
 *
 *    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 "pw_rpc/server.h"
#include "pw_rpc_system_server/rpc_server.h"
#include "pw_rpc_system_server/socket.h"

#include <map>
#include <thread>

#include "RpcClient.h"
#include <commands/common/IcdManager.h>
#include <commands/common/StayActiveSender.h>
#include <commands/fabric-sync/FabricSyncCommand.h>
#include <commands/interactive/InteractiveCommands.h>
#include <device_manager/DeviceManager.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>
#include <system/SystemClock.h>

#if defined(PW_RPC_FABRIC_ADMIN_SERVICE) && PW_RPC_FABRIC_ADMIN_SERVICE
#include "pigweed/rpc_services/FabricAdmin.h"
#endif

using namespace ::chip;

namespace admin {

namespace {

#if defined(PW_RPC_FABRIC_ADMIN_SERVICE) && PW_RPC_FABRIC_ADMIN_SERVICE

struct ScopedNodeIdHasher
{
    std::size_t operator()(const chip::ScopedNodeId & scopedNodeId) const
    {
        std::size_t h1 = std::hash<uint64_t>{}(scopedNodeId.GetFabricIndex());
        std::size_t h2 = std::hash<uint64_t>{}(scopedNodeId.GetNodeId());
        // Bitshifting h2 reduces collisions when fabricIndex == nodeId.
        return h1 ^ (h2 << 1);
    }
};

class FabricAdmin final : public rpc::FabricAdmin, public admin::PairingDelegate, public IcdManager::Delegate
{
public:
    void OnCheckInCompleted(const app::ICDClientInfo & clientInfo) override
    {
        // Accessing mPendingCheckIn should only be done while holding ChipStackLock
        assertChipStackLockedByCurrentThread();
        ScopedNodeId scopedNodeId = clientInfo.peer_node;
        auto it                   = mPendingCheckIn.find(scopedNodeId);
        VerifyOrReturn(it != mPendingCheckIn.end());

        KeepActiveDataForCheckIn checkInData = it->second;
        // Removed from pending map as check-in from this node has occured and we will handle the pending KeepActive
        // request.
        mPendingCheckIn.erase(scopedNodeId);

        auto timeNow = System::SystemClock().GetMonotonicTimestamp();
        if (timeNow > checkInData.mRequestExpiryTimestamp)
        {
            ChipLogError(NotSpecified,
                         "ICD check-in for device we have been waiting, came after KeepActive expiry. Request dropped for ID: "
                         "[%d:0x " ChipLogFormatX64 "]",
                         scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId()));
            return;
        }

        // TODO https://github.com/CHIP-Specifications/connectedhomeip-spec/issues/10448. Spec does
        // not define what to do if we fail to send the StayActiveRequest. We are assuming that any
        // further attempts to send a StayActiveRequest will result in a similar failure. Because
        // there is no mechanism for us to communicate with the client that sent out the KeepActive
        // command that there was a failure, we simply fail silently. After spec issue is
        // addressed, we can implement what spec defines here.
        auto onDone    = [=](uint32_t promisedActiveDuration) { ActiveChanged(scopedNodeId, promisedActiveDuration); };
        CHIP_ERROR err = StayActiveSender::SendStayActiveCommand(checkInData.mStayActiveDurationMs, clientInfo.peer_node,
                                                                 app::InteractionModelEngine::GetInstance(), onDone);
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(NotSpecified, "Failed to send StayActive command %s", err.AsString());
        }
    }

    void OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) override
    {
        if (mNodeId != deviceId)
        {
            ChipLogError(NotSpecified,
                         "Tried to pair a non-bridge device (0x:" ChipLogFormatX64 ") with result: %" CHIP_ERROR_FORMAT,
                         ChipLogValueX64(deviceId), err.Format());
            return;
        }
        else
        {
            ChipLogProgress(NotSpecified, "Reverse commission succeeded for NodeId:" ChipLogFormatX64, ChipLogValueX64(mNodeId));
        }

        if (err == CHIP_NO_ERROR)
        {
            DeviceManager::Instance().SetRemoteBridgeNodeId(deviceId);
        }
        else
        {
            ChipLogError(NotSpecified, "Failed to pair bridge device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT,
                         ChipLogValueX64(deviceId), err.Format());
        }

        mNodeId = kUndefinedNodeId;
    }

    pw::Status OpenCommissioningWindow(const chip_rpc_DeviceCommissioningWindowInfo & request,
                                       chip_rpc_OperationStatus & response) override
    {
        VerifyOrReturnValue(request.has_id, pw::Status::InvalidArgument());
        ScopedNodeId scopedNodeId(request.id.node_id, request.id.fabric_index);
        uint32_t iterations              = request.iterations;
        uint16_t discriminator           = request.discriminator;
        uint16_t commissioningTimeoutSec = static_cast<uint16_t>(request.commissioning_timeout);

        // Log the request details for debugging
        ChipLogProgress(NotSpecified,
                        "Received OpenCommissioningWindow request: NodeId " ChipLogFormatX64
                        ", Timeout: %u, Iterations: %u, Discriminator: %u",
                        ChipLogValueX64(scopedNodeId.GetNodeId()), commissioningTimeoutSec, iterations, discriminator);

        // Open the device commissioning window using raw binary data for salt and verifier
        DeviceManager::Instance().OpenDeviceCommissioningWindow(scopedNodeId, iterations, commissioningTimeoutSec, discriminator,
                                                                ByteSpan(request.salt.bytes, request.salt.size),
                                                                ByteSpan(request.verifier.bytes, request.verifier.size));

        response.success = true;

        return pw::OkStatus();
    }

    pw::Status CommissionNode(const chip_rpc_DeviceCommissioningInfo & request, pw_protobuf_Empty & response) override
    {
        char saltHex[Crypto::kSpake2p_Max_PBKDF_Salt_Length * 2 + 1];
        Encoding::BytesToHex(request.salt.bytes, request.salt.size, saltHex, sizeof(saltHex), Encoding::HexFlags::kNullTerminate);

        ChipLogProgress(NotSpecified, "Received CommissionNode request");

        SetupPayload setupPayload = SetupPayload();

        setupPayload.setUpPINCode = request.setup_pin;
        setupPayload.version      = 0;
        setupPayload.vendorID     = request.vendor_id;
        setupPayload.productID    = request.product_id;
        setupPayload.rendezvousInformation.SetValue(RendezvousInformationFlag::kOnNetwork);

        SetupDiscriminator discriminator{};
        discriminator.SetLongValue(request.discriminator);
        setupPayload.discriminator = discriminator;

        QRCodeSetupPayloadGenerator generator(setupPayload);
        std::string code;
        CHIP_ERROR error = generator.payloadBase38RepresentationWithAutoTLVBuffer(code);

        if (error == CHIP_NO_ERROR)
        {
            mNodeId = DeviceManager::Instance().GetNextAvailableNodeId();

            // After responding with RequestCommissioningApproval to the node where the client initiated the
            // RequestCommissioningApproval, you need to wait for it to open a commissioning window on its bridge.
            usleep(kCommissionPrepareTimeMs * 1000);
            PairingManager::Instance().SetPairingDelegate(this);
            DeviceManager::Instance().PairRemoteDevice(mNodeId, code.c_str());
        }
        else
        {
            ChipLogError(NotSpecified, "Unable to generate pairing code for setup payload: %" CHIP_ERROR_FORMAT, error.Format());
        }

        return pw::OkStatus();
    }

    pw::Status KeepActive(const chip_rpc_KeepActiveParameters & request, pw_protobuf_Empty & response) override
    {
        VerifyOrReturnValue(request.has_id, pw::Status::InvalidArgument());
        ScopedNodeId scopedNodeId(request.id.node_id, request.id.fabric_index);
        ChipLogProgress(NotSpecified, "Received KeepActive request: Id[%d, 0x" ChipLogFormatX64 "], %u",
                        scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId()), request.stay_active_duration_ms);

        KeepActiveWorkData * data =
            Platform::New<KeepActiveWorkData>(this, scopedNodeId, request.stay_active_duration_ms, request.timeout_ms);
        VerifyOrReturnValue(data, pw::Status::Internal());
        DeviceLayer::PlatformMgr().ScheduleWork(KeepActiveWork, reinterpret_cast<intptr_t>(data));
        return pw::OkStatus();
    }

    void ScheduleSendingKeepActiveOnCheckIn(ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs)
    {
        // Accessing mPendingCheckIn should only be done while holding ChipStackLock
        assertChipStackLockedByCurrentThread();

        auto timeNow                             = System::SystemClock().GetMonotonicTimestamp();
        System::Clock::Timestamp expiryTimestamp = timeNow + System::Clock::Milliseconds64(timeoutMs);
        KeepActiveDataForCheckIn checkInData     = { .mStayActiveDurationMs   = stayActiveDurationMs,
                                                     .mRequestExpiryTimestamp = expiryTimestamp };

        auto it = mPendingCheckIn.find(scopedNodeId);
        if (it != mPendingCheckIn.end())
        {
            checkInData.mStayActiveDurationMs   = std::max(checkInData.mStayActiveDurationMs, it->second.mStayActiveDurationMs);
            checkInData.mRequestExpiryTimestamp = std::max(checkInData.mRequestExpiryTimestamp, it->second.mRequestExpiryTimestamp);
        }

        mPendingCheckIn[scopedNodeId] = checkInData;
    }

private:
    struct KeepActiveDataForCheckIn
    {
        uint32_t mStayActiveDurationMs = 0;
        System::Clock::Timestamp mRequestExpiryTimestamp;
    };

    struct KeepActiveWorkData
    {
        KeepActiveWorkData(FabricAdmin * fabricAdmin, ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs,
                           uint32_t timeoutMs) :
            mFabricAdmin(fabricAdmin),
            mScopedNodeId(scopedNodeId), mStayActiveDurationMs(stayActiveDurationMs), mTimeoutMs(timeoutMs)
        {}

        FabricAdmin * mFabricAdmin;
        ScopedNodeId mScopedNodeId;
        uint32_t mStayActiveDurationMs;
        uint32_t mTimeoutMs;
    };

    static void KeepActiveWork(intptr_t arg)
    {
        KeepActiveWorkData * data = reinterpret_cast<KeepActiveWorkData *>(arg);
        data->mFabricAdmin->ScheduleSendingKeepActiveOnCheckIn(data->mScopedNodeId, data->mStayActiveDurationMs, data->mTimeoutMs);
        Platform::Delete(data);
    }

    NodeId mNodeId = chip::kUndefinedNodeId;

    // Modifications to mPendingCheckIn should be done on the MatterEventLoop thread
    // otherwise we would need a mutex protecting this data to prevent race as this
    // data is accessible by both RPC thread and Matter eventloop.
    std::unordered_map<ScopedNodeId, KeepActiveDataForCheckIn, ScopedNodeIdHasher> mPendingCheckIn;
};

FabricAdmin fabric_admin_service;
#endif // defined(PW_RPC_FABRIC_ADMIN_SERVICE) && PW_RPC_FABRIC_ADMIN_SERVICE

void RegisterServices(pw::rpc::Server & server)
{
#if defined(PW_RPC_FABRIC_ADMIN_SERVICE) && PW_RPC_FABRIC_ADMIN_SERVICE
    server.RegisterService(fabric_admin_service);
    IcdManager::Instance().SetDelegate(&fabric_admin_service);
#endif
}

} // namespace

void RunRpcService()
{
    pw::rpc::system_server::Init();
    RegisterServices(pw::rpc::system_server::Server());
    pw::rpc::system_server::Start();
}

void InitRpcServer(uint16_t rpcServerPort)
{
    pw::rpc::system_server::set_socket_port(rpcServerPort);
    std::thread rpc_service(RunRpcService);
    rpc_service.detach();
}

} // namespace admin
