/*
 *   Copyright (c) 2026 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 "ThreadMeshcopCommissionProxy.h"

#include <lib/core/CHIPEncoding.h>
#include <lib/dnssd/TxtFields.h>
#include <lib/dnssd/minimal_mdns/core/QNameString.h> // nogncheck
#include <lib/support/BytesToHex.h>
#include <lib/support/CHIPMemString.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <transport/raw/MessageHeader.h>

#include <json/json.h>

#include <errno.h>
#include <inttypes.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>

#include <chrono>
#include <thread>

using namespace chip;

namespace {
/**
 * Internal OT Commissioner Logger implementation.
 */
class CommissionerLogger : public ot::commissioner::Logger
{
public:
    void Log(ot::commissioner::LogLevel level, const std::string & region, const std::string & message) override
    {
        ChipLogProgress(Controller, "[ot-commissioner][%u][%s] %s", static_cast<unsigned>(level), region.c_str(), message.c_str());
    }
};

constexpr char kMatterCServiceSuffix[] = "_matterc._udp.local";

uint64_t JoinerIdFromBytes(const std::vector<uint8_t> & bytes)
{
    const uint8_t * buffer = bytes.data();
    return Encoding::BigEndian::Read64(buffer);
}

std::vector<uint8_t> DiscoveryCodeToVector(Thread::DiscoveryCode code)
{
    uint8_t bytes[sizeof(uint64_t)];
    Encoding::BigEndian::Put64(bytes, code.AsUInt64());
    return std::vector<uint8_t>(bytes, bytes + sizeof(bytes));
}

} // namespace

namespace chip {
namespace Controller {

ThreadMeshcopCommissionProxy::ThreadMeshcopCommissionProxy() : mState(State::kConnecting), mPromiseFulfilled(false)
{
    mCommissioner = ot::commissioner::Commissioner::Create(*this);
}

ThreadMeshcopCommissionProxy::~ThreadMeshcopCommissionProxy()
{
    std::unique_lock<std::recursive_mutex> lock(mMutex);
    if (mProxyFd != -1)
    {
        if (shutdown(mProxyFd, SHUT_RDWR) == 0 || errno != EBADF)
        {
            close(mProxyFd);
        }

        mProxyFd = -1;
    }

    if (mProxyThread.joinable())
    {
        lock.unlock();
        mProxyThread.join();
    }
}

void ThreadMeshcopCommissionProxy::ResetCommissionerForDiscovery()
{
    std::unique_lock<std::recursive_mutex> lock(mMutex);
    if (mProxyFd != -1)
    {
        if (shutdown(mProxyFd, SHUT_RDWR) == 0 || errno != EBADF)
        {
            close(mProxyFd);
        }
        mProxyFd = -1;
    }

    if (mProxyThread.joinable())
    {
        lock.unlock();
        mProxyThread.join();
        lock.lock();
    }

    mServicePort  = 0;
    mCommissioner = ot::commissioner::Commissioner::Create(*this);
}

void ThreadMeshcopCommissionProxy::SetState(State state)
{
    mState = state;
}

void ThreadMeshcopCommissionProxy::OnHeader(mdns::Minimal::ConstHeaderRef & header)
{
    ChipLogDetail(Controller, "mDNS Response: ID=%u, Answers=%u, Additional=%u", header.GetMessageId(), header.GetAnswerCount(),
                  header.GetAdditionalCount());
}

void ThreadMeshcopCommissionProxy::OnQuery(const mdns::Minimal::QueryData & data)
{
    if (mState != State::kDiscovering)
    {
        ChipLogProgress(Controller, "Received mDNS query but proxy is not in discovery state");
    }

    ChipLogDetail(Controller, "mDNS query: %s", mdns::Minimal::QNameString(data.GetName()).c_str());
    mNodeData.Set<Dnssd::CommissionNodeData>();
}

void ThreadMeshcopCommissionProxy::OnResource(mdns::Minimal::ResourceType section, const mdns::Minimal::ResourceData & data)
{
    if (mState != State::kDiscovering)
    {
        return;
    }

    auto name             = mdns::Minimal::QNameString(data.GetName());
    auto & commissionData = mNodeData.Get<Dnssd::CommissionNodeData>();

    commissionData.threadMeshcop = true;

    switch (data.GetType())
    {
    case mdns::Minimal::QType::A:
    case mdns::Minimal::QType::AAAA:
        Platform::CopyString(commissionData.hostName, name.c_str());
        break;

    case mdns::Minimal::QType::SRV: {
        mdns::Minimal::SrvRecord srv;
        if (!srv.Parse(data.GetData(), mDnsPacket))
        {
            ChipLogError(Controller, "Failed to parse mDNS SRV record");
            return;
        }

        if (!name.EndsWith(kMatterCServiceSuffix))
        {
            ChipLogDetail(Controller, "Ignoring non-Matter service: %s", name.c_str());
            return;
        }

        // Extract the instance label (portion before "._matterc._udp.local") for CommissionNodeData::instanceName.
        std::string fullName(name.c_str());
        constexpr size_t kMatterCServiceSuffixLen = sizeof(kMatterCServiceSuffix) - 1; // exclude null terminator
        if (fullName.length() >= kMatterCServiceSuffixLen)
        {
            fullName.erase(fullName.length() - kMatterCServiceSuffixLen);
        }
        Platform::CopyString(commissionData.instanceName, fullName.c_str());

        mServicePort = srv.GetPort();

        if (mProxyFd == -1)
        {
            CHIP_ERROR err = CreateProxySocket(commissionData);
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(Controller, "Failed to setup proxy socket: %" CHIP_ERROR_FORMAT, err.Format());
                SetState(State::kAborted);
            }
        }
        break;
    }

    case mdns::Minimal::QType::TXT:
        mdns::Minimal::ParseTxtRecord(data.GetData(), this);
        break;

    default:
        break;
    }
}

CHIP_ERROR ThreadMeshcopCommissionProxy::CreateProxySocket(chip::Dnssd::CommissionNodeData & commissionData)
{
    mProxyFd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
    VerifyOrReturnError(mProxyFd >= 0, CHIP_ERROR_POSIX(errno));

    sockaddr_in6 addr = {};
    addr.sin6_family  = AF_INET6;
    addr.sin6_port    = 0;
    addr.sin6_addr    = in6addr_loopback;

    if (bind(mProxyFd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)) != 0)
    {
        close(mProxyFd);
        mProxyFd = -1;
        return CHIP_ERROR_POSIX(errno);
    }

