package org.dromara.app.handler;

import cn.hutool.extra.spring.SpringUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.dromara.app.domain.bo.AppDeviceBo;
import org.dromara.app.service.IAppDeviceService;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.context.support.GenericApplicationContext;

import java.util.function.Supplier;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
@Tag("dev")
class DeviceDataHandlerTest {

    @Mock
    private IAppDeviceService appDeviceService;

    @Mock
    private DeviceIdentityResolver deviceIdentityResolver;

    @Mock
    private MqttDeviceStatusService deviceStatusService;

    @InjectMocks
    private DeviceDataHandler handler;

    @Test
    void handleMarksDeviceOnlineAndUpdatesPowerLevel() {
        when(deviceIdentityResolver.resolveDeviceNo("D01")).thenReturn("D01");

        withJsonContext(() -> {
            handler.handle("D01", "{\"powerLevel\":\"86\"}");
            return null;
        });

        ArgumentCaptor<AppDeviceBo> deviceCaptor = ArgumentCaptor.forClass(AppDeviceBo.class);
        verify(appDeviceService).updateByBo(deviceCaptor.capture());
        AppDeviceBo updatedDevice = deviceCaptor.getValue();
        assertThat(updatedDevice.getDeviceNo()).isEqualTo("D01");
        assertThat(updatedDevice.getPowerLevel()).isEqualTo("86");
        assertThat(updatedDevice.getPowerLevelUpdatatime()).isNotNull();
        verify(deviceStatusService).markOnline("D01");
    }

    private <T> T withJsonContext(Supplier<T> action) {
        try (GenericApplicationContext applicationContext = new GenericApplicationContext()) {
            applicationContext.registerBean(ObjectMapper.class, (Supplier<ObjectMapper>) ObjectMapper::new);
            applicationContext.refresh();
            new SpringUtil().setApplicationContext(applicationContext);
            return action.get();
        }
    }
}
