package org.dromara.mqtt;

import lombok.RequiredArgsConstructor;
import org.dromara.app.domain.mqtt.DeviceCommand;
import org.dromara.app.service.IDeviceCommandPublisher;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.mqtt.config.properties.MqttProperties;
import org.springframework.stereotype.Component;

import java.util.UUID;

@Component
@RequiredArgsConstructor
public class DeviceMqttCommandPublisher implements IDeviceCommandPublisher {

    private final MqttClientManager mqttClientManager;
    private final MqttCommandAckService ackService;
    private final MqttProperties mqttProperties;

    @Override
    public String send(DeviceCommand command) {
        long now = System.currentTimeMillis();
        if (StringUtils.isBlank(command.getCommandId())) {
            command.setCommandId(UUID.randomUUID().toString().replace("-", ""));
        }
        if (StringUtils.isBlank(command.getTopic())) {
            command.setTopic(buildCommandTopic(command.getDeviceNo()));
        }
        command.setCreatedAt(now);
        command.setLastSentAt(now);
        command.setNextRetryAt(now + mqttProperties.getCommandAck().getRetryIntervalMs());
        command.getPayload().put("commandId", command.getCommandId());
        command.getPayload().put("commandType", command.getCommandType());

        ackService.savePending(command);
        try {
            mqttClientManager.publish(command.getTopic(), JsonUtils.toJsonString(command.getPayload()));
        } catch (RuntimeException e) {
            ackService.removePending(command.getCommandId());
            throw e;
        }
        return command.getCommandId();
    }

    private String buildCommandTopic(String deviceNo) {
        if (StringUtils.isBlank(deviceNo)) {
            throw new ServiceException("命令下发缺少设备编号，无法拼接主题");
        }
        String device = deviceNo.trim().toLowerCase();
        String prefix = mqttProperties.getTopics().getPublishPrefix();
        if (StringUtils.isBlank(prefix)) {
            return "/" + device + "/subscriber/cmd";
        }
        String normalizedPrefix = prefix.startsWith("/") ? prefix : "/" + prefix;
        if (normalizedPrefix.endsWith("/")) {
            normalizedPrefix = normalizedPrefix.substring(0, normalizedPrefix.length() - 1);
        }
        return normalizedPrefix + "/" + device + "/subscriber/cmd";
    }
}