    socklen_t addr_len = sizeof(addr);
    if (getsockname(mProxyFd, reinterpret_cast<struct sockaddr *>(&addr), &addr_len) == -1)
    {
        close(mProxyFd);
        mProxyFd = -1;
        return CHIP_ERROR_POSIX(errno);
    }

    commissionData.numIPs       = 1;
    commissionData.port         = ntohs(addr.sin6_port);
    commissionData.ipAddress[0] = Inet::IPAddress::FromSockAddr(addr);
    commissionData.interfaceId  = Inet::InterfaceId::FromIPAddress(commissionData.ipAddress[0]);

    ChipLogProgress(Controller, "Proxy socket created on port %u", commissionData.port);
    return CHIP_NO_ERROR;
}

std::string ThreadMeshcopCommissionProxy::GetLastDiscoveryDiagnosticJson()
{
    DiscoveryDiagnostic diagnostic;
    {
        std::lock_guard<std::recursive_mutex> lock(mMutex);
        diagnostic = mLastDiscoveryDiagnostic;
    }

    Json::Value root(Json::objectValue);
    Json::StreamWriterBuilder writerBuilder;

    char steeringDataHex[ot::commissioner::kMaxSteeringDataLength * 2 + 1];
    char rotatingIdHex[Dnssd::kMaxRotatingIdLen * 2 + 1];
    if (Encoding::BytesToUppercaseHexString(diagnostic.steeringData.data(), diagnostic.steeringData.size(), steeringDataHex,
                                            sizeof(steeringDataHex)) != CHIP_NO_ERROR)
    {
        diagnostic.valid = false;
    }
    if (Encoding::BytesToUppercaseHexString(diagnostic.commissionData.rotatingId, diagnostic.commissionData.rotatingIdLen,
                                            rotatingIdHex, sizeof(rotatingIdHex)) != CHIP_NO_ERROR)
    {
        diagnostic.valid = false;
    }
    root["valid"] = diagnostic.valid;
    if (!diagnostic.valid)
    {
        return Json::writeString(writerBuilder, root);
    }

    root["requested_discriminator_type"] = diagnostic.requestedShort ? "short" : "long";
    root["requested_discriminator"]      = static_cast<Json::Value::UInt>(diagnostic.requestedValue);
    root["expected_long_discriminator"]  = static_cast<Json::Value::UInt>(diagnostic.expectedLongValue);
    root["discovery_code"]               = static_cast<Json::Value::UInt64>(diagnostic.discoveryCode);
    root["steering_data_hex"]            = steeringDataHex;
    root["joiner_id"]                    = static_cast<Json::Value::UInt64>(diagnostic.joinerId);
    root["joiner_udp_port"]              = static_cast<Json::Value::UInt>(diagnostic.joinerUdpPort);

    Json::Value dnsAnnouncement(Json::objectValue);
    dnsAnnouncement["long_discriminator"] = static_cast<Json::Value::UInt>(diagnostic.commissionData.longDiscriminator);
    dnsAnnouncement["commissioning_mode"] = static_cast<Json::Value::UInt>(diagnostic.commissionData.commissioningMode);
    dnsAnnouncement["device_type"]        = static_cast<Json::Value::UInt>(diagnostic.commissionData.deviceType);
    dnsAnnouncement["vendor_id"]          = static_cast<Json::Value::UInt>(diagnostic.commissionData.vendorId);
    dnsAnnouncement["product_id"]         = static_cast<Json::Value::UInt>(diagnostic.commissionData.productId);
    dnsAnnouncement["pairing_hint"]       = static_cast<Json::Value::UInt>(diagnostic.commissionData.pairingHint);
    dnsAnnouncement["service_port"]       = static_cast<Json::Value::UInt>(diagnostic.matterUdpPort);
    dnsAnnouncement["thread_meshcop"]     = diagnostic.commissionData.threadMeshcop;
    dnsAnnouncement["supports_commissioner_generated_passcode"] = diagnostic.commissionData.supportsCommissionerGeneratedPasscode;
    dnsAnnouncement["instance_name"]                            = diagnostic.commissionData.instanceName;
    dnsAnnouncement["hostname"]                                 = diagnostic.commissionData.hostName;
    dnsAnnouncement["rotating_id_hex"]                          = rotatingIdHex;
    root["dns_announcement"]                                    = dnsAnnouncement;

    return Json::writeString(writerBuilder, root);
}

