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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.time.LocalDate;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import incheon.ags.dss.config.mapper.SimZoneDtlMapper;
import incheon.ags.dss.config.mapper.SimZoneMstMapper;
import incheon.ags.dss.config.vo.SimZoneDtlVO;
import incheon.ags.dss.config.vo.SimZoneMstVO;
import incheon.ags.dss.report.mapper.SimRptpItemMapper;
import incheon.ags.dss.report.mapper.SimRptpMstMapper;
import incheon.ags.dss.report.service.SimRptpService;
import incheon.ags.dss.report.vo.SimRptpItemVO;
import incheon.ags.dss.report.vo.SimRptpMstVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import incheon.ags.dss.status.mapper.AnaLgdFomMapper;
// [각 도메인 Mapper]
import incheon.ags.dss.status.mapper.AnaZoneStatMapper;        // 통계
import incheon.ags.dss.decline.mapper.AnaZoneDgnsDtlMapper;   // 진단
import incheon.ags.dss.decline.vo.AnaZoneDgnsDtlVO;
import incheon.ags.dss.regen.mapper.UrbFcltyAnlsMapper;
import incheon.ags.dss.regen.mapper.UrbMdlMstMapper;          // 시설
import incheon.ags.dss.regen.vo.UrbFcltyAnlsDtlVO;
import incheon.ags.dss.regen.vo.UrbMdlMstVO;
import incheon.ags.dss.green.mapper.UrbGrnznAnlsMapper;     // 녹지 분석
import incheon.ags.dss.green.vo.UrbGrnznAnlsMstVO;
import incheon.ags.dss.green.vo.UrbGrnznAnlsDtlVO;
import incheon.ags.dss.under.mapper.UrbUdgdFcltyMapper;     // 지하
import incheon.ags.dss.under.vo.UrbUdgdFcltyDtlVO;
import incheon.com.cmm.context.RequestContext;

@Service("simRptpMstService")
@RequiredArgsConstructor
@Slf4j
public class SimRptpServiceImpl implements SimRptpService {

	private final SimRptpMstMapper simRptpMstMapper;
    private final SimRptpItemMapper simRptpItemMapper;
    private final SimZoneMstMapper simZoneMstMapper;
    private final SimZoneDtlMapper simZoneDtlMapper;
    
    private final AnaZoneStatMapper anaZoneStatMapper;
    private final AnaLgdFomMapper anaLgdFomMapper;         // [추가] 범례 Mapper 주입
    private final AnaZoneDgnsDtlMapper anaZoneDgnsDtlMapper;
    private final UrbMdlMstMapper urbMdlMstMapper;
    private final UrbGrnznAnlsMapper urbGrnznAnlsMapper; 
    private final UrbUdgdFcltyMapper urbUdgdFcltyDtlMapper;
    private final UrbFcltyAnlsMapper urbFcltyAnlsMapper; // [추가]

