package com.sensor.bridge;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * SHT30 온도/습도 센서 파서
 * 고정밀 온도 측정 센서 (정확도: ±0.2°C)
 */
public class SHT30Parser implements SensorParser {
    
    private static final Logger logger = LoggerFactory.getLogger(SHT30Parser.class);
    private static final String SENSOR_TYPE = "SHT30";
    
    // SHT30 센서 특성
    private static final double TEMPERATURE_ACCURACY = 0.2; // ±0.2°C
    private static final double TEMPERATURE_RESOLUTION = 0.01; // 0.01°C
    
    @Override
    public double parseTemperature(SensorData data, ParamItem paramItem) {
        logger.debug("SHT30 온도 파싱 시작: rawTem={}, floatValue={}, signedInt32Value={}", 
                    data.getRawTem(), data.getFloatValue(), data.getSignedInt32Value());
        
        // 1. param.dat 기반 보정 적용
        if (paramItem != null && paramItem.getScaleFactor() != 1.0) {
            double calibratedTemp = paramItem.calculateCalibratedTemperature(data.getRawTem());
            if (paramItem.isValidTemperature(calibratedTemp)) {
                logger.debug("SHT30 param.dat 기반 보정 적용: {} -> {}°C", data.getRawTem(), calibratedTemp);
                return calibratedTemp;
            }
        }
        
        // 2. 기본 SHT30 파싱 로직 (기존 rawTem * 10 공식)
        if (data.getRawTem() >= 0 && data.getRawTem() <= 50) {
            double temperature = data.getRawTem() * 10;
            if (isValidTemperature(temperature)) {
                logger.debug("SHT30 기본 파싱: {} -> {}°C", data.getRawTem(), temperature);
                return temperature;
            }
        }
        
        // 3. floatValue가 실제 온도인 경우
        if (data.getFloatValue() >= -40.0 && data.getFloatValue() <= 80.0) {
            logger.debug("SHT30 floatValue 사용: {}°C", data.getFloatValue());
            return data.getFloatValue();
        }
        
        // 4. signedInt32Value에서 온도 추출 시도
        if (data.getSignedInt32Value() != 0) {
            double temp = extractTemperatureFromInt32(data.getSignedInt32Value());
            if (isValidTemperature(temp)) {
                logger.debug("SHT30 signedInt32Value에서 추출: {} -> {}°C", data.getSignedInt32Value(), temp);
                return temp;
            }
        }
        
        // 5. 기본값 반환
        logger.warn("SHT30: 모든 파싱 방법 실패, 기본값 사용");
        return paramItem != null ? paramItem.getDefaultValue() : 25.0;
    }
    
    @Override
    public boolean isValid(SensorData data) {
        // SHT30 센서 데이터 유효성 검증
        return data != null && 
               (data.getRawTem() >= 0 || 
                data.getFloatValue() >= -40.0 || 
                data.getSignedInt32Value() != 0);
    }
    
    @Override
    public String getSensorType() {
        return SENSOR_TYPE;
    }
    
    @Override
    public double getParsingQuality(SensorData data) {
        if (!isValid(data)) {
            return 0.0;
        }
        
        // 파싱 품질 점수 계산 (0.0 ~ 1.0)
        double quality = 0.0;
        
        // rawTem 기반 파싱 가능성
        if (data.getRawTem() >= 0 && data.getRawTem() <= 50) {
            quality += 0.4;
        }
        
        // floatValue 기반 파싱 가능성
        if (data.getFloatValue() >= -40.0 && data.getFloatValue() <= 80.0) {
            quality += 0.4;
        }
        
        // signedInt32Value 기반 파싱 가능성
        if (data.getSignedInt32Value() != 0) {
            quality += 0.2;
        }
        
        return Math.min(quality, 1.0);
    }
    
    private double extractTemperatureFromInt32(int signedInt32Value) {
        // SHT30 특화 온도 추출 로직
        if (signedInt32Value > 500000 && signedInt32Value < 600000) {
            // 대시보드 매칭 패턴
            return signedInt32Value / 18000.0;
        }
        
        // 다른 패턴 시도
        double[] scaleFactors = {0.1, 0.01, 1.0, 10.0};
        for (double scale : scaleFactors) {
            double temp = signedInt32Value * scale;
            if (isValidTemperature(temp)) {
                return temp;
            }
        }
        
        return 25.0; // 기본값
    }
    
    private boolean isValidTemperature(double temperature) {
        return temperature >= -40.0 && temperature <= 80.0;
    }
}
