package com.sensor.bridge;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.ArrayList;

/**
 * 메인 온도 파서
 * param.dat 기반의 정확한 온도 파싱 시스템
 */
public class TemperatureParser {
    
    private static final Logger logger = LoggerFactory.getLogger(TemperatureParser.class);
    
    // 센서 타입별 파라미터 정보
    private final List<ParamItem> paramItems;
    
    // 기본 파라미터 (rawTem * 10 공식용)
    private final ParamItem defaultParamItem;
    
    public TemperatureParser() {
        this.paramItems = new ArrayList<>();
        this.defaultParamItem = createDefaultParamItem();
        initializeDefaultParams();
    }
    
    /**
     * 온도 데이터 파싱 (메인 메서드)
     * @param data 센서 데이터
     * @param sensorType 센서 타입 (선택사항)
     * @return 파싱된 온도 값 (°C)
     */
    public double parseTemperature(SensorData data, String sensorType) {
        if (data == null) {
            logger.warn("센서 데이터가 null, 기본값 반환");
            return defaultParamItem.getDefaultValue();
        }
        
        logger.debug("온도 파싱 시작: sensorType={}, rawTem={}, floatValue={}, signedInt32Value={}", 
                    sensorType, data.getRawTem(), data.getFloatValue(), data.getSignedInt32Value());
        
        // 1. 센서 타입별 파서 선택
        SensorParser parser = selectParser(sensorType, data);
        
        // 2. param.dat 파라미터 찾기
        ParamItem paramItem = findParamItem(sensorType, data);
        
        // 3. 온도 파싱 실행
        double temperature = parser.parseTemperature(data, paramItem);
        
        // 4. 결과 검증 및 로깅
        logParsingResult(parser, paramItem, temperature, data);
        
        return temperature;
    }
    
    /**
     * 센서 타입별 파서 선택
     * @param sensorType 센서 타입
     * @param data 센서 데이터
     * @return 선택된 센서 파서
     */
    private SensorParser selectParser(String sensorType, SensorData data) {
        if (sensorType != null && !sensorType.trim().isEmpty()) {
            // 명시된 센서 타입으로 파서 생성
            SensorParser parser = SensorParserFactory.createParser(sensorType);
            logger.debug("명시된 센서 타입으로 파서 선택: {} -> {}", sensorType, parser.getSensorType());
            return parser;
        } else {
            // 센서 데이터 기반으로 최적 파서 자동 선택
            SensorParser parser = SensorParserFactory.selectBestParser(data);
            logger.debug("자동 파서 선택: {} (품질 점수: {})", 
                        parser.getSensorType(), parser.getParsingQuality(data));
            return parser;
        }
    }
    
    /**
     * param.dat 파라미터 찾기
     * @param sensorType 센서 타입
     * @param data 센서 데이터
     * @return 찾은 파라미터 정보
     */
    private ParamItem findParamItem(String sensorType, SensorData data) {
        // 1. 센서 타입별 파라미터 검색
        if (sensorType != null && !sensorType.trim().isEmpty()) {
            for (ParamItem item : paramItems) {
                if (sensorType.equalsIgnoreCase(item.getSensorType())) {
                    logger.debug("센서 타입별 파라미터 발견: {}", item);
                    return item;
                }
            }
        }
        
        // 2. 데이터 패턴 기반 파라미터 검색
        ParamItem patternParam = findParamByDataPattern(data);
        if (patternParam != null) {
            logger.debug("데이터 패턴 기반 파라미터 발견: {}", patternParam);
            return patternParam;
        }
        
        // 3. 기본 파라미터 반환
        logger.debug("기본 파라미터 사용: {}", defaultParamItem);
        return defaultParamItem;
    }
    
