package cn.iocoder.yudao.module.iot.service.rule.data.action;

import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.config.IotDataSinkTcpConfig;
import cn.iocoder.yudao.module.iot.service.rule.data.action.tcp.IotTcpClient;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

/**
 * {@link IotTcpDataRuleAction} 的单元测试
 *
 * @author HUIHUI
 */
class IotTcpDataRuleActionTest {

    private IotTcpDataRuleAction tcpDataRuleAction;

    @Mock
    private IotTcpClient mockTcpClient;

    @BeforeEach
    public void setUp() {
        MockitoAnnotations.openMocks(this);
        tcpDataRuleAction = new IotTcpDataRuleAction();
    }

    @Test
    public void testGetType() {
        // 准备参数
        Integer expectedType = 2; // 数据接收类型枚举中 TCP 类型的值

        // 调用方法
        Integer actualType = tcpDataRuleAction.getType();

        // 断言结果
        assertEquals(expectedType, actualType);
    }

    @Test
    public void testInitProducer_success() throws Exception {
        // 准备参数
        IotDataSinkTcpConfig config = new IotDataSinkTcpConfig();
        config.setHost("localhost");
        config.setPort(8080);
        config.setDataFormat("JSON");
        config.setSsl(false);

        // 调用方法 & 断言结果
        // 此测试需要实际的 TCP 连接，在单元测试中可能不可用
        // 目前我们只验证配置是否有效
        assertNotNull(config.getHost());
        assertTrue(config.getPort() > 0 && config.getPort() <= 65535);
    }

    @Test
    public void testInitProducer_invalidHost() {
        // 准备参数
        IotDataSinkTcpConfig config = new IotDataSinkTcpConfig();
        config.setHost("");
        config.setPort(8080);

        // 调用方法 & 断言结果
        IotTcpDataRuleAction action = new IotTcpDataRuleAction();

        // 测试验证逻辑（通常在 initProducer 方法中）
        assertThrows(IllegalArgumentException.class, () -> {
            if (config.getHost() == null || config.getHost().trim().isEmpty()) {
                throw new IllegalArgumentException("TCP 服务器地址不能为空");
            }
        });
    }

    @Test
    public void testInitProducer_invalidPort() {
        // 准备参数
        IotDataSinkTcpConfig config = new IotDataSinkTcpConfig();
        config.setHost("localhost");
        config.setPort(-1);

        // 调用方法 & 断言结果
        assertThrows(IllegalArgumentException.class, () -> {
            if (config.getPort() == null || config.getPort() <= 0 || config.getPort() > 65535) {
                throw new IllegalArgumentException("TCP 服务器端口无效");
            }
        });
    }

    @Test
    public void testCloseProducer() throws Exception {
        // 准备参数
        IotTcpClient client = mock(IotTcpClient.class);

        // 调用方法
        tcpDataRuleAction.closeProducer(client);

        // 断言结果
        verify(client, times(1)).close();
    }

    @Test
    public void testExecute_withValidConfig() {
        // 准备参数
        IotDeviceMessage message = IotDeviceMessage.requestOf("thing.property.report",
                "{\"temperature\": 25.5, \"humidity\": 60}");

        IotDataSinkTcpConfig config = new IotDataSinkTcpConfig();
        config.setHost("localhost");
        config.setPort(8080);
        config.setDataFormat("JSON");

        // 调用方法 & 断言结果
        // 通常这需要实际的 TCP 连接
        // 在单元测试中，我们只验证输入参数
        assertNotNull(message);
        assertNotNull(config);
        assertNotNull(config.getHost());
        assertTrue(config.getPort() > 0);
    }

    @Test
    public void testConfig_defaultValues() {
        // 准备参数
        IotDataSinkTcpConfig config = new IotDataSinkTcpConfig();

        // 调用方法 & 断言结果
        // 验证默认值
        assertEquals("JSON", config.getDataFormat());
        assertEquals(5000, config.getConnectTimeoutMs());
        assertEquals(10000, config.getReadTimeoutMs());
        assertEquals(false, config.getSsl());
        assertEquals(30000L, config.getHeartbeatIntervalMs());
        assertEquals(5000L, config.getReconnectIntervalMs());
        assertEquals(3, config.getMaxReconnectAttempts());
    }

    @Test
    public void testMessageSerialization() {
        // 准备参数
        IotDeviceMessage message = IotDeviceMessage.builder()
                .deviceId(123L)
                .method("thing.property.report")
                .params(MapUtil.of("temperature", 25.5))
                .build();

        // 调用方法
        String json = JsonUtils.toJsonString(message);

        // 断言结果
        assertNotNull(json);
        assertTrue(json.contains("\"deviceId\":123"));
        assertTrue(json.contains("\"method\":\"thing.property.report\""));
        assertTrue(json.contains("\"temperature\":25.5"));
    }

}