    /**
     * 보고서 상세 조회
     */
    @Override
    public SimRptpMstVO selectSimRptpDetail(SimRptpMstVO vo) throws Exception {
        
        SimRptpMstVO mstData = simRptpMstMapper.selectSimRptpMstDetail(vo);
        
        if (mstData != null) {
            Long zoneNo = mstData.getZoneNo();
            
            // 1. [공통] 구역 정보 조회
            SimZoneMstVO zoneMst = simZoneMstMapper.selectSimZoneMstDetail(SimZoneMstVO.builder().zoneNo(zoneNo).build());
            
            // 2. 목차(아이템) 조회
            List<SimRptpItemVO> itemList = simRptpItemMapper.selectSimRptpItemList(SimRptpItemVO.builder().rptpNo(mstData.getRptpNo()).build());
            mstData.setItemList(itemList);
            
            // 3. 데이터 조립을 위한 Map 초기화
            Map<String, Object> reportData = new HashMap<>();
            
            // 문서 번호 및 기본 정보 설정
            int currentYear = LocalDate.now().getYear();
            
            // [수정] RPTP 문자열에서 숫자만 추출하여 포맷팅 (예: RPTP00...059 -> 59)
            int seqNo = 0;
            try {
                // 숫자가 아닌 문자(RPTP 등)를 모두 제거하고 정수로 변환 (앞의 0 제거됨)
                String numStr = mstData.getRptpNo().replaceAll("[^0-9]", "");
                seqNo = Integer.parseInt(numStr);
            } catch (Exception e) {
            	log.warn("보고서 번호 시퀀스 파싱 실패 (기본값 0 적용): {}", mstData.getRptpNo());
                // 파싱 실패 시 0 또는 원본 유지 등 처리 (여기선 0으로 안전 처리)
                seqNo = 0;
            }
            
            String docNo = String.format("제 %d - %04d 호", currentYear, seqNo);
            reportData.put("docNo", docNo);
            
            String reqName = mstData.getUserNm();
            if (reqName == null || reqName.isEmpty()) {
                reqName = mstData.getFrstRegId();
            }
            reportData.put("requestor", reqName);
            reportData.put("publishDate", mstData.getFrstRegDt());
            
            // =========================================================
            // [리스트 초기화] 중복 선택 가능성을 고려하여 개별 리스트로 관리
            // =========================================================
            List<Map<String, Object>> statsResults = new ArrayList<>();   // 통계(S) - N개
            List<Map<String, Object>> diagResults = new ArrayList<>();    // 진단(D) - N개
            List<Map<String, Object>> greenResults = new ArrayList<>();   // 녹지(G) - N개
            
            List<Map<String, Object>> underResults = new ArrayList<>();   // 지하(U) - ★병합 안함 (N개)
            List<Map<String, Object>> fcltyResults = new ArrayList<>();   // 시설분석(FA) - ★병합 안함 (N개)
            List<Map<String, Object>> accessResults = new ArrayList<>();  // 접근도(AA) - ★병합 안함 (N개)
            
            List<UrbMdlMstVO> mergedModelList = new ArrayList<>();        // 시설배치(P) - ★유일하게 병합
            
            // 4. 아이템 순회 및 데이터 조회
            for (SimRptpItemVO item : itemList) {
                String se = item.getArtclSe(); 
                String hstryNo = item.getHstryNo();
                String itemTitle = item.getArtclNm();

                // [1] 종합 요약 (단건)
                if ("1".equals(se)) {
                	Map<String, Object> headerInfo = simRptpMstMapper.selectReportHeaderInfo(zoneNo);
                	reportData.put("summary_zoneNm", headerInfo.get("target_name"));
                	reportData.put("summary_centerAddr", headerInfo.get("center_addr"));
                	reportData.put("summary_map_center", headerInfo.get("center_coord"));
                	reportData.put("summary_area", headerInfo.get("area_size"));
                	reportData.put("summary_pop", headerInfo.get("est_pop"));
                }
                // [2] 위치도 (단건)
                else if ("2".equals(se)) {
                    if (zoneMst != null) {
                        reportData.put("location_geom", zoneMst.getGeom());
                        reportData.put("location_center", zoneMst.getCepoCrdnt());
                        reportData.put("indctColr", zoneMst.getIndctColr());
                    }
                }
                // [S] 통계 (N개 허용)
                else if ("S".equals(se)) {
                    Map<String, Object> mapMst = anaZoneStatMapper.selectAnaStatsMapMstDetail(hstryNo);
                    if (mapMst != null) {
                        Map<String, Object> statData = new HashMap<>();
                        statData.put("anlsNo", hstryNo); // [필수 추가] 식별자
                        statData.put("title", itemTitle);
                        
                        String crtrYr = String.valueOf(mapMst.get("crtr_yr"));
                        String cmprYr = String.valueOf(mapMst.get("cmpr_yr"));
                        statData.put("stat_crtrYear", crtrYr);
                        statData.put("stat_cmprYear", cmprYr);
                        
                        // 범례 조회
                        if (mapMst.get("lgd_frm_no") != null) {
                            try {
                                int lgdFrmNo = Integer.parseInt(String.valueOf(mapMst.get("lgd_frm_no")));
                                if(lgdFrmNo > 0) {
                                    statData.put("legendList", anaLgdFomMapper.selectAnaLgdFomDtlList(lgdFrmNo));
                                }
                            } catch(Exception e) { log.error("범례 오류", e); }
                        }

                        // 기준년도 데이터
                        Map<String, Object> paramsCrtr = new HashMap<>();
                        paramsCrtr.put("tareNo", mstData.getZoneNo());
                        paramsCrtr.put("baye", crtrYr);
                        paramsCrtr.put("userId", vo.getLOGIN_USER_ID());
                        statData.put("gapList", anaZoneStatMapper.selectGapAnalysisAll(paramsCrtr));

                        // 비교년도 데이터
                        Map<String, Object> paramsCmpr = new HashMap<>();
                        paramsCmpr.put("tareNo", mstData.getZoneNo());
                        paramsCmpr.put("baye", cmprYr);
                        statData.put("gapList_cmpr", anaZoneStatMapper.selectGapAnalysisAll(paramsCmpr));
                        
                        statsResults.add(statData);
                    }
                }                
             	// [D] 진단 (N개 허용)
                else if ("D".equals(se)) {
                    AnaZoneDgnsDtlVO dtlVO = anaZoneDgnsDtlMapper.selectAnaZoneDgnsDtlDetail(AnaZoneDgnsDtlVO.builder().dgnsNo(hstryNo).build());
                    if (dtlVO != null) {
                        Map<String, Object> diagData = new HashMap<>();
                        diagData.put("anlsNo", hstryNo); // [필수 추가] 식별자
                        diagData.put("title", itemTitle);
                        diagData.put("diagInfo", dtlVO); 
                        
                        String crtrYear = dtlVO.getCrtrPnttm();
                        String predcYear = dtlVO.getPredcPnttm();

                        Map<String, Object> paramsCrtr = new HashMap<>();
                        paramsCrtr.put("dgnsNo", hstryNo);
                        paramsCrtr.put("targetYear", crtrYear);
                        diagData.put("diagResult_crtr", anaZoneDgnsDtlMapper.selectDiagnosisResult(paramsCrtr));

                        Map<String, Object> paramsPredc = new HashMap<>();
                        paramsPredc.put("dgnsNo", hstryNo);
                        paramsPredc.put("targetYear", predcYear);
                        diagData.put("diagResult_predc", anaZoneDgnsDtlMapper.selectDiagnosisResult(paramsPredc));
                        
                        diagResults.add(diagData);
                    }
                }
                // [P] 시설 배치 (★병합)
                else if ("P".equals(se)) {
                    UrbMdlMstVO mdlVO = urbMdlMstMapper.selectUrbMdlMstDetail(UrbMdlMstVO.builder().mdlNo(hstryNo).build());
                    if (mdlVO != null) {
                        mergedModelList.add(mdlVO);
                    }
                }
                // [G] 녹지 (N개 허용)
                else if ("G".equals(se)) {
                    if (StringUtils.hasText(hstryNo)) {
                        Map<String, Object> greenData = new HashMap<>();
                        greenData.put("anlsNo", hstryNo); // [필수 추가] 식별자
                        greenData.put("title", itemTitle);
                        
                        UrbGrnznAnlsMstVO mstVO = UrbGrnznAnlsMstVO.builder().anlsNo(Integer.parseInt(hstryNo)).build();
                        greenData.put("greenAnlsResult", urbGrnznAnlsMapper.selectUrbGrnznAnlsMstDetail(mstVO));
                        
                        UrbGrnznAnlsDtlVO dtlVO = UrbGrnznAnlsDtlVO.builder()
                                .anlsNo(Integer.parseInt(hstryNo))
                                .includeJ("Y")
                                .build();
                        greenData.put("greenList", urbGrnznAnlsMapper.selectUrbGrnznAnlsDtlList(dtlVO));
                        
                        greenResults.add(greenData);
                    }
                }
                // [U] 지하 (★분리 - 병합하지 않음)
                else if ("U".equals(se)) {
                    UrbUdgdFcltyDtlVO udgdVO = new UrbUdgdFcltyDtlVO();
                    udgdVO.setAnlsMngNo(hstryNo); 
                    udgdVO.setRecordCountPerPage(0); // 전체 조회
                    List<UrbUdgdFcltyDtlVO> list = urbUdgdFcltyDtlMapper.selectUrbUdgdFcltyDtlList(udgdVO);
                    
                    if(list != null) {
                        Map<String, Object> underData = new HashMap<>();
                        underData.put("anlsNo", hstryNo);
                        underData.put("title", itemTitle);
                        underData.put("items", list);
                        underResults.add(underData);
                    }
                }
                // [F] 시설 분석 (★분리 - 병합하지 않음)
                else if ("F".equals(se)) {
                    UrbFcltyAnlsDtlVO dtlSearch = new UrbFcltyAnlsDtlVO();
                    dtlSearch.setFcltAnlsNo(hstryNo);
                    dtlSearch.setRecordCountPerPage(0);
                    
                    List<UrbFcltyAnlsDtlVO> list = urbFcltyAnlsMapper.selectUrbFcltyAnlsDtlList(dtlSearch);
                    
                    Map<String, Object> fcltyData = new HashMap<>();
                    fcltyData.put("anlsNo", hstryNo);
                    fcltyData.put("title", itemTitle);
                    fcltyData.put("items", list);
                    fcltyResults.add(fcltyData);
                }
                // [A] 접근도 분석 (★분리 - 병합하지 않음)
                else if ("A".equals(se)) {
                    UrbFcltyAnlsDtlVO dtlSearch = new UrbFcltyAnlsDtlVO();
                    dtlSearch.setFcltAnlsNo(hstryNo);
                    dtlSearch.setRecordCountPerPage(0);
                    
                    List<UrbFcltyAnlsDtlVO> list = urbFcltyAnlsMapper.selectUrbFcltyAnlsDtlList(dtlSearch);
                    
                    Map<String, Object> accessData = new HashMap<>();
                    accessData.put("anlsNo", hstryNo);
                    accessData.put("title", itemTitle);
                    accessData.put("items", list);
                    accessResults.add(accessData);
                }
            }
            
            // [최종] reportData 구성
            reportData.put("statsResults", statsResults);     // List
            reportData.put("diagResults", diagResults);       // List
            reportData.put("greenResults", greenResults);     // List
            reportData.put("mergedModelList", mergedModelList); // List (병합됨)
            reportData.put("underResults", underResults);     // List (분리됨)
            reportData.put("fcltyResults", fcltyResults);     // List (분리됨)
            reportData.put("accessResults", accessResults);   // List (분리됨)
            
            mstData.setReportContent(reportData);
        }
        return mstData;
    }
    
