package com.sensor.bridge;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import static org.junit.jupiter.api.Assertions.*;

/**
 * SensorDataParser 클래스의 단위 테스트
 */
public class SensorDataParserTest {

    @BeforeEach
    void setUp() {
        // 테스트 전 초기화 작업
    }

    @Test
    void testParseTemperature() {
        // 테스트 케이스 1: signedInt32Value가 실제 온도인 경우
        double temp1 = SensorDataParser.parseTemperature(0.0, 0.0, 524306);
        assertEquals(29.1, temp1, 0.1, "온도 변환 테스트 1 실패");

        // 테스트 케이스 2: rawTem이 0.1도 단위인 경우
        double temp2 = SensorDataParser.parseTemperature(2.91, 0.0, 0);
        assertEquals(29.1, temp2, 0.1, "온도 변환 테스트 2 실패");

        // 테스트 케이스 3: floatValue가 실제 온도인 경우
        double temp3 = SensorDataParser.parseTemperature(0.0, 29.1, 0);
        assertEquals(29.1, temp3, 0.1, "온도 변환 테스트 3 실패");

        // 테스트 케이스 4: 기본값 반환
        double temp4 = SensorDataParser.parseTemperature(0.0, 0.0, 0);
        assertEquals(25.0, temp4, 0.1, "온도 기본값 테스트 실패");
    }

    @Test
    void testParseHumidity() {
        // 테스트 케이스 1: rawHum이 0.8인 경우 (35.0%로 변환)
        double humidity1 = SensorDataParser.parseHumidity(0.8);
        assertEquals(35.0, humidity1, 0.1, "습도 변환 테스트 1 실패");

        // 테스트 케이스 2: rawHum이 이미 적절한 범위인 경우
        double humidity2 = SensorDataParser.parseHumidity(60.0);
        assertEquals(60.0, humidity2, 0.1, "습도 변환 테스트 2 실패");

        // 테스트 케이스 3: 기본값 반환
        double humidity3 = SensorDataParser.parseHumidity(0.0);
        assertEquals(60.0, humidity3, 0.1, "습도 기본값 테스트 실패");
    }

    @Test
    void testParsePM10() {
        // 테스트 케이스 1: floatValue가 유효한 범위인 경우
        double pm10_1 = SensorDataParser.parsePM10(25.5, 0);
        assertEquals(25.5, pm10_1, 0.1, "PM10 floatValue 테스트 실패");

        // 테스트 케이스 2: signedInt32Value에서 추출
        double pm10_2 = SensorDataParser.parsePM10(0.0, 2550); // 2550 / 100 = 25.5
        assertEquals(25.5, pm10_2, 0.1, "PM10 signedInt32Value 테스트 실패");
    }

    @Test
    void testParsePM25() {
        // 테스트 케이스 1: floatValue가 유효한 범위인 경우
        double pm25_1 = SensorDataParser.parsePM25(12.3, 0);
        assertEquals(12.3, pm25_1, 0.1, "PM2.5 floatValue 테스트 실패");

        // 테스트 케이스 2: signedInt32Value에서 추출 (상위 16비트)
        double pm25_2 = SensorDataParser.parsePM25(0.0, 1230 << 16); // 1230 / 100 = 12.3
        assertEquals(12.3, pm25_2, 0.1, "PM2.5 signedInt32Value 테스트 실패");
    }

    @Test
    void testParsePressure() {
        // 테스트 케이스: signedInt32Value에서 기압 추출
        double pressure = SensorDataParser.parsePressure(101325 << 16); // 1013.25 hPa
        assertEquals(1013.25, pressure, 0.1, "기압 변환 테스트 실패");
    }

