package incheon.ags.ias.clct.service.impl;

import incheon.ags.ias.clct.mapper.ClctIntgHstryMapper;
import incheon.ags.ias.clct.service.ClctIntgHstryService;
import incheon.ags.ias.clct.vo.ClctIntgHstryVO;
import incheon.com.cmm.context.RequestContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;

@Slf4j
@Service("clctIntgHstryService")
@RequiredArgsConstructor
public class ClctIntgHstryServiceImpl extends EgovAbstractServiceImpl implements ClctIntgHstryService {

    private final ClctIntgHstryMapper clctIntgHstryMapper;

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void logCollectionStart(String excnId, Long refHstryId, String jobId, String jobNm,
                                   String dataSourceNm, String description) {
        log.info("▶ logCollectionStart 진입: excnId={}, refHstryId={}, jobId={}, jobNm={}", excnId, refHstryId, jobId, jobNm);

        LocalDateTime excnDt = LocalDateTime.now();

        ClctIntgHstryVO clctIntgHstry = new ClctIntgHstryVO();
        clctIntgHstry.setRefHstryId(refHstryId);
        clctIntgHstry.setJobId(jobId);
        clctIntgHstry.setJobNm(jobNm);
        clctIntgHstry.setDataSourceNm(dataSourceNm);
        clctIntgHstry.setExcnStcd(ClctIntgHstryVO.ExcnStcd.READY.getCode());
        clctIntgHstry.setExcnDt(excnDt);
        clctIntgHstry.setExcnId(excnId);
        clctIntgHstry.setExcnGroupNm(description);
        clctIntgHstry.setPrcsDataNocs(0);
        clctIntgHstry.setScsNocs(0);
        clctIntgHstry.setFailNocs(0);
        clctIntgHstry.setLOGIN_USER_ID(RequestContext.getCurrentUserId());

        try {
            clctIntgHstryMapper.insertClctIntgHstry(clctIntgHstry);
            log.info("===== {} 수집 시작 이력 기록 완료 (실행ID: {}, 참조이력ID: {}) =====", jobNm, excnId, refHstryId);
        } catch (Exception e) {
            log.error("수집 시작 이력 기록 실패: {}", jobNm, e);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void logCollectionSuccess(String excnId, Integer processedCount, Integer successCount) {
        try {
            ClctIntgHstryVO existingHstry = clctIntgHstryMapper.selectClctIntgHstryByExcnId(excnId);
            if (existingHstry == null) {
                log.warn("수집 이력을 찾을 수 없습니다. 실행ID: {}", excnId);
                return;
            }

            LocalDateTime cmptnDt = LocalDateTime.now();
            Long prcsHr = Duration.between(existingHstry.getExcnDt(), cmptnDt).toMillis();

            ClctIntgHstryVO clctIntgHstry = new ClctIntgHstryVO();
            clctIntgHstry.setClctHstrySn(existingHstry.getClctHstrySn());
            clctIntgHstry.setExcnStcd(ClctIntgHstryVO.ExcnStcd.SUCCESS.getCode());
            clctIntgHstry.setCmptnDt(cmptnDt);
            clctIntgHstry.setPrcsHr(prcsHr);
            clctIntgHstry.setPrcsDataNocs(processedCount);
            clctIntgHstry.setScsNocs(successCount);
            clctIntgHstry.setFailNocs(processedCount != null && successCount != null ?
                    processedCount - successCount : 0);
            clctIntgHstry.setLOGIN_USER_ID(RequestContext.getCurrentUserId());

            clctIntgHstryMapper.updateClctIntgHstry(clctIntgHstry);
            log.info("===== {} 수집 성공 이력 기록 완료 (실행ID: {}, 처리시간: {}ms) =====",
                    existingHstry.getJobNm(), excnId, prcsHr);

        } catch (Exception e) {
            log.error("수집 성공 이력 기록 실패. 실행ID: {}", excnId, e);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void logCollectionFailure(String excnId, Exception error, Integer processedCount) {
        try {
            ClctIntgHstryVO existingHstry = clctIntgHstryMapper.selectClctIntgHstryByExcnId(excnId);
            if (existingHstry == null) {
                log.warn("수집 이력을 찾을 수 없습니다. 실행ID: {}", excnId);
                return;
            }

            LocalDateTime cmptnDt = LocalDateTime.now();
            Long prcsHr = Duration.between(existingHstry.getExcnDt(), cmptnDt).toMillis();

            ClctIntgHstryVO clctIntgHstry = new ClctIntgHstryVO();
            clctIntgHstry.setClctHstrySn(existingHstry.getClctHstrySn());
            clctIntgHstry.setExcnStcd(ClctIntgHstryVO.ExcnStcd.FAIL.getCode());
            clctIntgHstry.setCmptnDt(cmptnDt);
            clctIntgHstry.setPrcsHr(prcsHr);
            clctIntgHstry.setPrcsDataNocs(processedCount);
            clctIntgHstry.setScsNocs(0);
            clctIntgHstry.setFailNocs(processedCount != null ? processedCount : 0);
            clctIntgHstry.setLOGIN_USER_ID(RequestContext.getCurrentUserId());

            clctIntgHstryMapper.updateClctIntgHstry(clctIntgHstry);
            log.error("===== {} 수집 실패 이력 기록 완료 (실행ID: {}, 처리시간: {}ms) =====",
                    existingHstry.getJobNm(), excnId, prcsHr);

        } catch (Exception e) {
            log.error("수집 실패 이력 기록 실패. 실행ID: {}", excnId, e);
        }
    }
}