    /**
     * 보고서 생성 팝업 후보군 조회
     */
    @Override
    public Map<String, Object> selectReportCandidates(SimRptpMstVO searchVO) throws Exception {
        Map<String, Object> result = new HashMap<>();
        
        // 검색 조건 (S, D, P, G, U, FA, AA)
        String type = searchVO.getSearchCondition();
        if (type == null) type = "";

        // 1. 통계 (S)
        if ("".equals(type) || "S".equals(type)) {
            result.put("statsList", simRptpMstMapper.selectCandidateStats(searchVO));
        }
        
        // 2. 진단 (D)
        if ("".equals(type) || "D".equals(type)) {
            result.put("diagList", simRptpMstMapper.selectCandidateDiagnosis(searchVO));
        }
        
        // 3. 시설 배치 (P)
        if ("".equals(type) || "P".equals(type)) {
            result.put("modelList", simRptpMstMapper.selectCandidateModels(searchVO));
        }
        
        // 4. 녹지 (G)
        if ("".equals(type) || "G".equals(type)) {
            result.put("greenList", simRptpMstMapper.selectCandidateGreenAnls(searchVO));
        }
        
        // 5. 지하 (U)
        if ("".equals(type) || "U".equals(type)) {
            result.put("undergroundList", simRptpMstMapper.selectCandidateUndergroundAnls(searchVO));
        }
        
        // 6. 시설 분석 (FA) - [수정] main_usg_cd != 'ACEI'
        if ("".equals(type) || "F".equals(type)) {
            result.put("fcltyAnlsList", simRptpMstMapper.selectCandidateFcltyAnls(searchVO));
        }
        
        // 7. 접근도 분석 (AA) - [수정] main_usg_cd == 'ACEI'
        if ("".equals(type) || "A".equals(type)) {
            result.put("accessAnlsList", simRptpMstMapper.selectCandidateAccessAnls(searchVO));
        }
        
        return result;
    }