void ThreadMeshcopCommissionProxy::OnRecord(const mdns::Minimal::BytesRange & name, const mdns::Minimal::BytesRange & value)
{
    ByteSpan key(name.Start(), name.Size());
    ByteSpan val(value.Start(), value.Size());

    Dnssd::FillNodeDataFromTxt(key, val, mNodeData.Get<Dnssd::CommissionNodeData>());
}

void ThreadMeshcopCommissionProxy::ProcessAnnouncement(const std::vector<uint8_t> & joinerIdBytes, uint16_t joinerPort,
                                                       const std::vector<uint8_t> & payload)
{
    std::lock_guard<std::recursive_mutex> lock(mMutex);

    if (mPromiseFulfilled)
    {
        return;
    }

    mNodeData.Set<Dnssd::CommissionNodeData>();
    mDnsPacket = mdns::Minimal::BytesRange(payload.data(), payload.data() + payload.size());

    if (!mdns::Minimal::ParsePacket(mDnsPacket, this))
    {
        ChipLogError(Controller, "Failed to parse joiner mDNS announcement");
        return;
    }

    uint32_t discoveredDiscriminator = mNodeData.Get<Dnssd::CommissionNodeData>().longDiscriminator;
    ChipLogProgress(Controller, "Discovered joiner with discriminator: %u", discoveredDiscriminator);

    if (!mExpectedDiscriminator.MatchesLongDiscriminator(static_cast<uint16_t>(discoveredDiscriminator)))
    {
        ChipLogProgress(Controller, "Discriminator mismatch (Expected %u, Got %u). Ignoring announcement.",
                        mExpectedDiscriminator.GetLongValue(), discoveredDiscriminator);
        return;
    }

    mDiscoveredNodePromise.set_value(mNodeData);
    mPromiseFulfilled = true;

    mLastDiscoveryDiagnostic.valid          = true;
    mLastDiscoveryDiagnostic.joinerId       = JoinerIdFromBytes(joinerIdBytes);
    mLastDiscoveryDiagnostic.joinerUdpPort  = joinerPort;
    mLastDiscoveryDiagnostic.matterUdpPort  = mServicePort;
    mLastDiscoveryDiagnostic.commissionData = mNodeData.Get<Dnssd::CommissionNodeData>();

    SetState(State::kDiscovered);

    if (mProxyThread.joinable())
    {
        mProxyThread.join();
    }

    mProxyThread = std::thread([id = joinerIdBytes, this]() {
        struct sockaddr_storage addr;
        socklen_t len = sizeof(addr);
        uint8_t buf[chip::detail::kMaxIPPacketSizeBytes];
        ssize_t received;

        while ((received = recvfrom(mProxyFd, buf, sizeof(buf), 0, reinterpret_cast<struct sockaddr *>(&addr), &len)) > 0)
        {
            switch (mState)
            {
            case State::kDiscovered: {
                int rval = connect(mProxyFd, reinterpret_cast<struct sockaddr *>(&addr), len);
                if (rval < 0)
                {
                    ChipLogError(Controller, "Failed to connect to Matter Commissioner: %s", strerror(errno));
                    continue;
                }
                SetState(State::kCommissioning);
                FALLTHROUGH;
            }

            case State::kCommissioning: {
                std::vector<uint8_t> pkt(buf, buf + received);

                auto error = mCommissioner->SendToJoiner(id, mServicePort, pkt);
                if (error != ot::commissioner::ErrorCode::kNone)
                {
                    ChipLogError(Controller, "Failed to send packet to joiner: %s", error.GetMessage().c_str());
                    return;
                }
                break;
            }
            default:
                ChipLogError(Controller, "Invalid CommissionProxy state: %d", static_cast<int>(mState.load()));
                return;
            }
        }
    });
}

