package cokr.xit.ens.modules.common.ctgy.intgrnnoti.service.support;

import cokr.xit.ens.core.aop.EnsResponseVO;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.biztmplt.SendProcTemplate;
import cokr.xit.ens.modules.common.code.PostSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.code.TryStatCd;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.IntgrnSendDetail;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.IntgrnSendMast;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.repository.IntgrnSendDetailRepository;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.repository.IntgrnSendMastRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;

@Slf4j
@Component
@RequiredArgsConstructor
public class IntgrnNotiSender extends SendProcTemplate {

    private final IntgrnSendMastRepository intgrnSendMastRepository;
    private final IntgrnSendDetailRepository intgrnSendDetailRepository;
    private final ApplicationEventPublisher applicationEventPublisher;


    /**
     * 전송시작
     *
     * @param intSendMastId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public EnsResponseVO statBegin(Long intSendMastId) {

        EnsResponseVO respVO = null;
        try {
            if (CmmnUtil.isEmpty(intSendMastId))
                throw new EnsException(EnsErrCd.SEND410, "발송마스터ID(은)는 필수조건 입니다.");

            IntgrnSendMast sendMast = intgrnSendMastRepository.findById(intSendMastId).orElseThrow(() -> new EnsException(EnsErrCd.SEND404, String.format("일치하는 발송마스터 자료가 없습니다. [ intSendMastId %s ]", intSendMastId)));
            sendMast.setTryStatCd(TryStatCd.start);

           
            respVO = EnsResponseVO.okBuilder().resultInfo(intSendMastId).build();
        } catch (EnsException e) {
           
            respVO = EnsResponseVO.errBuilder().errCode(e.getErrCd()).errMsg(e.getMessage()).build();
        } catch (Exception e) {
           
            respVO = EnsResponseVO.errBuilder().errCode(EnsErrCd.SEND500).errMsg(e.getMessage()).build();
        }

        return respVO;
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public EnsResponseVO execute(Long intSendMastId) {

        IntgrnSendMast intgrnSendMast = null;
        List<IntgrnSendDetail> intgrnSendDetails = null;
        EnsResponseVO respVO = null;
        try {
            if (CmmnUtil.isEmpty(intSendMastId))
                throw new EnsException(EnsErrCd.SEND410, "발송마스터ID(은)는 필수조건 입니다.");

            intgrnSendMast = intgrnSendMastRepository.findById(intSendMastId).orElseThrow(() -> new EnsException(EnsErrCd.SEND404, String.format("일치하는 발송마스터 자료가 없습니다. [ intSendMastId %s ]", intSendMastId)));
            intgrnSendDetails = intgrnSendDetailRepository.findAllBySendTargetAndSendMastAndTryStatCdIn(intgrnSendMast, Arrays.asList(TryStatCd.start));
            if (intgrnSendDetails.size() < 1)   
                throw new EnsException(EnsErrCd.SEND500, "조회된 발송상세 자료가 없음.");


            PostSeCd postSeCd = null;
            final int currentTryNum = intgrnSendMast.getTrySeq() + 1;
            final boolean isReserve = currentTryNum == 1 ? true : false;   
            final TryStatCd tryStatCd = currentTryNum == 1 ? TryStatCd.sndRsrv : TryStatCd.sndRtme;
            if (currentTryNum == 1) postSeCd = intgrnSendMast.getTry1();
            else if (currentTryNum == 2) postSeCd = intgrnSendMast.getTry2();
            else if (currentTryNum == 3) postSeCd = intgrnSendMast.getTry3();
            AcceptDataFactory makerFactory = new AcceptDataMakerFactory(intgrnSendMast, intgrnSendDetails, isReserve);
           
            applicationEventPublisher.publishEvent(makerFactory.get(postSeCd));

            
            intgrnSendMast.setTrySeq(currentTryNum);
            intgrnSendMast.setTryStatCd(tryStatCd);
           
            PostSeCd finalPostSeCd = postSeCd;
            intgrnSendDetails.forEach(data -> data.setCurPostSe(finalPostSeCd));


           
            respVO = EnsResponseVO.okBuilder().build();

        } catch (EnsException e) {
           
            respVO = EnsResponseVO.errBuilder().errCode(e.getErrCd()).errMsg(e.getMessage()).build();
        } catch (Exception e) {
           
            respVO = EnsResponseVO.errBuilder().errCode(EnsErrCd.SEND500).errMsg(e.getMessage()).build();
        }


        return respVO;
    }
}
