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

import java.math.BigDecimal;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import incheon.ags.dss.green.service.UrbGrnznAnlsService;
import incheon.ags.dss.green.mapper.UrbGrnznAnlsMapper;
import incheon.ags.dss.green.vo.UrbGrnznAnlsMstVO;
import incheon.com.cmm.context.RequestContext;
import incheon.ags.dss.green.vo.UrbGrnznAnlsDtlVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Service("urbGrnznAnlsService")
@RequiredArgsConstructor
@Slf4j
public class UrbGrnznAnlsServiceImpl implements UrbGrnznAnlsService {

    private final UrbGrnznAnlsMapper mapper;

    @Override
    @Transactional
    public void runGreenAnalysis(UrbGrnznAnlsMstVO vo) throws Exception {
        log.info("Starting Green Zone Analysis for Zone: {}", vo.getTareNo());
        
        // 1. 기존 분석 데이터 존재 여부 확인
        Integer existAnlsNo = mapper.selectAnlsNoByTareNo(vo.getTareNo());

        if (existAnlsNo != null) {
        	// ====================================================
            // Case A: 데이터 있음 -> 파라미터 갱신 및 재계산 (상세 데이터 유지)
            // ====================================================
            log.info("Analysis exists (AnlsNo: {}). Updating parameters only.", existAnlsNo);
            
            vo.setAnlsNo(existAnlsNo);
            // 2-1. 입력받은 파라미터(인구수, 비율 등) 업데이트
            mapper.updateUrbGrnznAnlsMstParams(vo);
        }else {
        	// ====================================================
            // Case B: 데이터 없음 -> 신규 생성 및 초기 적재
            // ====================================================
            log.info("No analysis found. Creating new analysis data.");

            // 2-1. Master 등록
            mapper.insertUrbGrnznAnlsMst(vo);
            Integer anlsNo = vo.getAnlsNo();

            // 2-2. Detail 자동 적재
            UrbGrnznAnlsDtlVO dtlVO = new UrbGrnznAnlsDtlVO();
            dtlVO.setAnlsNo(anlsNo);
            dtlVO.setTareNo(vo.getTareNo());
            dtlVO.setLOGIN_USER_ID(vo.getLOGIN_USER_ID());
            mapper.insertUrbGrnznAnlsDtlFromZone(dtlVO);
            
            // 후속 처리를 위해 VO에 키 세팅
            vo.setAnlsNo(anlsNo);
        }

        // 3. [Step 3] 공통: 결과(면적) 계산 및 업데이트
        // (Case A는 변경된 파라미터 기반으로, Case B는 신규 데이터를 기반으로 계산)
        mapper.updateUrbGrnznAnlsResult(vo);
        
        log.info("Green Zone Analysis Completed. AnlsNo: {}", vo.getAnlsNo());
    }

    @Override
    public UrbGrnznAnlsMstVO selectGreenAnalysisResult(int zoneNo) throws Exception {
        UrbGrnznAnlsMstVO vo = new UrbGrnznAnlsMstVO();
        vo.setTareNo(zoneNo);
        // Master 조회 시 AnlsNo를 모르므로, selectAnlsNoByTareNo를 쓰거나 
        // Mapper XML의 selectUrbGrnznAnlsMstDetail 쿼리가 tareNo를 지원하도록 수정 필요할 수 있음.
        // 현재 로직상 anlsNo를 먼저 찾아야 함.
        Integer anlsNo = mapper.selectAnlsNoByTareNo(zoneNo);
        if (anlsNo == null) return null;
        
        vo.setAnlsNo(anlsNo);
        return mapper.selectUrbGrnznAnlsMstDetail(vo);
    }

    @Override
    public List<UrbGrnznAnlsDtlVO> selectGreenZoneList(Integer anlsNo) throws Exception {
        UrbGrnznAnlsDtlVO vo = new UrbGrnznAnlsDtlVO();
        vo.setAnlsNo(anlsNo);
        return mapper.selectUrbGrnznAnlsDtlList(vo);
    }