    @Override public List<SimRptpMstVO> selectSimRptpList(SimRptpMstVO vo) throws Exception { return simRptpMstMapper.selectSimRptpMstList(vo); }
    @Override public int selectSimRptpListCnt(SimRptpMstVO vo) throws Exception { return simRptpMstMapper.selectSimRptpMstListCnt(vo); }
    @Override public List<SimRptpMstVO> selectSimRptpRecentList(SimRptpMstVO vo) throws Exception { return simRptpMstMapper.selectSimRptpMstRecentList(vo); }
    
    @Override 
    @Transactional 
    public String insertSimRptp(SimRptpMstVO vo) throws Exception {
        if (vo.getRptpTtl() == null || vo.getRptpTtl().isEmpty()) vo.setRptpTtl("자동 생성 보고서");
        simRptpMstMapper.insertSimRptpMst(vo);
        String rptpNo = vo.getRptpNo();
        if (vo.getItemList() != null) {
            for (SimRptpItemVO item : vo.getItemList()) {
                item.setRptpNo(rptpNo);
                item.setLOGIN_USER_ID(RequestContext.getCurrentUserId());
                simRptpItemMapper.insertSimRptpItem(item);
            }
        }
        return rptpNo;
    }
    @Override @Transactional public int deleteSimRptp(SimRptpMstVO vo) throws Exception {
        SimRptpItemVO itemVO = new SimRptpItemVO();
        itemVO.setRptpNo(vo.getRptpNo());
        simRptpItemMapper.deleteSimRptpItemByMst(itemVO);
        simRptpMstMapper.deleteSimRptpMst(vo);
        return 1;
    }
}