package com.eactive.eai.rms.onl.loader.service;

import java.util.List;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.eactive.eai.data.entity.onl.adapter.Adapter;
import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageInfo;
import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.data.entity.onl.adapter.AdapterGroupService;
import com.eactive.eai.rms.data.entity.onl.adapter.AdapterService;
import com.eactive.eai.rms.data.entity.onl.stdmessage.StandardMessageInfoService;
import com.eactive.eai.rms.onl.common.util.FileWriteUtil;
import com.eactive.eai.rms.onl.loader.intf.InterfaceDeployService;
import com.eactive.eai.rms.onl.loader.intf.deploy.EAIMessageDeploy;
import com.eactive.eai.rms.onl.loader.intf.deploy.StandardMessageInfoDeploy;
import com.eactive.eai.rms.onl.loader.layout.LayoutDeployService;
import com.eactive.eai.rms.onl.loader.layout.deploy.LayoutDeploy;
import com.eactive.eai.rms.onl.loader.transform.TransformDeployService;
import com.eactive.eai.rms.onl.loader.transform.deploy.TransformDeploy;

@Service("deployJsonServiceOnline")
public class TransactionDeployJsonServiceOnline extends TransactionDeployJsonEmptyService {

    /** The monitoring context. */
    @Autowired
    @Qualifier("monitoringContext")
    private transient MonitoringContext monitoringContext;

   @Autowired @Qualifier("OnlInterfaceDeployService")
   private InterfaceDeployService interfaceDeployService;

   @Autowired
   private LayoutDeployService layoutDeployService;

   @Autowired
   private TransformDeployService transformDeployService;

   @Autowired
   private AdapterGroupService adapterGroupService;
   
   @Autowired
   private AdapterService adapterService;

   @Autowired
   private StandardMessageInfoService standardMessageInfoService;


   @Transactional
   public void insertLayoutLoading(String path, String fileName)
         throws Exception {
      String json = load(path + fileName, "UTF-8");
      LayoutDeploy deploy = mapper.readValue(json, LayoutDeploy.class);
      layoutDeployService.saveDeploy(deploy);
   }

   @Transactional
   public void insertTransformLoading(String path, String fileName)
         throws Exception {
      String json = load(path + fileName, "UTF-8");
      TransformDeploy transformDeploy = mapper.readValue(json, TransformDeploy.class);
      transformDeployService.saveDeploy(transformDeploy);
   }

   @Transactional
   public void insertInterfaceLoading(String path, String fileName)
         throws Exception {
      String json = load(path + fileName, "UTF-8");
      EAIMessageDeploy eaiMessageDeploy = mapper.readValue(json, EAIMessageDeploy.class);
      checkAdapter(eaiMessageDeploy);
      checkAdapterInstance(eaiMessageDeploy);
      checkInnerStandardDuplication(eaiMessageDeploy);
      interfaceDeployService.saveDeploy(eaiMessageDeploy);
   }
   
