package com.its.op.dao.mapper.its.link;

import com.its.op.dao.mapper.BatchDaoService;
import com.its.op.dto.its.link.LinkParaClctSystDto;
import com.its.op.dto.its.link.LinkParaDetlDto;
import com.its.op.dto.its.link.LinkParaStupDto;
import com.its.op.dto.its.link.LinkPrcsParaDto;
import com.its.op.entity.its.link.TbLink;
import com.its.utils.Elapsed;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Repository;

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

@Slf4j
@Repository
public class LinkPrcsParaDao extends BatchDaoService {

    public LinkPrcsParaDao(SqlSessionFactory sqlSessionFactory) {
        super(sqlSessionFactory);
        this.serviceName = "LinkPrcsParaDao";
        this.mapperName  = "mapper.LinkPrcsParaMapper.";
    }

    public LinkPrcsParaDto.LinkPrcsParaUpdateReq mergeAll(LinkPrcsParaDto.LinkPrcsParaUpdateReq req, List<TbLink> links) {

        log.info("{}.mergeAll: START.", this.serviceName);
        Elapsed elapsed = new Elapsed();
        int total = 0;
        SqlSession sqlSession = null;
        try {
            sqlSession = this.sqlSessionFactory.openSession(ExecutorType.BATCH, false);

            this.mapper = this.mapperName + "deleteLinkParaStup";
            sqlSession.update(this.mapper);

            this.mapper = this.mapperName + "insertLinkParaStup";
            total += insertBatch(sqlSession, makeStup(req, links));

            this.mapper = this.mapperName + "deleteLinkParaDetl";
            sqlSession.update(this.mapper);

            this.mapper = this.mapperName + "insertLinkParaDetl";
            total += insertBatch(sqlSession, makeDetl(req, links));

            this.mapper = this.mapperName + "deleteLinkParaClctSyst";
            sqlSession.update(this.mapper);

            this.mapper = this.mapperName + "insertLinkParaClctSyst";
            total += insertBatch(sqlSession, makeClctSyst(req, links));

            sqlSession.commit();
        }
        finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
        log.info("{}.mergeAll: ..END. {} EA. {} ms.", this.serviceName, total, elapsed.milliSeconds());

        return req;
    }

    public int insertBatch(SqlSession sqlSession, List<HashMap<String, Object>> lists) {
        log.info("{}.insertBatch: {}: START.", this.serviceName, this.mapper);

        Elapsed elapsed = new Elapsed();
        int total = lists.size();
        int jobCnt = 0;

        for (Map<String, Object> param : lists) {
            sqlSession.insert(this.mapper, param);
            jobCnt++;
            if (jobCnt % this.MAX_BATCH_SIZE == 0 || jobCnt == total) {
                sqlSession.flushStatements();
                sqlSession.clearCache();
            }
        }
        log.info("{}.insertBatch: {}: ..END. {} EA. {} ms.", this.serviceName, this.mapper, total, elapsed.milliSeconds());
        return total;
    }

    private List<HashMap<String, Object>> makeStup(LinkPrcsParaDto.LinkPrcsParaUpdateReq req, List<TbLink> links) {

        List<HashMap<String, Object>> lists = new ArrayList<>();
        LinkParaStupDto.LinkParaStupUpdateReq stup = req.getStup();
        if (stup == null) return lists;

        for (TbLink link : links) {
            if (link.getDelYn().equals("Y")) {
                continue;
            }

            HashMap<String, Object> param = new HashMap<>();
            param.put("LINK_ID",      link.getLinkId());
            param.put("FLTR_MTHD_CD", stup.getFLTR_MTHD_CD());
            param.put("FUSN_MTHD_CD", stup.getFUSN_MTHD_CD());
            param.put("ADJS_MTHD_CD", stup.getADJS_MTHD_CD());
            param.put("SMTH_MTHD_CD", stup.getSMTH_MTHD_CD());
            lists.add(param);
        }
        return lists;
    }

    private List<HashMap<String, Object>> makeDetl(LinkPrcsParaDto.LinkPrcsParaUpdateReq req, List<TbLink> links) {

        List<HashMap<String, Object>> lists = new ArrayList<>();
        LinkParaDetlDto.LinkParaDetlUpdateReq detl = req.getDetl();
        if (detl == null) return lists;

        for (TbLink link : links) {
            if (link.getDelYn().equals("Y")) {
                continue;
            }

            HashMap<String, Object> param = new HashMap<>();
            param.put("LINK_ID",                  link.getLinkId());
            param.put("FLTR_MIN_TFVL",            detl.getFLTR_MIN_TFVL());
            param.put("FLTR_MAX_TFVL",            detl.getFLTR_MAX_TFVL());
            param.put("FLTR_LWST_SPED",           detl.getFLTR_LWST_SPED());
            param.put("FLTR_HGHS_SPED",           detl.getFLTR_HGHS_SPED());
            param.put("ADJS_WGHT_AVRG_PRE_1CYCL", detl.getADJS_WGHT_AVRG_PRE_1CYCL());
            param.put("ADJS_WGHT_AVRG_PRE_2CYCL", detl.getADJS_WGHT_AVRG_PRE_2CYCL());
            param.put("ADJS_WGHT_AVRG_PRE_3CYCL", detl.getADJS_WGHT_AVRG_PRE_3CYCL());
            param.put("ADJS_PTRN_15M_APLY_YN",    detl.getADJS_PTRN_15M_APLY_YN());
            param.put("ADJS_SHTR_MISS_DECS_CYCL", detl.getADJS_SHTR_MISS_DECS_CYCL());
            param.put("SMTH_LWST_SPED_FCTR",      detl.getSMTH_LWST_SPED_FCTR());
            param.put("SMTH_HGHS_SPED_FCTR",      detl.getSMTH_HGHS_SPED_FCTR());
            param.put("SMTH_WGHT_AVRG_PRST",      detl.getSMTH_WGHT_AVRG_PRST());
            param.put("SMTH_WGHT_AVRG_PRE_1CYCL", detl.getSMTH_WGHT_AVRG_PRE_1CYCL());
            param.put("SMTH_WGHT_AVRG_PRE_2CYCL", detl.getSMTH_WGHT_AVRG_PRE_2CYCL());

            lists.add(param);
        }
        return lists;
    }

    private List<HashMap<String, Object>> makeClctSyst(LinkPrcsParaDto.LinkPrcsParaUpdateReq req, List<TbLink> links) {

        List<HashMap<String, Object>> lists = new ArrayList<>();
        List<LinkParaClctSystDto.LinkParaClctSystUpdateReq> systList = req.getSystList();
        if (systList == null) return lists;

        for (TbLink link : links) {
            if (link.getDelYn().equals("Y")) {
                continue;
            }

            for (LinkParaClctSystDto.LinkParaClctSystUpdateReq syst : systList) {
                HashMap<String, Object> param = new HashMap<>();
                param.put("LINK_ID", link.getLinkId());
                param.put("CLCT_SYST_CD", syst.getCLCT_SYST_CD());
                param.put("FUSN_PRRT",    syst.getFUSN_PRRT());
                param.put("FUSN_WGHT",    syst.getFUSN_WGHT());
                lists.add(param);
            }
        }
        return lists;
    }

}
