package cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service;

import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.entity.repository.BillHistRepository;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.kko.service.repair.kit.RepairKkoPayResultTransferFail;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.api.PayUseSysApi;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.repair.RepairPayResultService;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.repair.model.RepairPayRsltFwdFailSearchDTO;
import cokr.xit.ens.modules.common.domain.support.FieldError;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class KkoPayRepairService implements RepairPayResultService<RepairPayRsltFwdFailSearchDTO> {

    private final JPAQueryFactory query;
    private final PayUseSysApi payUseSysApi;
    private final BillHistRepository billHistRepository;


    @Override
    @Transactional(readOnly = true)
    public Map<String, Map<String, Object>> findTransferFailedPayResultDataList(RepairPayRsltFwdFailSearchDTO searchDTO) {
        Map<String, Map<String, Object>> mResultByOrg = new HashMap<>();
        RepairKkoPayResultTransferFail.builder()
                .query(query)
                .searchDTO(searchDTO)
                .build()
                .findDatas()
                .forEach(failData -> {
                    /**
                     * 응답데이터 구조
                     * {
                     *   "기관코드" {
                     *     "orgCd": "aaaa",
                     *     "orgNm": "sdafsf",
                     *     "billSe": {
                     *       "nvBp": [
                     *         { "billerUserKey": "aaaaaaaaaaaaa" },
                     *         { "billerUserKey": "bbbbbbbbbbbbb" }
                     *       ],
                     *       "kkoBp": [
                     *         { "billerUserKey": "fffffffffffff" }
                     *       ]
                     *     }
                     *   }
                     * }
                     */
                    Map<String, Object> mOrg = mResultByOrg.get(failData.getOrgCd());
                    if (mOrg == null) {
                        mOrg = new HashMap<>();
                        mOrg.put("orgCd", failData.getOrgCd());
                        mOrg.put("orgNm", failData.getOrgNm());
                        Map<String, String> data = new HashMap<>();
                        data.put("billerUserKey", failData.getBillerUserKey());
                        List<Map<String, String>> datas = new ArrayList<>();
                        datas.add(data);
                        Map<String, Object> billSe = new HashMap<>();
                        billSe.put(failData.getBillSe().getCode(), datas);
                        mOrg.put("billSe", billSe);
                        mResultByOrg.put(failData.getOrgCd(), mOrg);
                    } else {
                        Map<String, Object> billSe = (Map<String, Object>) mOrg.get("billSe");
                        List<Map<String, String>> datas = (List<Map<String, String>>) billSe.getOrDefault(failData.getBillSe().getCode(), new ArrayList<>());
                        Map<String, String> data = new HashMap<>();
                        data.put("billerUserKey", failData.getBillerUserKey());
                        datas.add(data);
                        billSe.put(failData.getBillSe().getCode(), datas);
                    }
                });
        return mResultByOrg;
    }

    @Override
    public Map<String, Map<String, Object>> sendTransferFailedPayResultDataList(RepairPayRsltFwdFailSearchDTO searchDTO) {
        Map<String, Map<String, Object>> mResultByOrg = new HashMap<>();
        RepairKkoPayResultTransferFail.builder()
                .query(query)
                .searchDTO(searchDTO)
                .build()
                .transferData(payUseSysApi, billHistRepository)
                .forEach(billHist -> {
                    /**
                     * 응답데이터 구조
                     * {
                     *   "기관코드" {
                     *     "orgCd": "aaaa",
                     *     "orgNm": "sdafsf",
                     *     "billSe": {
                     *       "nvBp": [
                     *         { "billerUserKey": "aaaaaaaaaaaaa", "code": "OK", "message": "성공" },
                     *         { "billerUserKey": "bbbbbbbbbbbbb", "code": "OK", "message": "성공" }
                     *       ],
                     *       "kkoBp": [
                     *         { "billerUserKey": "fffffffffffff", "code": "FAILED_SAVE_PAYRSLT", "message": "납부(결제)결과 저장 실패" }
                     *       ]
                     *     }
                     *   }
                     * }
                     */
                    Map<String, Object> mOrg = mResultByOrg.get(billHist.getOrgMng().getOrgCd());
                    FieldError error = billHist.getError() == null ? FieldError.initBuilder().errorCode(EnsErrCd.OK.getCode()).errorMessage(EnsErrCd.OK.getCodeNm()).build() : billHist.getError();
                    if (mOrg == null) {

                        mOrg = new HashMap<>();
                        mOrg.put("orgCd", billHist.getOrgMng().getOrgCd());
                        mOrg.put("orgNm", billHist.getOrgMng().getOrgNm());
                        Map<String, String> data = new HashMap<>();
                        data.put("billerUserKey", billHist.getLinkedUuid());
                        data.put("code", error.getErrorCode());
                        data.put("message", error.getErrorMessage());
                        List<Map<String, String>> datas = new ArrayList<>();
                        datas.add(data);
                        Map<String, Object> billSe = new HashMap<>();
                        billSe.put(billHist.getBillSe().getCode(), datas);
                        mOrg.put("billSe", billSe);
                        mResultByOrg.put(billHist.getOrgMng().getOrgCd(), mOrg);
                    } else {
                        Map<String, Object> billSe = (Map<String, Object>) mOrg.get("billSe");
                        List<Map<String, String>> datas = (List<Map<String, String>>) billSe.getOrDefault(billHist.getBillSe().getCode(), new ArrayList<>());
                        Map<String, String> data = new HashMap<>();
                        data.put("billerUserKey", billHist.getLinkedUuid());
                        data.put("code", error.getErrorCode());
                        data.put("message", error.getErrorMessage());
                        datas.add(data);
                        billSe.put(billHist.getBillSe().getCode(), datas);
                    }
                });


        return mResultByOrg;
    }
}
