package incheon.ags.ias.rst.volu.service.impl;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.transaction.Transactional;

import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;

import incheon.ags.ias.rst.volu.mapper.AgsRstVoluMapper;
import incheon.ags.ias.rst.volu.service.AgsRstVoluService;
import incheon.ags.ias.rst.volu.vo.AgsRstVoluVO;
import lombok.extern.slf4j.Slf4j;

/**
 * @ClassName : AgsRstVoluServiceImpl.java
 * @Description : 부동산통계 전월세 거래량 관리 서비스 구현체
 * @author : 이주훈
 * @since : 2025.10.27
 * @version : 1.0
 */
@Slf4j
@Service
public class AgsRstVoluServiceImpl  implements AgsRstVoluService {
	
    private final AgsRstVoluMapper agsRstVoluMapper;
    public AgsRstVoluServiceImpl(AgsRstVoluMapper agsRstVoluMapper) {
        this.agsRstVoluMapper = agsRstVoluMapper;
    }
    
    @Override
    public List<Map<String, Object>> getCrtrYmRange() {
        return agsRstVoluMapper.getCrtrYmRange();
    }
    
    @Override
    public List<String> getMonthsByYear(String year) {
        return agsRstVoluMapper.getMonthsByYear(year);
    }
    
    @Override
    public List<Map<String, Object>> selectCrtrYmSummary(Map<String, Object> param) {
        return agsRstVoluMapper.selectCrtrYmSummary(param);
    }

    @Override
    public int selectCrtrYmSummaryCnt(Map<String, Object> param) {
        return agsRstVoluMapper.selectCrtrYmSummaryCnt(param);
    }

    @Override
    public List<Map<String, Object>> selectVoluMatrix(String crtrYm) {
        List<Map<String, Object>> voluMatrix = agsRstVoluMapper.selectVoluMatrix(crtrYm);
        for (Map<String, Object> row : voluMatrix) {
            System.out.println(row);
        }
        return voluMatrix;
    }
    
    private static final Map<String, String> SGG_MAP = Map.ofEntries(
    	    Map.entry("110", "중구"),
    	    Map.entry("140", "동구"),
    	    Map.entry("177", "미추홀구"),
    	    Map.entry("185", "연수구"),
    	    Map.entry("200", "남동구"),
    	    Map.entry("237", "부평구"),
    	    Map.entry("245", "계양구"),
    	    Map.entry("260", "서구"),
    	    Map.entry("710", "강화군"),
    	    Map.entry("720", "옹진군")
    	);

    	private static final Map<String, String> HS_MAP = Map.ofEntries(
    	    Map.entry("1", "아파트"),
    	    Map.entry("2", "연립주택"),
    	    Map.entry("3", "다세대주택"),
    	    Map.entry("4", "단독주택"),
    	    Map.entry("5", "다가구주택")
    	);