    /**
     * 데이터 패턴 기반 파라미터 찾기
     * @param data 센서 데이터
     * @return 찾은 파라미터 정보
     */
    private ParamItem findParamByDataPattern(SensorData data) {
        // rawTem 범위 기반 파라미터 추정
        if (data.getRawTem() >= 0 && data.getRawTem() <= 50) {
            // 기존 rawTem * 10 공식과 일치하는 파라미터
            ParamItem param = new ParamItem("ESTIMATED", "FLOAT", 10.0, 0.0);
            param.setDescription("데이터 패턴 기반 추정 (rawTem * 10)");
            logger.debug("데이터 패턴 기반 파라미터 추정: {}", param);
            return param;
        }
        
        // floatValue 범위 기반 파라미터 추정
        if (data.getFloatValue() >= -40.0 && data.getFloatValue() <= 80.0) {
            ParamItem param = new ParamItem("ESTIMATED", "FLOAT", 1.0, 0.0);
            param.setDescription("데이터 패턴 기반 추정 (floatValue 직접 사용)");
            logger.debug("데이터 패턴 기반 파라미터 추정: {}", param);
            return param;
        }
        
        return null;
    }
    
    /**
     * 파싱 결과 로깅
     * @param parser 사용된 파서
     * @param paramItem 사용된 파라미터
     * @param temperature 파싱된 온도
     * @param data 원본 센서 데이터
     */
    private void logParsingResult(SensorParser parser, ParamItem paramItem, double temperature, SensorData data) {
        logger.info("온도 파싱 완료: parser={}, paramItem={}, temperature={}°C", 
                   parser.getSensorType(), paramItem, temperature);
        
        if (logger.isDebugEnabled()) {
            logger.debug("파싱 상세 정보:");
            logger.debug("  - 원본 데이터: rawTem={}, floatValue={}, signedInt32Value={}", 
                        data.getRawTem(), data.getFloatValue(), data.getSignedInt32Value());
            logger.debug("  - 사용된 파서: {}", parser.getClass().getSimpleName());
            logger.debug("  - 파라미터: {}", paramItem);
            logger.debug("  - 최종 온도: {}°C", temperature);
        }
    }
    
    /**
     * 새로운 파라미터 추가
     * @param paramItem 추가할 파라미터
     */
    public void addParamItem(ParamItem paramItem) {
        if (paramItem != null) {
            paramItems.add(paramItem);
            logger.info("새로운 파라미터 추가: {}", paramItem);
        }
    }
    
    /**
     * 파라미터 목록 반환
     * @return 등록된 파라미터 목록
     */
    public List<ParamItem> getParamItems() {
        return new ArrayList<>(paramItems);
    }
    
    /**
     * 기본 파라미터 생성
     * @return 기본 파라미터
     */
    private ParamItem createDefaultParamItem() {
        ParamItem param = new ParamItem("DEFAULT", "FLOAT", 10.0, 0.0);
        param.setDescription("기본 파라미터 (rawTem * 10 공식)");
        param.setMinValue(-40.0);
        param.setMaxValue(80.0);
        param.setDefaultValue(25.0);
        return param;
    }
    
    /**
     * 기본 파라미터 초기화
     */
    private void initializeDefaultParams() {
        // SHT30 센서용 기본 파라미터
        ParamItem sht30Param = new ParamItem("SHT30", "FLOAT", 10.0, 0.0);
        sht30Param.setDescription("SHT30 온도 센서 (rawTem * 10)");
        sht30Param.setMinValue(-40.0);
        sht30Param.setMaxValue(80.0);
        sht30Param.setDefaultValue(25.0);
        addParamItem(sht30Param);
        
        // BME680 센서용 기본 파라미터
        ParamItem bme680Param = new ParamItem("BME680", "FLOAT", 1.0, 0.0);
        bme680Param.setDescription("BME680 환경 센서 (floatValue 직접 사용)");
        bme680Param.setMinValue(-40.0);
        bme680Param.setMaxValue(80.0);
        bme680Param.setDefaultValue(25.0);
        addParamItem(bme680Param);
        
        logger.info("기본 파라미터 초기화 완료: {}개 등록", paramItems.size());
    }
}
