#include <softbus_edge/egress/CommandExecutor.h>

#include <softbus_core/logging/Logger.h>

namespace softbus::edge {

CommandExecutor::CommandExecutor(softbus::registry::PointRegistry* registry,
                                 ShadowChannelStore* store,
                                 UplinkClient* uplink,
                                 std::string deviceId)
    : registry_(registry)
    , store_(store)
    , uplink_(uplink)
    , deviceId_(std::move(deviceId))
{
}

softbus::core::SoftbusAck CommandExecutor::execute(const softbus::api::ExecuteCommand& command)
{
    softbus::core::SoftbusAck ack;
    ack.requestId = command.requestId;
    ack.traceId = command.traceId;

    if (!registry_ || !store_) {
        ack.success = false;
        ack.error = "executor not initialized";
        return ack;
    }

    const auto entry = registry_->findByObjectRef(command.objectRef);
    if (!entry) {
        ack.success = false;
        ack.error = "unknown objectRef on edge";
        return ack;
    }

    ack.deviceId = entry->deviceId;
    ack.pointId = entry->pointId;

    if (command.command != "write") {
        ack.success = false;
        ack.error = "unsupported command";
        return ack;
    }

    const double value = command.params.value("value", 0.0);
    std::string error;
    if (!registry_->validateWriteValue(*entry, value, &error)) {
        ack.success = false;
        ack.error = error;
        return ack;
    }

    store_->write(*entry, value);
    ack.executedValue = value;
    ack.success = true;

    const int raw = store_->rawRegisterValue(*entry, value);
    SB_LOG_INFO_TRACE("CommandExecutor", command.traceId,
        "write ", entry->physicalChannel, " value=", value,
        entry->unit, " raw=", raw, " (mock AO)");

    if (uplink_) {
        uplink_->sendAck(ack);
    }
    return ack;
}

} // namespace softbus::edge