    @Override
    @Transactional
    public Map<String, Object> processVoluBulk(
            String mode,
            String crtrYm,
            String[] sggs, String[] hsTypes, String[] nocs) {

        Map<String, Object> result = new HashMap<>();
        int affected = 0; // 실제로 DB에 등록/수정된 건수

        try {
            // 입력된 항목만 처리
            for (int i = 0; i < sggs.length; i++) {
                String sgg = sggs[i];
                String hsType = hsTypes[i];
                String ym = crtrYm;
                // 인천광역시 전체는 입력 배열에서 무시
                if (sgg.equals("000")) {
                    continue; 
                }
                // 거래 건수가 비어있는 경우
                if (nocs[i] == null || nocs[i].trim().isEmpty()) {
                    boolean exists = agsRstVoluMapper.existsVolu(crtrYm, sgg, hsType) > 0;
                    if (exists) {
                    	// 데이터가 존재하면 거래 건수를 null로 업데이트
                        Map<String, Object> param = new HashMap<>();
                        param.put("crtrYm", crtrYm);
                        param.put("sttySggCd", sgg);
                        param.put("hsTypeSeCd", hsType);
                        param.put("dlngNocs", null);
                        agsRstVoluMapper.updateVoluBulk(param);
                    }
                    continue;
                }
                
                // 거래 건수를 정수로 변환
                int nocsVal;
                try {
                    nocsVal = Integer.parseInt(nocs[i].trim());
                } catch (NumberFormatException e) {
                    continue; // 숫자 변환 실패 시 건너뛰기
                }
                
                // 데이터 존재 여부 확인
                boolean exists = agsRstVoluMapper.existsVolu(ym, sgg, hsType) > 0;

                // 등록 or 수정 분기 처리
                if (mode.equals("insert")) {
                    if (exists) {
                    	// 등록 모드인데 이미 데이터가 존재하는 경우 메시지와 함께 즉시 반환
                    	String sggNm = SGG_MAP.getOrDefault(sgg, sgg);
                        String hsNm = HS_MAP.getOrDefault(hsType, hsType);
                        result.put("success", false);
                        result.put("msg", String.format("[%s] %s(%s)는 이미 등록되어 있습니다.", ym, sggNm, hsNm));
                        return result;
                    }
                    // 데이터가 없으면 신규 등록
                    agsRstVoluMapper.insertVolu(new AgsRstVoluVO(ym, sgg, hsType, nocsVal));
                } else if (mode.equals("update")) {
                    if (!exists) {
                    	// 수정 모드인데 데이터가 없으면 신규 등록
                        agsRstVoluMapper.insertVolu(new AgsRstVoluVO(ym, sgg, hsType, nocsVal));
                    } else {
                    	// 데이터가 있으면 거래 건수 수정
                        Map<String, Object> param = new HashMap<>();
                        param.put("crtrYm", ym);
                        param.put("sttySggCd", sgg);
                        param.put("hsTypeSeCd", hsType);
                        param.put("dlngNocs", nocsVal);
                        agsRstVoluMapper.updateVoluBulk(param);
                    }
                }

                affected++;

            } // 루프 종료
            
            // 군·구별 주택유형 합계(0) 생성
            Set<String> targetSggSet = new HashSet<>();

            for (String sgg : sggs) {
                if (!"000".equals(sgg)) {
                    targetSggSet.add(sgg);
                }
            }

            for (String sgg : targetSggSet) {

                // 기존 군구 합계(0) 삭제
                agsRstVoluMapper.deleteVoluBySggAndHsType(crtrYm, sgg, "0");

                // 군구별 합계 계산
                int sggTotal = agsRstVoluMapper.selectSggTotalSum(crtrYm, sgg);

                // 합계 insert
                agsRstVoluMapper.insertVolu(new AgsRstVoluVO(crtrYm, sgg, "0", sggTotal));
            }

            // 인천광역시(000) 집계 재생성
        	if (affected > 0) {
	
				 // 기존 인천광역시(000) 데이터 전부 삭제
				 agsRstVoluMapper.deleteVoluBySgg(crtrYm, "000");
				
				 // 주택유형별(1~5) 집계
				 List<Map<String, Object>> ctpvTypeSums = agsRstVoluMapper.selectCtpvHsTypeSum(crtrYm);
				
				 int ctpvTotal = 0;
				
				 for (Map<String, Object> row : ctpvTypeSums) {
				     String hsType = row.get("hsTypeSeCd").toString();
				     int total = ((Number) row.get("total")).intValue();
				     ctpvTotal += total;
				
				     agsRstVoluMapper.insertVolu(new AgsRstVoluVO(crtrYm, "000", hsType, total));
				 }
				
				 // 전체 합계 (0)
				 agsRstVoluMapper.insertVolu(new AgsRstVoluVO(crtrYm, "000", "0", ctpvTotal));
	         }

            result.put("success", true);
            result.put("msg", "총 " + affected + "건 처리 완료");

        } catch (DataAccessException e) {
            log.error("부동산 전월세 거래량 일괄 처리 중 DB 예외 발생 (mode={})", mode);
            result.put("success", false);
            result.put("msg", mode.equals("insert") ? "데이터베이스 등록 중 오류가 발생했습니다." : "데이터베이스 수정 중 오류가 발생했습니다.");
        } catch (NullPointerException e) {
            log.error("부동산 전월세 거래량 일괄 처리 중 필수값 누락 예외 발생");
            result.put("success", false);
            result.put("msg", "처리 데이터가 유효하지 않습니다.");
        }

        return result;
    }

    @Override
    public void deleteVolu(String crtrYm) {
    	try {
            agsRstVoluMapper.deleteVolu(crtrYm);
        } catch (DataAccessException e) {
            log.error("부동산 전월세 거래량 삭제 중 DB 예외 발생 (crtrYm={})", crtrYm);
            throw e; 
        }
    }
    
}