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

import java.util.*;
import java.util.stream.*;

import org.springframework.context.*;
import org.springframework.stereotype.*;

import cokr.xit.ens.core.aop.*;
import cokr.xit.ens.core.exception.code.*;
import cokr.xit.ens.core.monitor.slack.event.*;
import cokr.xit.ens.modules.common.code.*;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.*;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.repository.*;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.service.support.*;
import cokr.xit.ens.modules.common.monitor.*;
import cokr.xit.ens.modules.kkotalk.model.*;
import cokr.xit.ens.modules.kkotalk.service.*;
import cokr.xit.ens.modules.kkotalk.service.event.*;
import lombok.*;
import lombok.extern.slf4j.*;

// FIXME: 카카오톡 신규 추가
@Slf4j
@Component
@RequiredArgsConstructor
public class AcceptByKkoTalkEventListener implements AcceptDataEventListener<AcceptDataByKkoTalk, SendDetailKkoTalkDTO> {

    private final ApplicationEventPublisher applicationEventPublisher;
    private final KkoTalkService kkoTalkService;
    private final IntgrnSendDetailRepository intgrnSendDetailRepository;


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

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


            Map<String, Object> resultInfo = (Map<String, Object>) responseVO.getResultInfo();
            Long sendMastId = (Long) resultInfo.get("sendMastId");
            List<SendDetailKkoTalkDTO> sendDetails = (List<SendDetailKkoTalkDTO>) 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()) {
                KkoTalkSendReserveEvent event = KkoTalkSendReserveEvent.builder()
                        .sendMastIds(Arrays.asList(sendMastId))
                        .build();
                applicationEventPublisher.publishEvent(event);

            } else {
                KkoTalkSendRealtimeEvent event = KkoTalkSendRealtimeEvent.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<SendDetailKkoTalkDTO> sendDetails) {

        Map<String, Long> sendDetailIdMap = sendDetails.stream()
            .map(row -> {
                Map<String, Object> m = new HashMap<>();
                m.put("key", row.getExternalId());
                m.put("value", row.getSendDetailId());
                return m;
            })
                // .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.setSendDetailIdKkoTalk(sendDetailId);
    }
}