void ThreadMeshcopCommissionProxy::OnJoinerMessage(const std::vector<uint8_t> & joinerIdBytes, uint16_t joinerPort,
                                                   const std::vector<uint8_t> & payload)
{
    std::lock_guard<std::recursive_mutex> lock(mMutex);

    if (joinerIdBytes.size() != sizeof(uint64_t) || mState == State::kAborted)
    {
        return;
    }

    uint64_t joinerId = JoinerIdFromBytes(joinerIdBytes);
    ChipLogDetail(Controller, "Message from joiner 0x%" PRIx64 " on port %u", joinerId, joinerPort);

    if (mJoinerId == 0)
    {
        mJoinerId = joinerId;
    }
    else if (mJoinerId != joinerId)
    {
        ChipLogProgress(Controller, "Ignoring message from unexpected joiner 0x%" PRIx64, joinerId);
        return;
    }

    switch (mState)
    {
    case State::kCommissioning:
        if (mProxyFd != -1)
        {
            if (send(mProxyFd, payload.data(), payload.size(), 0) < 0)
            {
                ChipLogError(Controller, "Failed to forward packet to local proxy: %s", strerror(errno));
                SetState(State::kAborted);
            }
        }
        break;
    case State::kAborted:
        break;
    case State::kConnecting:
        // First message from joiner is usually the mDNS announcement
        SetState(State::kDiscovering);
        FALLTHROUGH;
    case State::kDiscovering:
        ProcessAnnouncement(joinerIdBytes, joinerPort, payload);
        break;
    case State::kDiscovered:
        ChipLogProgress(Controller, "WARNING ignore unsolicited messages after joiner is already discovered");
        break;
    }
}

ot::commissioner::CommissionerDataset ThreadMeshcopCommissionProxy::MakeCommissionerDataset(Thread::DiscoveryCode code)
{
    ot::commissioner::CommissionerDataset dataset;

    dataset.mJoinerUdpPort = ot::commissioner::kDefaultJoinerUdpPort;
    dataset.mPresentFlags |= ot::commissioner::CommissionerDataset::kJoinerUdpPortBit;
    dataset.mPresentFlags &=
        ~(ot::commissioner::CommissionerDataset::kSessionIdBit | ot::commissioner::CommissionerDataset::kBorderAgentLocatorBit);

    if (code.IsAny())
    {
        dataset.mSteeringData = std::vector<uint8_t>{ 0xff };
    }
    else
    {
        std::vector<uint8_t> steeringData(ot::commissioner::kMaxSteeringDataLength);
        ot::commissioner::Commissioner::AddJoiner(steeringData, DiscoveryCodeToVector(code));
        dataset.mSteeringData = steeringData;
    }

    dataset.mPresentFlags |= ot::commissioner::CommissionerDataset::kSteeringDataBit;
    return dataset;
}
CHIP_ERROR ThreadMeshcopCommissionProxy::InitializeCommissioner(ByteSpan & pskc)
{
    VerifyOrReturnError(pskc.size() == Thread::kSizePSKc, CHIP_ERROR_INVALID_ARGUMENT);
    ot::commissioner::Config config;
    config.mLogger    = std::make_shared<CommissionerLogger>();
    config.mEnableCcm = false;
    config.mProxyMode = true;
    config.mPSKc      = std::vector<uint8_t>(pskc.begin(), pskc.end());

    auto error = mCommissioner->Init(config);
    if (error != ot::commissioner::ErrorCode::kNone)
    {
        ChipLogError(Controller, "OT Commissioner Init failed: %s", error.GetMessage().c_str());
        return CHIP_ERROR_INTERNAL;
    }
    return CHIP_NO_ERROR;
}

