package kr.xit.biz.ens.service;

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

import org.slf4j.MDC;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import kr.xit.biz.common.ApiConstants;
import kr.xit.biz.common.ApiConstants.SndngSeCode;
import kr.xit.biz.ens.cmm.CmmEnsBizUtils;
import kr.xit.biz.ens.mapper.IEnsBatchMapper;
import kr.xit.biz.ens.model.EnsDTO;
import kr.xit.biz.ens.model.cmm.SndngMssageParam;
import kr.xit.core.exception.BizRuntimeException;
import kr.xit.core.service.AbstractService;
import lombok.RequiredArgsConstructor;

/**
 * <pre>
 * description : 모바일 전자고지 배치 서비스
 *               - 배치에서 호출되는 클래스로 배치 로그등 Transaction 분리 필요
 *               - 메소드 트랜잭션 Transactional(propagation = Propagation.REQUIRES_NEW)로 선언
 * packageName : kr.xit.biz.ens.service
 * fileName    : EnsBatchService
 * author      : limju
 * date        : 2023-08-31
 * ======================================================================
 * 변경일         변경자        변경 내용
 * ----------------------------------------------------------------------
 * 2023-08-31    limju       최초 생성
 *
 * </pre>
 */
@RequiredArgsConstructor
@Service
public class EnsBatchMakeService extends AbstractService implements IEnsBatchMakeService {
    private static final String SNDNG_PROCESS_STTUS = "sndngProcessSttus";
    private static final String UNITY_SNDNG_MST_ID = "unitySndngMastrId";

    private final IEnsBatchMapper mapper;

