
package com.icomsys.main_vm.biz.rcp.conversation.service;


import com.icomsys.main_vm.biz.common.common.service.ExcelService;
import com.icomsys.main_vm.biz.common.common.service.LogService;
import com.icomsys.main_vm.biz.common.common.service.LogVO;
import com.icomsys.main_vm.biz.rcp.conversation.nlp.wisenut.service.NlpWisenutEntityService;
import com.icomsys.main_vm.biz.rcp.conversation.nlp.wisenut.vo.NlpWisenutResult;
import com.icomsys.main_vm.biz.rcp.conversation.vo.SynonymWordListVo;
import com.icomsys.main_vm.biz.rcp.conversation.vo.synonym.SelectSynonymList2Vo;
import com.icomsys.main_vm.biz.rcp.conversation.vo.synonym.SelectSynonymListVo;
import com.icomsys.main_vm.common.code.enumresource.ActionResource;
import com.icomsys.main_vm.common.code.enumresource.MenuResource;
import com.icomsys.main_vm.db.jpa.entity.conversation.TbSynonymMaster;
import com.icomsys.main_vm.db.jpa.entity.conversation.TbSynonymWord;
import com.icomsys.main_vm.db.jpa.repo.system.TbSynonymMasterRepo;
import com.icomsys.main_vm.db.jpa.repo.system.TbSynonymWordRepo;
import com.icomsys.main_vm.db.mybatis.alias.LoginVO;
import com.icomsys.main_vm.db.mybatis.mapper.SynonymManageMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.json.simple.JSONArray;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class SynonymManageService {

    private final HttpServletRequest request;

    private final MappingJackson2JsonView ajaxMainView;
    private final NlpWisenutEntityService nlpWisenutEntityService;
    @Autowired
    private SynonymManageMapper synonymManageMapper;
    @Autowired
    private TbSynonymMasterRepo tbSynonymMasterRepo;
    @Autowired
    private TbSynonymWordRepo tbSynonymWordRepo;
    private final LogService logService;
    private final ExcelService excelService;
    public ModelAndView synonymList(Map<String, String> dataMap) {
        ModelAndView mv = new ModelAndView(ajaxMainView);
        String oprMngCode = dataMap.get("custCode") + "_RCP_" + dataMap.get("serviceGroup") == null ? null : dataMap.get("custCode") + "_RCP_" + dataMap.get("serviceGroup");
        String repWord = dataMap.get("repWord") == null ? null : dataMap.get("repWord");

        List<SelectSynonymListVo> list = tbSynonymMasterRepo.selectSynonymList(oprMngCode, repWord).stream().map(e ->
                e.toSelect(tbSynonymWordRepo.findByMasterSeqAndUseYn(e.getSeq(), "Y")
                                .stream().map(f -> f.getSynonymWord())
                                .collect(Collectors.joining(",")),
                        tbSynonymWordRepo.findByMasterSeqAndUseYn(e.getSeq(), "Y")
                                .stream().map(f -> f.getSeq().toString())
                                .collect(Collectors.joining(","))
                        ))
                        .collect(Collectors.toList());
        mv.addObject("list", list);

        return mv;
    }

    public int deleteSynonym(HashMap eMap) {

        NlpWisenutResult nlpWisenutResult = nlpWisenutEntityService.entityDeleteApi(eMap);
        if (nlpWisenutResult.getResult()) {
            tbSynonymWordRepo.deleteSynonymWord(eMap);
            // 작업이력 저장
            this.workLogSave(MenuResource.rcpconversationsynonymmanage, ActionResource.delete, String.valueOf(eMap.get("serviceGroup")), "리스트 삭제");
//            synonymManageMapper.deleteSynonymWord(eMap);
            return tbSynonymMasterRepo.deleteSynonyms(eMap);
//            return synonymManageMapper.deleteSynonym(eMap);
        } else {
            log.error(nlpWisenutResult.getReturnCode() + " : " + nlpWisenutResult.getReturnMsg());
            return 0;
        }
    }

    @Transactional
    public int dupCheck(HashMap eMap) {

        LoginVO resultVO = (LoginVO) request.getSession().getAttribute("LoginVO");

        boolean nlpApiInsert;
        int returnSeq = -1;

        NlpWisenutResult nlpWisenutResult = new NlpWisenutResult();

//        int dupIndivWord = synonymManageMapper.dupIndivWord(eMap);
        Long dupIndivWord = tbSynonymMasterRepo.dupIndivWord(eMap);
        if (dupIndivWord > 0) {
            throw new DuplicateKeyException("중복된 개체어입니다.");
        }

        //int dupRepWord = synonymManageMapper.dupRepWord(eMap);
        Long dupRepWord = tbSynonymMasterRepo.dupRepWord(eMap);
        if (dupRepWord > 0) {
            throw new DuplicateKeyException("중복된 대표어입니다.");
        }

        //Integer seq = synonymManageMapper.selectSynonymMaster(eMap);
        Long seq = tbSynonymMasterRepo.selectSynonymMaster(eMap);
        if (seq == null) {
            eMap.put("seq", "");
        } else {
            eMap.put("seq", seq);
        }

        nlpApiInsert = StringUtils.isEmpty(eMap.get("seq").toString());
        if (nlpApiInsert) {
            // NLP API
            nlpWisenutResult = nlpWisenutEntityService.entityInsertApi(eMap);
        } else {
            // NLP API
            if (tbSynonymMasterRepo.dupRepWordN(eMap) > 0) {
                nlpWisenutResult = nlpWisenutEntityService.entityInsertApi(eMap);
            } else {
                nlpWisenutResult = nlpWisenutEntityService.entityUpdateApi(eMap);
            }
        }

        // NLP API
        if (nlpWisenutResult.getResult()) {
            if (nlpApiInsert) {
                eMap.put("mappingId", nlpWisenutResult.getMappingId());
            }
            //this.insertSynonymMaster(eMap);
            if (tbSynonymMasterRepo.existsBySeq(seq)){

                tbSynonymMasterRepo.updateSynonymMaster(eMap);
            /*findBySeq(seq).get()
                        .UpdateSynonymMaster(eMap);*/

            /*save(new TbSynonymMaster().builder()
                            .idivWord(eMap.get("idivWord").toString())
                            .repWord(eMap.get("repWord").toString())
                            .useYn("Y")
                            .updateId(resultVO.getUserId())
                            .updateDate(LocalDateTime.now())
                        .build());*/
            }
            else {
                BigDecimal decimalId = new BigDecimal(nlpWisenutResult.getMappingId());

                    tbSynonymMasterRepo.save(TbSynonymMaster.builder()
                            .oprMngCode(eMap.get("custCode") + "_RCP_" + eMap.get("serviceGroup"))
                            .idivWord(eMap.get("idivWord").toString())
                            .repWord(eMap.get("repWord").toString())
                            .ifMappingId(decimalId.longValue())
                            .useYn("Y")
                            .registId(resultVO.getUserId())
                            .registDate(LocalDateTime.now())
                            .updateId(resultVO.getUserId())
                            .updateDate(LocalDateTime.now())
                            .build());
                    this.workLogSave(MenuResource.rcpconversationsynonymmanage, ActionResource.insert, String.valueOf(eMap.get("serviceGroup")), "리스트 등록");
            }
            //returnSeq = synonymManageMapper.selectSynonymMaster(eMap);
            returnSeq = Math.toIntExact(tbSynonymMasterRepo.selectSynonymMaster(eMap));
            JSONArray arr = (JSONArray) eMap.get("list");
            for (int i = 0; i < arr.size(); i++) {

                eMap.put("synonymWord", arr.get(i));

                //int dupSynonymY = synonymManageMapper.dupSynonymY(eMap);
                Long dupSynonymY = tbSynonymMasterRepo.dupSynonymY(eMap);

                if (dupSynonymY > 0) {
                    throw new DuplicateKeyException("중복된 동의어입니다.");
                }

                //int dupSynonymN = synonymManageMapper.dupSynonymN(eMap);
                Long dupSynonymN = tbSynonymMasterRepo.dupSynonymN(eMap);
                if (dupSynonymN > 0) {
                    this.updateSynonymWord(eMap);
                    //tbSynonymWordRepo.updateSynonymWord(eMap);
                } else {
                    //this.insertSynonymWord(eMap);
                    List<TbSynonymWord> SynonymWordInsert = new ArrayList<>();
                    for (SynonymWordListVo e : tbSynonymWordRepo.insertSynonymWord(eMap)) {

                        SynonymWordInsert.add(TbSynonymWord.builder()
                                .masterSeq(e.getSeq())
                                .oprMngCode(eMap.get("custCode") + "_RCP_" + eMap.get("serviceGroup"))
                                .synonymWord(eMap.get("synonymWord").toString())
                                .useYn("Y")
                                .registId(resultVO.getUserId())
                                .registDate(LocalDateTime.now())
                                .updateId(resultVO.getUserId())
                                .updateDate(LocalDateTime.now())
                                .build());
                        tbSynonymWordRepo.saveAll(SynonymWordInsert);

                        logService.LogSave(LogVO.builder()
                                .menuAuth(MenuResource.rcpconversationsynonymmanage)
                                .actionCode(String.valueOf((ActionResource.insert)))
                                .serviceGroup(String.valueOf(eMap.get("serviceGroup")))
                                .remark("동의어 단일 등록")
                                .build());
                    }
                }
            }

            // NLP API
        } else {
            log.error(nlpWisenutResult.getReturnCode() + " : " + nlpWisenutResult.getReturnMsg());
            throw new DuplicateKeyException(nlpWisenutResult.getReturnMsg());
        }
        return returnSeq;
    }

    public void uploadDupCheck (HashMap eMap) {

        boolean nlpApiInsert = true;
        NlpWisenutResult nlpWisenutResult = new NlpWisenutResult();

        int dupIndivWord = synonymManageMapper.dupIndivWord(eMap);
        if (dupIndivWord > 0) {
            throw new DuplicateKeyException("중복된 개체어입니다.");
        }
        int dupRepWord = synonymManageMapper.dupRepWord(eMap);
        if (dupRepWord > 0) {
            throw new DuplicateKeyException("중복된 대표어입니다.");
        }

        Integer seq = synonymManageMapper.selectSynonymMaster(eMap);

        if (eMap.get("seq") != null) {
            nlpApiInsert = StringUtils.isEmpty(eMap.get("seq").toString());
        }

        if (seq == null) {
            eMap.put("seq", "");
        } else {
            eMap.put("seq", seq);
        }

        if (nlpApiInsert) {
            // NLP API
            nlpWisenutResult = nlpWisenutEntityService.entityInsertApi(eMap);
        } else {
            // NLP API
            nlpWisenutResult = nlpWisenutEntityService.entityUpdateApi(eMap);
        }
        if (nlpWisenutResult.getResult()) {
            if (dupRepWord <= 1 && dupIndivWord <= 1) {
                if (nlpApiInsert) {
                    eMap.put("mappingId", nlpWisenutResult.getMappingId());
                }
                this.insertSynonymMaster(eMap);
            }


            System.out.println("***************************************");
            String[] list = (String[]) eMap.get("list");
            for (String s : list) {
                eMap.put("synonymWord", s);

                int dupSynonymY = synonymManageMapper.dupSynonymY(eMap);

                if (dupSynonymY > 0) {
                    throw new DuplicateKeyException("중복된 동의어입니다.");
                }
                if (dupSynonymY <= 1) {
                    int dupSynonymN = synonymManageMapper.dupSynonymN(eMap);
                    if (dupSynonymN > 0) {
                        this.updateSynonymWord(eMap);
                    } else {
                        this.insertSynonymWord(eMap);
                    }
                }
            }
        } else {
            log.error(nlpWisenutResult.getReturnCode() + " : " + nlpWisenutResult.getReturnMsg());
            throw new DuplicateKeyException(nlpWisenutResult.getReturnMsg());
        }
    }

    private int insertSynonymMaster(HashMap eMap) {
        return synonymManageMapper.insertSynonymMaster(eMap);
    }

    private void insertSynonymWord(HashMap eMap) {
        synonymManageMapper.insertSynonymWord(eMap);
    }

    private void updateSynonymWord(HashMap eMap) {
        synonymManageMapper.updateSynonymWord(eMap);
    }

    public int saveSynonymList(HashMap eMap) {

        logService.LogSave(LogVO.builder()
                .menuAuth(MenuResource.rcpconversationsynonymmanage)
                .actionCode(String.valueOf((ActionResource.delete)))
                .serviceGroup(String.valueOf(eMap.get("serviceGroup")))
                .remark("동의어 단일 삭제")
                .build());
        return synonymManageMapper.saveSynonymList(eMap);
    }

    public int countSynonymWord(HashMap eMap) {
        return synonymManageMapper.countSynonymWord(eMap);
    }

    public void workLogSave(MenuResource menuAuth, ActionResource actionCode, String serviceGroup, String remark) {
        logService.LogSave(LogVO.builder()
                .menuAuth(menuAuth)
                .actionCode(String.valueOf((actionCode)))
                .serviceGroup(serviceGroup)
                .remark(remark)
                .build());
    }

    public void downloadExcel(Map<String, String> dataMap) throws IOException {

        String oprMngCode = dataMap.get("custCode") + "_RCP_" + dataMap.get("serviceGroup") == null ? null : dataMap.get("custCode") + "_RCP_" + dataMap.get("serviceGroup");
        String repWord = dataMap.get("repWord") == null ? null : dataMap.get("repWord");

        List<SelectSynonymList2Vo> list = tbSynonymMasterRepo.selectSynonymList(oprMngCode, repWord).stream().map(e ->
                        e.toExcel(tbSynonymWordRepo.findByMasterSeqAndUseYn(e.getSeq(), "Y")
                                .stream().map(f -> f.getSynonymWord())
                                .collect(Collectors.joining(","))
                        ))
                .collect(Collectors.toList());
        List<String> colName = new ArrayList<>();

        colName.add("개체어");
        colName.add("대표어");
        colName.add("동의어");
        excelService.ExcelDownload("excel_synonym", list, colName);
        this.workLogSave(MenuResource.rcpconversationsynonymmanage, ActionResource.download, dataMap.get("serviceGroup"), "엑셀 다운로드");

    }
}