CHIP_ERROR ThreadMeshcopCommissionProxy::Discover(ByteSpan & pskc, const Transport::PeerAddress & peerAddr,
                                                  const Thread::DiscoveryCode code, SetupDiscriminator expectedDiscriminator,
                                                  Dnssd::DiscoveredNodeData & nodeData, uint16_t timeout)
{
    using ot::commissioner::Error;

    Error error;
    ResetCommissionerForDiscovery();

    // Reset the promise and state for a new discovery session
    std::future<Dnssd::DiscoveredNodeData> future;
    {
        std::lock_guard<std::recursive_mutex> lock(mMutex);
        mExpectedDiscriminator = expectedDiscriminator;
        SetState(State::kConnecting);
        mDiscoveredNodePromise                  = std::promise<Dnssd::DiscoveredNodeData>();
        future                                  = mDiscoveredNodePromise.get_future();
        mPromiseFulfilled                       = false;
        mJoinerId                               = 0;
        mLastDiscoveryDiagnostic                = DiscoveryDiagnostic();
        mLastDiscoveryDiagnostic.requestedShort = expectedDiscriminator.IsShortDiscriminator();
        mLastDiscoveryDiagnostic.requestedValue =
            mLastDiscoveryDiagnostic.requestedShort ? expectedDiscriminator.GetShortValue() : expectedDiscriminator.GetLongValue();
        mLastDiscoveryDiagnostic.expectedLongValue =
            expectedDiscriminator.IsShortDiscriminator() ? 0 : expectedDiscriminator.GetLongValue();
        mLastDiscoveryDiagnostic.discoveryCode = code.AsUInt64();
    }

    ReturnErrorOnFailure(InitializeCommissioner(pskc));

    {
        std::string id;
        char host[Inet::IPAddress::kMaxStringLength];
        peerAddr.GetIPAddress().ToString(host);

        ChipLogProgress(Controller, "Petitioning Thread Border Agent at %s:%u", host, peerAddr.GetPort());
        error = mCommissioner->Petition(id, std::string(host), peerAddr.GetPort());
        if (error != ot::commissioner::ErrorCode::kNone)
        {
            ChipLogError(Controller, "Petition failed: %s", error.GetMessage().c_str());
            SetState(State::kAborted);
            return CHIP_ERROR_INTERNAL;
        }

        ChipLogProgress(Controller, "Thread Commissioner active with ID: %s", id.c_str());
    }

    auto commissionerDataset = MakeCommissionerDataset(code);
    {
        std::lock_guard<std::recursive_mutex> lock(mMutex);
        mLastDiscoveryDiagnostic.steeringData = commissionerDataset.mSteeringData;
    }

    error = mCommissioner->SetCommissionerDataset(commissionerDataset);
    if (error != ot::commissioner::ErrorCode::kNone)
    {
        ChipLogError(Controller, "Failed to set Steering Data: %s", error.GetMessage().c_str());
        SetState(State::kAborted);
        return CHIP_ERROR_INTERNAL;
    }

    ChipLogProgress(Controller, "Waiting for mDNS announcement from joiner...");
    auto waitDuration = std::chrono::seconds(timeout);
    if (future.wait_for(waitDuration) == std::future_status::timeout)
    {
        ChipLogError(Controller, "Timed out waiting for joiner mDNS announcement after %u seconds", timeout);
        SetState(State::kAborted);
        return CHIP_ERROR_TIMEOUT;
    }
    nodeData = future.get();
    return CHIP_NO_ERROR;
}
} // namespace Controller
} // namespace chip