    @Override
    @Transactional
    public void saveGreenZoneDetails(int zoneNo, List<UrbGrnznAnlsDtlVO> list) throws Exception {
        
        // 1. 해당 구역(zoneNo)의 분석 마스터(anlsNo)가 존재하는지 확인
    	Integer anlsNo = mapper.selectAnlsNoByTareNo(zoneNo);

        // 2. 마스터가 없으면 -> [초기화 로직] 실행
        if (anlsNo == null) {
            log.info("분석 마스터가 존재하지 않아 초기화를 진행합니다. ZoneNo: {}", zoneNo);
            
            // 2-1. Master 생성 (기본값 설정)
            UrbGrnznAnlsMstVO initVO = new UrbGrnznAnlsMstVO();
            initVO.setTareNo(zoneNo);
            initVO.setLOGIN_USER_ID(RequestContext.getCurrentUserId());
            
            // 초기값 세팅 (NULL 방지 정책)
            initVO.setTarePpltnCnt(BigDecimal.ZERO); 
            initVO.setMinGreensRt(BigDecimal.ZERO);
            initVO.setPsnbyGreensArea(BigDecimal.ZERO);
            
            // 통합된 메서드 호출
            mapper.insertUrbGrnznAnlsMst(initVO); 
            anlsNo = initVO.getAnlsNo();

            // 2-2. Detail 자동 적재 (지적도 기반 초기 데이터)
            UrbGrnznAnlsDtlVO initDtlVO = new UrbGrnznAnlsDtlVO();
            initDtlVO.setAnlsNo(anlsNo);
            initDtlVO.setTareNo(zoneNo);
            initDtlVO.setLOGIN_USER_ID(RequestContext.getCurrentUserId());
            
            // 통합된 메서드 호출
            mapper.insertUrbGrnznAnlsDtlFromZone(initDtlVO);
        }else {
        	// 마스터가 이미 존재한다면, 기존의 수동 편집 데이터(D, S)를 먼저 삭제
            mapper.deleteUrbGrnznAnlsDtlManual(anlsNo);
//        	mapper.deleteUrbGrnznAnlsDtlByMst(anlsNo);// 전체삭제
        	
            // 2-2. 초기 데이터(I)는 일단 모두 'J'(논리삭제)로 변경
            // -> 리스트에서 빠진 애들은 이 상태(J)로 남게 됨
            mapper.updateUrbGrnznAnlsDtlStatusToJ(anlsNo);
        	
        }

        // 3. 사용자가 편집한 내용(추가/삭제 등) 저장
        if (list != null && !list.isEmpty()) {
            for (UrbGrnznAnlsDtlVO vo : list) {
                vo.setAnlsNo(anlsNo); // 찾거나 생성한 번호 주입
                vo.setLOGIN_USER_ID(RequestContext.getCurrentUserId());
                
                if ("I".equals(vo.getRegType())) {
                    // [Case I] 초기 데이터인 경우 -> UPDATE (부활)
                    // 프론트엔드에서 반드시 PK(greensSpceNo)를 보내줘야 함
                    if (vo.getGreensSpceNo() != null) {
                        mapper.updateUrbGrnznAnlsDtlStatusToI(vo);
                    } else {
                        log.warn("I 타입 데이터에 PK(greensSpceNo)가 없어 업데이트 실패: {}", vo);
                    }
                } else {
                    // [Case S, D] 수동 데이터인 경우 -> INSERT (신규 등록)
                    // 위에서 deleteManual로 지웠으므로 Insert 하면 됨
                    mapper.insertUrbGrnznAnlsDtl(vo);
                }
            }
        }

        // 4. 최종 면적 재계산 (필수)
        UrbGrnznAnlsMstVO calcVO = new UrbGrnznAnlsMstVO();
        calcVO.setAnlsNo(anlsNo);
        mapper.updateUrbGrnznAnlsResult(calcVO);
    }
}