package incheon.ags.dss.status.service.impl;

import incheon.ags.dss.status.mapper.AnaZoneStatMapper;
import incheon.ags.dss.status.service.AnaLgdFomService;
import incheon.ags.dss.status.service.StatAnalysisService;
import incheon.ags.dss.status.vo.AnaLgdFomDtlVO;
import incheon.ags.dss.status.vo.AnaLgdFomMstVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("statAnalysisService")
@RequiredArgsConstructor
@Slf4j
public class StatAnalysisServiceImpl implements StatAnalysisService {

    private final AnaZoneStatMapper mapper;
    private final AnaLgdFomService anaLgdFomService;

    @Async("dssAnalysisExecutor")
    @Transactional
    public void executeStatusAnalysisAsync(int tareNo, String userId) {
        log.info(">>> [Async Start] Status Analysis Zone: {}", tareNo);
        try {
            mapper.deleteAnaZoneStatByTareNo(tareNo);

            // A. 기본 범례 생성
            int lgdFrmNo = 0;
            try {
                AnaLgdFomMstVO defaultLgdVO = createDefaultLegendVO(userId);
                lgdFrmNo = anaLgdFomService.saveAnaLgdFom(defaultLgdVO);
            } catch (Exception e) {
            	// 실패해도 로직이 계속되는 구간이므로 warn 레벨 유지하되 메시지 은닉
                log.warn("기본 범례 자동 생성 실패 (기본값 ID: 1 사용)");
                log.debug("Legend Creation Failed", e);
                lgdFrmNo = 1;
            }

            // B. 연도별 계산
            List<String> years = mapper.selectAvailableAnalysisYears();
            if (years != null) {
                for (String yearStr : years) {
                    Map<String, Object> params = new HashMap<>();
                    params.put("tareNo", tareNo);
                    params.put("baye", yearStr);
                    params.put("userId", userId);
                    mapper.insertCalculatedZoneStat(params);
                }
            }
            log.info("<<< [Async End] Status Analysis Complete Zone: {}", tareNo);

        } catch (Exception e) {
            log.error("Status Analysis Failed", e);
        }
    }



    // [신규] 폴링 완료 시 호출할 기본 범례 ID 생성/조회 메서드
    @Override
    public int getDefaultLegendId(String userId) throws Exception {
        int lgdFrmNo = 0;
        try {
            // 기존에 있던 createDefaultLegendVO 메서드 활용
            AnaLgdFomMstVO defaultLgdVO = createDefaultLegendVO(userId);
            // 범례 저장 후 생성된 ID 반환
            lgdFrmNo = anaLgdFomService.saveAnaLgdFom(defaultLgdVO);
        } catch (Exception e) {
        	// 실패해도 로직이 계속되는 구간이므로 warn 레벨 유지하되 메시지 은닉
            log.warn("기본 범례 자동 생성 실패 (기본값 ID: 1 사용)");
            log.debug("Legend Creation Failed", e);
            lgdFrmNo = 1; // 실패 시 Fallback ID
        }
        return lgdFrmNo;
    }

    /**
     * [Private] 기본 범례 데이터 생성 헬퍼 메서드
     * - 기존 XML에 하드코딩 되어있던 값을 Java 객체로 변환
     */
    private AnaLgdFomMstVO createDefaultLegendVO(String userId) {
        AnaLgdFomMstVO mst = new AnaLgdFomMstVO();
        mst.setUserId(userId);
        mst.setLOGIN_USER_ID(userId); // Audit용
        mst.setClsfMth("AUTO");
        mst.setClsfStp(5);
        mst.setColrMod("CUSTOM");
        mst.setTrsp(80);

        List<AnaLgdFomDtlVO> dtlList = new ArrayList();

        // 1단계
        dtlList.add(createDtlVO(1, 0, 2000, "#f1eef6", "매우 낮음", userId));
        // 2단계
        dtlList.add(createDtlVO(2, 2000, 4000, "#bdc9e1", "낮음", userId));
        // 3단계
        dtlList.add(createDtlVO(3, 4000, 6000, "#74a9cf", "보통", userId));
        // 4단계
        dtlList.add(createDtlVO(4, 6000, 8000, "#2b8cbe", "높음", userId));
        // 5단계
        dtlList.add(createDtlVO(5, 8000, 10000, "#045a8d", "매우 높음", userId));

        mst.setDtlList(dtlList);
        return mst;
    }

    /**
     * 상세 VO 생성 헬퍼 (BigDecimal 변환 적용)
     */
    private AnaLgdFomDtlVO createDtlVO(int seq, double min, double max, String color, String label, String userId) {
        AnaLgdFomDtlVO dtl = new AnaLgdFomDtlVO();
        dtl.setSortSeq(seq);

        // [수정됨] double -> BigDecimal 변환
        dtl.setSectionMiva(BigDecimal.valueOf(min));
        dtl.setSectionMavl(BigDecimal.valueOf(max));

        dtl.setFlinColr(color);
        dtl.setLblCn(label);
        dtl.setLOGIN_USER_ID(userId);
        return dtl;
    }
}
