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

import cokr.xit.ens.core.aop.EnsResponseVO;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.monitor.slack.event.MonitorEvent;
import cokr.xit.ens.modules.common.code.PostSeCd;
import cokr.xit.ens.modules.common.code.StatCd;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.IntgrnSendDetail;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.repository.IntgrnSendDetailRepository;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.service.support.AcceptDataEventListener;
import cokr.xit.ens.modules.common.monitor.MessageByPhase;
import cokr.xit.ens.modules.kkomydoc.domain.SendDetailKkoMydoc;
import cokr.xit.ens.modules.kkomydoc.service.KkoMydocService;
import cokr.xit.ens.modules.kkomydoc.service.event.KkoMydocSendRealtimeEvent;
import cokr.xit.ens.modules.kkomydoc.service.event.KkoMydocSendReserveEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
@RequiredArgsConstructor
public class AcceptByKkoMydocEventListener implements AcceptDataEventListener<AcceptDataByKkoMydoc, SendDetailKkoMydoc> {

    private final ApplicationEventPublisher applicationEventPublisher;
    private final KkoMydocService kkoMydocService;
    private final IntgrnSendDetailRepository intgrnSendDetailRepository;


    @Override
    public void accept(AcceptDataByKkoMydoc ev) {
        final PostSeCd POST_SE_CD = PostSeCd.kkoMydoc;
        EnsResponseVO responseVO = null;
        try {

            responseVO = kkoMydocService.accept(ev.createReqDto());


            Map<String, Object> resultInfo = (Map<String, Object>) responseVO.getResultInfo();
            Long sendMastId = (Long) resultInfo.get("sendMastId");
            List<SendDetailKkoMydoc> sendDetails = (List<SendDetailKkoMydoc>) resultInfo.get("sendDetails");
            if (EnsErrCd.OK.equals(responseVO.getErrCode())) {
                Map<String, Long> sendDetailIdMap = convertSendDetailIdMap(sendDetails);
                this.acceptSuccess(ev.getIntgrnSendDetails(), POST_SE_CD, sendDetailIdMap);
                intgrnSendDetailRepository.saveAll(ev.getIntgrnSendDetails());
            } else {
                this.acceptFail(ev.getIntgrnSendDetails(), POST_SE_CD, responseVO.getErrCode(), String.format("%s %s", responseVO.getErrMsg(), responseVO.getResultInfo().toString()));
                intgrnSendDetailRepository.saveAll(ev.getIntgrnSendDetails());
                return;
            }


            if (ev.IsReserveSend()) {
                KkoMydocSendReserveEvent event = KkoMydocSendReserveEvent.builder()
                        .sendMastIds(Arrays.asList(sendMastId))
                        .build();
                applicationEventPublisher.publishEvent(event);

            } else {
                KkoMydocSendRealtimeEvent event = KkoMydocSendRealtimeEvent.builder()
                        .sendMastIds(Arrays.asList(sendMastId))
//                    .callback(() -> this.fetch(sendMastId, ev.getSendDetails()))
                        .build();
                applicationEventPublisher.publishEvent(event);
            }
        } catch (Exception e) {
            this.acceptFail(ev.getIntgrnSendDetails(), POST_SE_CD, EnsErrCd.ACPT999, e.getMessage());
            intgrnSendDetailRepository.saveAll(ev.getIntgrnSendDetails());
            responseVO = EnsResponseVO.errBuilder().errCode(EnsErrCd.ERR999).errMsg(e.getMessage()).build();
        } finally {
            if (!EnsErrCd.OK.equals(responseVO.getErrCode())) {
                String message = createFailMessage(ev.getIntgrnSendDetails().get(0).getIntgrnSendMast().getIntSendMastId(), POST_SE_CD, responseVO);
                applicationEventPublisher.publishEvent(MonitorEvent.builder()
                        .message(MessageByPhase.builder()
                                .oClass(getClass().getSimpleName() + "." + new Throwable().getStackTrace()[0].getMethodName())
                                .postSeCd(PostSeCd.intgrnNoti)
                                .statCd(StatCd.sendfail)
                                .errCd(responseVO.getErrCode())
                                .message(message)
                                .build())
                        .build());
            }
        }
    }

    @Override
    public Map<String, Long> convertSendDetailIdMap(List<SendDetailKkoMydoc> sendDetails) {

        Map<String, Long> sendDetailIdMap = sendDetails.stream()
                .map(row -> {
                    Map<String, Object> m = new HashMap<>();
                    m.put("key", row.getPropExternalDocumentUuid());
                    m.put("value", row.getSendDetailId());
                    return m;
                })
                .collect(Collectors.toMap(m -> String.valueOf(m.get("key")), m -> (Long) m.get("value"), (k1, k2) -> k1));

        return sendDetailIdMap;
    }

    @Override
    public void setSendDetailId(IntgrnSendDetail intgrnSendDetail, Long sendDetailId) {
        intgrnSendDetail.setSendDetailIdKkoMd(sendDetailId);
    }
}