   private void checkAdapter(EAIMessageDeploy deploy) throws Exception {
      String eaiSvcName  = deploy.getEaisvcname();                                             //인터페이스명

      //1.src adapter 추출
      String srcAdapter = deploy.getGstatsysadptrbzwkgroupname();
      String srcType    = deploy.getSvcmotivusedstcd();
      if (StringUtils.isBlank(srcAdapter)) {
         throw new Exception("소스 어댑터명이 비었습니다. interface["+ deploy.getEaisvcname() +"]");
      }
      
      ;
      
      if (!adapterGroupService.findById(srcAdapter).isPresent()) {
         throw new Exception("소스어댑터("+srcAdapter+")가 DB에 존재하지 않습니다.");
      }
      if (deploy.getServiceMessages() == null || deploy.getServiceMessages().size() ==0 ) {
         throw new Exception("인터페이스("+eaiSvcName+") 서비스처리정보가 없습니다.");
      }
      String sndRecvType = eaiSvcName.substring(eaiSvcName.length()-2, eaiSvcName.length()-1); //인터페이스 송수신구분

      //2.tgt adapter 추출
      String tgtAdapter = deploy.getServiceMessages().get(0).getPsvsysadptrbzwkgroupname();
      String tgtType    = deploy.getServiceMessages().get(0).getPsvintfacdsticname();
      
      //S-A 응답일때 빼고 수동어댑터 체크
      if ("SYNC".equals(srcType) && "ASYN".equals(tgtType) && "R".equals(sndRecvType)   ) {
         ;
      }else {
         if (StringUtils.isBlank(tgtAdapter)) {
            throw new Exception("타겟 어댑터명이 비었습니다.. interface["+ deploy.getEaisvcname() +"]");
         }
         if (!adapterGroupService.findById(tgtAdapter).isPresent()) {
            throw new Exception("타겟 어댑터("+tgtAdapter+")가 DB에 존재하지 않습니다.");
         }
      }
      
      // A-S > HE01의 인터페이스유형 ASYN이고 HE02의 첫번째 수동인터페이스가 SYNC일 때 -> 수동인터페이스 2개
      if(srcType.equals("ASYN") && tgtType.equals("SYNC")){
         if(deploy.getServiceMessages().size()==1){
            throw new Exception("sync-async 응답 서비스가 존재 하지 않습니다.");
         }
         
         String resAdapter = deploy.getServiceMessages().get(1).getPsvsysadptrbzwkgroupname();
         if(StringUtils.isBlank(resAdapter)){
            throw new Exception("sync-async 응답 어댑터명이 비었습니다. interface["+ deploy.getEaisvcname() +"]");
         }
         if (!adapterGroupService.findById(resAdapter).isPresent()) {
            throw new Exception("sync-async 응답 어댑터("+resAdapter+")가 존재하지 않습니다.");
         }
      }
   }
   private void checkAdapterInstance(EAIMessageDeploy deploy) throws Exception {
       boolean ret = true;
      if (deploy == null || StringUtils.isBlank(deploy.getEaisvcname())){
         ret = false;
         throw new Exception("인터페이스가 존재하지 않습니다.");
      }
      String eaiSvcName  = deploy.getEaisvcname();
      String srcType     = deploy.getSvcmotivusedstcd();
      String srcAdapter  = deploy.getGstatsysadptrbzwkgroupname();                  //기동어댑터명
      
      if (deploy.getServiceMessages() == null || deploy.getServiceMessages().size() ==0 ) {
         throw new Exception("인터페이스("+eaiSvcName+") 서비스처리정보가 없습니다.");
      }
      
      String tgtAdapter = deploy.getServiceMessages().get(0).getPsvsysadptrbzwkgroupname();  //수동어댑터명
      String tgtType    = deploy.getServiceMessages().get(0).getPsvintfacdsticname();
      
      String sndRecvType = eaiSvcName.substring(eaiSvcName.length()-2, eaiSvcName.length()-1);   //인터페이스 송수신구분
      
      //ad02
      Iterable<Adapter> ouAdapterInst = adapterService.findByIdAdptrbzwkgroupname(tgtAdapter);
      //outBound 어댑터 정보가 없고 그룹명만 있을 때 ____ 비교 X
      int count =0;
      for(Adapter a : ouAdapterInst) {
         count++;
      }
      if(count==0){
         return ;
      }
      
      //기동어댑터와 관계없이 수동어댑터 바인딩된 인스턴스가 ALL일때 우선적으로 PASS (A_S 패턴 포함 - 처리순서1인 어댑터로 비교)
      for(Adapter a : ouAdapterInst) {
         if ("ALL".equals(a.getEaisevrinstncname())) {
            return;
         }
      }
      
      Iterable<Adapter> inAdapterInst = adapterService.findByIdAdptrbzwkgroupname(srcAdapter);
      //inBound 어댑터 정보가 없고 그룹명만 있을 때 ____ 비교 X
      count =0;
      for(Adapter a : inAdapterInst) {
         count++;
      }
      if(count==0){
         return ;
      }
      
      Iterable<Adapter> ouAdptInst2 = null;
      
      //S_A 패턴 응답 ___ 비교 X
      if(srcType.equals("SYNC") && tgtType.equals("ASYN") && sndRecvType.equals("R")){
         return ;
      }
      
      //A_S 패턴 
      if(srcType.equals("ASYN") && tgtType.equals("SYNC")){
         if(deploy.getServiceMessages().size()==1){
            throw new Exception("sync-async 응답 서비스가 존재 하지 않습니다.");
         }
         String resAdapter = deploy.getServiceMessages().get(1).getPsvsysadptrbzwkgroupname();
         
         ouAdptInst2 = adapterService.findByIdAdptrbzwkgroupname(resAdapter);
      }
      /**
       * SNA 체크임 SNA안쓰는곳에서는 필요없음-시작
       */
      /*
      //IN 어댑터 List의 ADPTRCD는 다 같음.
      String adptrGrpName = (String)inAdptInstList.get(0).get("ADPTRBZWKGROUPNAME");
      //IN 어댑터가 SNA일때
      boolean flag = false;
      if(adptrGrpName.indexOf("SNA")>=0){
         inAdptInstList.clear();
         List<LinkedHashMap> snaApList = inboundErrorInfoDao.selectSnaAdpApList(dataSourceType, adptrGrpName);
         String svcApCd = eaiSvcName.substring(0,3);   //서비스코드 앞 3자리
         for(LinkedHashMap m : snaApList){
            String apList = (String)m.get("PRPTY2VAL");
            int chk = apList.indexOf(svcApCd);
            if(chk>=0){
               inAdptInstList.add(m);
               flag = true;
            }
         }
         if(!flag){
            ret = false;
            throw new Exception("[EAI서비스코드 : "+eaiSvcName+"] AP코드("+svcApCd+")가 SNA어댑터["+adptrGrpName+"]에 존재하지 않습니다");
         }
      }
      //in out 불일치 
      int cnt = inAdptInstList.size();
      String srcAdptName = "";
      String tgtAdptName = "";
      for(HashMap om : ouAdptInstList){
         String ouInst = (String)om.get("EAISEVRINSTNCNAME");
         tgtAdptName = (String)om.get("ADPTRBZWKGROUPNAME");
         if("ALL".equals(ouInst)){
            cnt=0;
            break;
         }
         for(HashMap im : inAdptInstList){
            String inInst =(String)im.get("EAISEVRINSTNCNAME");
            srcAdptName = (String)im.get("ADPTRBZWKGROUPNAME");
            if(ouInst.equals(inInst)){
               cnt--;
               continue;
            }
         }
      }
      if(cnt>0){
         ret = false;
         throw new Exception("[EAI서비스코드 : "+eaiSvcName+"] 기동어댑터와 수동어댑터의 인스턴스가 일치하지 않습니다 [기동 : "+srcAdptName+" / 수동 : "+tgtAdptName+"]");
      }
      if(ouAdptInstList2.size()>0){   //A-S 패턴 수동인터페이스 어댑터2 번째꺼 
         int cnt2 = inAdptInstList.size();
         for(HashMap om : ouAdptInstList2){
            String ouInst = (String)om.get("EAISEVRINSTNCNAME");
            tgtAdptName = (String)om.get("ADPTRBZWKGROUPNAME");
            if("ALL".equals(ouInst)){
               cnt2=0;
               break;
            }
            for(HashMap im : inAdptInstList){
               String inInst =(String)im.get("EAISEVRINSTNCNAME");
               srcAdptName = (String)im.get("ADPTRBZWKGROUPNAME");
               if(ouInst.equals(inInst)){
                  cnt2--;
                  continue;
               }
            }
         }
         if(cnt2>0){
            ret = false;
            throw new Exception("[EAI서비스코드 : "+eaiSvcName+"] 기동어댑터와 수동어댑터의 인스턴스가 일치하지 않습니다 [기동 : "+srcAdptName+" / 수동 : "+tgtAdptName+"]");
         }
      }
      */
      /**
       * SNA 체크임 SNA안쓰는곳에서는 필요없음-종료
       */

   }
   private void checkInnerStandardDuplication(EAIMessageDeploy deploy) throws Exception {
      List<StandardMessageInfoDeploy> standardInfo = deploy.getStandardMessageInfoDeploys();
      if (standardInfo.size()> 0 ) {
         for(StandardMessageInfoDeploy s : standardInfo) {
            //db정보가져옴
            Optional<StandardMessageInfo> optional = standardMessageInfoService.findById(s.getBzwksvckeyname());
            if (optional.isPresent()) {
               StandardMessageInfo info = optional.get();
               if (!deploy.getEaisvcname().equals(info.getEaisvcname())){// 설정정보가 다른경우
                  throw  new Exception("저장 하려는 내부표준전문 key("+s.getBzwksvckeyname()+") 의 interface("+deploy.getEaisvcname()+")값과 DB의 interface("+info.getEaisvcname()+")값이 다르다");
               }
            }
         }
      }
   }   
    @Transactional
    public String getLayout(String layoutName)   throws Exception {
       LayoutDeploy layoutDeploy = layoutDeployService.selectDeploy(layoutName);
       if (layoutDeploy == null) {
          throw new Exception ("layout data is empty  layoutName =["+layoutName+"]") ;
       }


      return mapper.writeValueAsString(layoutDeploy);
    }
    @Transactional
    public String getTransform(String transformName)   throws Exception {
       TransformDeploy transformDeploy = transformDeployService.selectDeploy(transformName);
       if (transformDeploy == null) {
          throw new Exception ("transform data is empty  transformName =["+transformName+"]") ;
       }
       
       return mapper.writeValueAsString(transformDeploy);
    }
    @Transactional
    public String getInterface(String eaiSvcName)   throws Exception {
       EAIMessageDeploy interfaceDeploy = interfaceDeployService.selectDeploy(eaiSvcName);
       if (interfaceDeploy == null) {
          throw new Exception ("interface data is empty  interfaceName =["+eaiSvcName+"]") ;
       }
       
       return mapper.writeValueAsString(interfaceDeploy);
    }
    public void layoutDownLoading(String path,String layoutName)   throws Exception {
       String json = getLayout(layoutName);
       FileWriteUtil.FileWrite(path , layoutName+".txt", json, "UTF-8");
    }
    public void transformDownLoading(String path,String transformName)   throws Exception {
       String json = getTransform(transformName);
       FileWriteUtil.FileWrite(path , transformName+".txt", json, "UTF-8");
    }
    public void interfaceDownLoading(String path,String eaiSvcName)   throws Exception {
       String json = getInterface(eaiSvcName);
       FileWriteUtil.FileWrite(path , eaiSvcName+".txt", json, "UTF-8");
    }

}