    /**
     * <pre>
     * 1. 통합 발송 생성 대상 조회
     *    - 발송처리상태가 접수(accept-ok)인 데이타
     *    - 발송처리상태가 1차, 2차 전송상태(sending1, sending2)인 데이타
     *    -> {@link IEnsBatchMapper#selectMakeTgts selectMakeTgts}
     *    - tb_ens_unity_sndng_mastr
     * @param reqDTO
     * @return Map<String, List<SndngMssageParam>> 'tty1', 'tty2', 'tty3'에 대상 put
     * </pre>
     */
    /**
     *
     * @param reqDTO
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public Map<String, List<SndngMssageParam>> findMakes(final EnsDTO.BatchEnsRequest reqDTO) {
        final Map<String, List<SndngMssageParam>> tgtMap = new HashMap<>();
        // FIXME :: 순차 발송 값 바인딩 잘못함 순차발송이 필요한 경우 수정 필요
        // final String sndngProcessSttus2 = ApiConstants.SndngProcessStatus.SENDING1.getCode();
        // final String sndngProcessSttus3 = ApiConstants.SndngProcessStatus.SENDING2.getCode();

        tgtMap.put("tty1", mapper.selectMakeTgts(reqDTO));
        //tgtMap.put("tty2", mapper.selectMakeTgts(sndngProcessSttus2));
        //tgtMap.put("tty3", mapper.selectMakeTgts(sndngProcessSttus3));
        return tgtMap;
    }

    /**
     * <pre>
     * 2차 or 3차 발송 대상이 있는지 확인하여
     * 없으면 발송마스터, 통합발송 마스터 send-ok 처리
     * 2차 or 3차 발송 대상이 있으면 true return
     * @param dto SndngMssageParam
     * @return boolean 2차 or 3차 발송 대상이 있으면 true
     * </pre>
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public boolean makeIsNext(final SndngMssageParam dto) {
        MDC.put(UNITY_SNDNG_MST_ID, dto.getUnitySndngMastrId());
        MDC.put(SNDNG_PROCESS_STTUS, "make-fail2");
        dto.setProfile(ApiConstants.IS_PROFILE_LOCAL? "local" : "prod");

        final SndngSeCode sndngSeCode =  CmmEnsBizUtils.getSndngSeCodFromTrySeq(dto);

        //try2 발송 대상이 있는지 확인
        int sendCnt = 0;
        if(SndngSeCode.KAKAO.equals(sndngSeCode)) {
            sendCnt = mapper.selectKkopaySendOkTgts(dto);
        } else {
            sendCnt = mapper.selectKkotalkSendOkTgts(dto);
        }
        //없으면 연계 발송 마스터, 통합 발송 마스터 send-ok
        if (sendCnt == 0) {
            CmmEnsBizUtils.setMappingProcessStatus(dto, dto.getNewSndngProcessSttus());
            if (mapper.updateProcessSttusCntcSndngMst(dto) != 1) {
                throw BizRuntimeException.create("[make]연계 발송 마스터 상태변경 실패");
            }

            dto.setNewSndngProcessSttus(ApiConstants.SndngProcessStatus.SEND_OK.getCode());
            if (mapper.updateProcessSttusUnitySndngMst(dto) != 1) {
                throw BizRuntimeException.create("[make]통합 발송 마스터 상태변경 실패");
            }
            return false;
        }
        //있으면 make
        dto.setSndngProcessSttus(ApiConstants.SndngProcessStatus.SENDING1.getCode());
        dto.setNewSndngProcessSttus(ApiConstants.SndngProcessStatus.MAKE_OK.getCode());
        dto.setTrySeq(2);
        dto.setSndngCo(sendCnt);
        dto.setSndngSeCode(dto.getTry2());
        return true;
    }

    /**
     * <pre>
     * make 처리
     * 1. 발송마스터 생성 : {@link IEnsBatchMapper#insertSndngMst insertSndngMst}
     *                   - tb_ens_sndng_mastr
     * 2. 문서 중개자별 발송 상세 생성 : {@link #makeEnsDetailByTry}
     *   - KAKAO - tb_ens_kakao_my_doc
     *   - E_GREEN - tb_ens_post_sndng
     *   - SMS     - tb_ens_sms_sndng
     *   - KT_BC   - tb_ens_kt_bc
     *   - PPLUS   - tb_ens_
     * 3. 연계/통합 발송마스터 상테 변경
     *   3-1. 연계 발송 마스터 상태 변경 : {@link IEnsBatchMapper#updateProcessSttusCntcSndngMst}
     *   3-2. 통합 발송 마스터 상태 변경 : {@link IEnsBatchMapper#updateProcessSttusUnitySndngMst}
     * @param dto SndngMssageParam
     * </pre>
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void make(SndngMssageParam dto) {
        // 1. master
        if (mapper.insertSndngMst(dto) != 1) {
            throw BizRuntimeException.create("[make]데이타 생성(마스터) 실패");
        }

        // 2. detail
        int insCnt = makeEnsDetailByTry(dto);
        if (insCnt != dto.getSndngCo()) {
            throw BizRuntimeException.create(
                String.format("[make]상세 데이타 생성 실패-발송건수[%d]와 생성건수[%d] 불일치", dto.getSndngCo(),
                    insCnt));
        }

        // 3. status
        CmmEnsBizUtils.setMappingProcessStatus(dto, dto.getNewSndngProcessSttus());
        if (mapper.updateProcessSttusCntcSndngMst(dto) != 1) {
            throw BizRuntimeException.create("[make]데이타 생성(발송마스터 상태변경) 실패");
        }
        dto.setNewSndngProcessSttus(ApiConstants.SndngProcessStatus.MAKE_OK.getCode());
        if (mapper.updateProcessSttusUnitySndngMst(dto) != 1) {
            throw BizRuntimeException.create("[make]데이타 생성(통합발송마스터 상태변경) 실패");
        }
    }

    //*************************************************************************
    // private method
    //*************************************************************************

    //-----------------------------------------------------------------------------------------------------------------
    // make
    //-----------------------------------------------------------------------------------------------------------------
    /**
     * <pre>
     * make 상세 데이타 생성 : 문서 중개자별 상세 데이타 생셩
     * - 최초(전송 없슴), 1차 전송, 2차 전송 데이타 대상
     * KAKAO   - {@link IEnsBatchMapper#insertKakaopay(Object) insertKakaopay}
     *         - tb_ens_kakao_my_doc
     * KT_BC, KT_GIBIS   - {@link IEnsBatchMapper#insertKtBcMastr(Object) insertKtBcMastr}
     *         - tb_ens_kt_bc_mastr, tb_ens_kt_gbs
     *         - {@link IEnsBatchMapper#insertKtBcDetail(Object)}
     *           {@link IEnsBatchMapper#insertKtGbsDetail(Object)}
     * @param dto SndngMssageParam
     * @return int
     * </pre>
     */
    private int makeEnsDetailByTry(final SndngMssageParam dto) {
        final SndngSeCode sndngSeCode = CmmEnsBizUtils.getSndngSeCodFromTrySeq(dto);

        return
            switch (sndngSeCode) {
                case KAKAO -> mapper.insertKakaopay(dto);
                case KAKAO_NEW -> mapper.insertKakaotalk(dto);
                case KT_BC -> {
                    mapper.insertKtBcMastr(dto);
                    yield mapper.insertKtBcDetail(dto);
                }
                case KT_GIBIS -> {
                    yield mapper.insertKtGbsDetail(dto);
                }
                //default -> throw BizRuntimeException.create(String.format("정의 되지 않은 문서 중개자[%s] 입니다", sndngSeCode.getCode()));
        };
    }
    //-----------------------------------------------------------------------------------------------------------------
}
