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

import incheon.ags.ias.clct.mapper.ClctHstryMapper;
import incheon.ags.ias.clct.service.ClctHstryService;
import incheon.ags.ias.clct.vo.ClctHstryVO;
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("clctHstryService")
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ClctHstryServiceImpl extends EgovAbstractServiceImpl implements ClctHstryService {

    private final ClctHstryMapper clctHstryMapper;

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Long registerHistoryStart(String excnId, String jobNm, String jobExpln) {
        try {
            ClctHstryVO clctHstry = new ClctHstryVO();
            clctHstry.setExcnId(excnId);
            clctHstry.setJobNm(jobNm);
            clctHstry.setJobExpln(jobExpln);
            clctHstry.setJobStcd("READY");
            clctHstry.setBgngDt(LocalDateTime.now());
            clctHstry.setExcnStcd(ClctHstryVO.ExcnStcd.READY.getCode());
            clctHstry.setPrcsNocs(0);
            clctHstry.setScsNocs(0);
            clctHstry.setFailNocs(0);
            clctHstry.setLOGIN_USER_ID(RequestContext.getCurrentUserId());

            clctHstryMapper.insertClctHstry(clctHstry);

            log.info("""
                    수집 이력 시작 기록 완료
                    - 이력 일련번호: {}
                    - 실행 ID: {}
                    - 작업명: {}
                    """,
                    clctHstry.getClctHstrySn(),
                    excnId,
                    jobNm
            );

            return clctHstry.getClctHstrySn();

        } catch (Exception e) {
            log.error("수집 이력 시작 기록 실패: excnId={}, jobNm={}", excnId, jobNm, e);
            throw new RuntimeException("수집 이력 시작 기록 실패: " + e.getMessage(), e);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public boolean markHistoryAsCompleted(String excnId, Integer processedCount,
                                           Integer successCount, String logMsg) {
        try {
            ClctHstryVO existingHstry = clctHstryMapper.selectClctHstryByExcnId(excnId);
            if (existingHstry == null) {
                log.warn("존재하지 않는 수집 이력: excnId={}", excnId);
                return false;
            }

            LocalDateTime endDt = LocalDateTime.now();
            Long prcsHr = Duration.between(existingHstry.getBgngDt(), endDt).toMillis();

            ClctHstryVO clctHstry = new ClctHstryVO();
            clctHstry.setClctHstrySn(existingHstry.getClctHstrySn());
            clctHstry.setJobStcd("SUCCESS");
            clctHstry.setEndDt(endDt);
            clctHstry.setPrcsHr(prcsHr);
            clctHstry.setExcnStcd(ClctHstryVO.ExcnStcd.SUCCESS.getCode());
            clctHstry.setPrcsNocs(processedCount);
            clctHstry.setScsNocs(successCount);
            clctHstry.setFailNocs(processedCount != null && successCount != null ?
                    processedCount - successCount : 0);
            clctHstry.setLogMsg(logMsg);
            clctHstry.setLOGIN_USER_ID(RequestContext.getCurrentUserId());

            clctHstryMapper.updateClctHstry(clctHstry);

            log.info("수집 이력 완료 처리 완료: 이력 일련번호 {}, 처리시간 {}ms",
                    existingHstry.getClctHstrySn(), prcsHr);
            return true;

        } catch (Exception e) {
            log.error("수집 이력 완료 처리 실패: excnId={}", excnId, e);
            return false;
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public boolean markHistoryAsFailed(String excnId, Integer processedCount, String errorMessage) {
        try {
            ClctHstryVO existingHstry = clctHstryMapper.selectClctHstryByExcnId(excnId);
            if (existingHstry == null) {
                log.warn("존재하지 않는 수집 이력: excnId={}", excnId);
                return false;
            }

            LocalDateTime endDt = LocalDateTime.now();
            Long prcsHr = Duration.between(existingHstry.getBgngDt(), endDt).toMillis();

            ClctHstryVO clctHstry = new ClctHstryVO();
            clctHstry.setClctHstrySn(existingHstry.getClctHstrySn());
            clctHstry.setJobStcd("FAIL");
            clctHstry.setEndDt(endDt);
            clctHstry.setPrcsHr(prcsHr);
            clctHstry.setExcnStcd(ClctHstryVO.ExcnStcd.FAIL.getCode());
            clctHstry.setPrcsNocs(processedCount != null ? processedCount : 0);
            clctHstry.setScsNocs(0);
            clctHstry.setFailNocs(processedCount != null ? processedCount : 0);
            clctHstry.setErrMsg(errorMessage);
            clctHstry.setLOGIN_USER_ID(RequestContext.getCurrentUserId());

            clctHstryMapper.updateClctHstry(clctHstry);

            log.warn("수집 이력 실패 처리 완료: 이력 일련번호 {}, 처리시간 {}ms, 에러: {}",
                    existingHstry.getClctHstrySn(), prcsHr, errorMessage);
            return true;

        } catch (Exception e) {
            log.error("수집 이력 실패 처리 실패: excnId={}", excnId, e);
            return false;
        }
    }
}