    @Test
    void testParseIllumination() {
        // 테스트 케이스 1: floatValue가 유효한 범위인 경우
        double illumination1 = SensorDataParser.parseIllumination(500.0, 0);
        assertEquals(500.0, illumination1, 0.1, "조도 floatValue 테스트 실패");

        // 테스트 케이스 2: unsignedInt32Value에서 추출
        double illumination2 = SensorDataParser.parseIllumination(0.0, 50); // 50 * 10 = 500 lux
        assertEquals(500.0, illumination2, 0.1, "조도 unsignedInt32Value 테스트 실패");
    }

    @Test
    void testParseTVOC() {
        // 테스트 케이스 1: floatValue가 유효한 범위인 경우
        double tvoc1 = SensorDataParser.parseTVOC(150.0, 0);
        assertEquals(150.0, tvoc1, 0.1, "TVOC floatValue 테스트 실패");

        // 테스트 케이스 2: signedInt32Value에서 추출
        double tvoc2 = SensorDataParser.parseTVOC(0.0, 150);
        assertEquals(150.0, tvoc2, 0.1, "TVOC signedInt32Value 테스트 실패");
    }

    @Test
    void testParseCO2() {
        // 테스트 케이스 1: floatValue가 유효한 범위인 경우
        double co2_1 = SensorDataParser.parseCO2(800.0, 0);
        assertEquals(800.0, co2_1, 0.1, "CO2 floatValue 테스트 실패");

        // 테스트 케이스 2: signedInt32Value에서 추출 (상위 16비트)
        double co2_2 = SensorDataParser.parseCO2(0.0, 400 << 16); // 400 + 400 = 800 ppm
        assertEquals(800.0, co2_2, 0.1, "CO2 signedInt32Value 테스트 실패");
    }

    @Test
    void testParseO2() {
        // 테스트 케이스 1: floatValue가 유효한 범위인 경우
        double o2_1 = SensorDataParser.parseO2(20.9, 0);
        assertEquals(20.9, o2_1, 0.1, "O2 floatValue 테스트 실패");

        // 테스트 케이스 2: unsignedInt32Value에서 추출 (상위 16비트)
        double o2_2 = SensorDataParser.parseO2(0.0, 2090 << 16); // 2090 / 100 = 20.9%
        assertEquals(20.9, o2_2, 0.1, "O2 unsignedInt32Value 테스트 실패");
    }

    @Test
    void testParseCO() {
        // 테스트 케이스 1: floatValue가 유효한 범위인 경우
        double co1 = SensorDataParser.parseCO(2.5, 0);
        assertEquals(2.5, co1, 0.01, "CO floatValue 테스트 실패");

        // 테스트 케이스 2: signedInt32Value에서 추출
        double co2 = SensorDataParser.parseCO(0.0, 250); // 250 / 100 = 2.5 ppm
        assertEquals(2.5, co2, 0.01, "CO signedInt32Value 테스트 실패");
    }

    @Test
    void testEdgeCases() {
        // 경계값 테스트
        assertDoesNotThrow(() -> {
            SensorDataParser.parseTemperature(Double.MAX_VALUE, Double.MAX_VALUE, Integer.MAX_VALUE);
            SensorDataParser.parseHumidity(Double.MAX_VALUE);
            SensorDataParser.parsePM10(Double.MAX_VALUE, Integer.MAX_VALUE);
            SensorDataParser.parsePM25(Double.MAX_VALUE, Integer.MAX_VALUE);
            SensorDataParser.parsePressure(Integer.MAX_VALUE);
            SensorDataParser.parseIllumination(Double.MAX_VALUE, Long.MAX_VALUE);
            SensorDataParser.parseTVOC(Double.MAX_VALUE, Integer.MAX_VALUE);
            SensorDataParser.parseCO2(Double.MAX_VALUE, Integer.MAX_VALUE);
            SensorDataParser.parseO2(Double.MAX_VALUE, Long.MAX_VALUE);
            SensorDataParser.parseCO(Double.MAX_VALUE, Integer.MAX_VALUE);
        }, "경계값 테스트에서 예외가 발생했습니다");
    }
} 