package com.eactive.eai.common.logger;

import java.nio.charset.Charset;
import java.util.Properties;

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

import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.agent.encryption.EncryptionManager;
import com.eactive.eai.authserver.service.OAuth2Manager;
import com.eactive.eai.authserver.vo.ClientVO;
import com.eactive.eai.common.dao.DAOException;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.logger.mapper.StatAdapterLogMapper;
import com.eactive.eai.common.logger.mapper.StatLogMapper;
import com.eactive.eai.common.logger.mapper.StatTranLogMapper;
import com.eactive.eai.common.message.EAIMessage;
import com.eactive.eai.common.message.EAIMessageKeys;
import com.eactive.eai.common.message.MessageType;
import com.eactive.eai.common.message.ServiceMessage;
import com.eactive.eai.common.monitor.StatMonitorLogVO;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.server.EAIServerManager;
import com.eactive.eai.common.server.EAIServerVO;
import com.eactive.eai.common.server.loader.EAIServerLoader;
import com.eactive.eai.common.util.DatetimeUtil;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.common.util.MessageUtil;
import com.eactive.eai.common.util.StringUtil;
import com.eactive.eai.data.RollingTable;
import com.eactive.eai.data.entity.onl.logger.EAIErrorLog;
import com.eactive.eai.data.entity.onl.logger.EAIErrorLogId;
import com.eactive.eai.data.entity.onl.logger.EAILog;
import com.eactive.eai.data.entity.onl.logger.EAILogId;
import com.eactive.eai.data.entity.onl.logger.StatAdapterLog;
import com.eactive.eai.data.entity.onl.logger.StatLog;
import com.eactive.eai.data.entity.onl.logger.StatTranLog;
import com.eactive.eai.data.entity.onl.logger.SubMessageLog;
import com.eactive.eai.data.entity.onl.logger.SubMessageLogId;
import com.eactive.eai.message.EncodingVar;
import com.eactive.eai.message.StandardMessage;
import com.eactive.eai.message.manager.StandardMessageManager;
import com.eactive.eai.transformer.layout.Item;
import com.eactive.eai.transformer.layout.Layout;
import com.eactive.eai.transformer.transform.Transform;
import com.eactive.eai.transformer.transform.TransformManager;
// safeDB
import com.eactive.ext.kjb.safedb.KjbSafedbWrapper;
import com.eactive.ext.kjb.safedb.Utils;
import com.ext.eai.common.stdmessage.STDMessageKeys;


@Service
@Transactional
public class EAILogDAO {
//extends BaseDAO {
	static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);

	@Autowired
	private ApplicationContext applicationContext;

	@Autowired
	private EAILogLogger eaiLogEntityService;
	
	@Autowired
	private SubMessageLogLogger subMessageLogLogger;

	@Autowired
	private StatLogLogger statLogLogger;
	
	@Autowired
	private StatTranLogLogger statTranLogLogger;
	
	@Autowired
	private StatAdapterLogLogger statAdapterLogLogger;

	@Autowired
	private StatLogMapper statLogMapper;
	
	@Autowired
	private StatTranLogMapper statTranLogMapper;
	
	@Autowired
	private StatAdapterLogMapper statAdapterLogMapper;
	
	@Autowired
	private EAIServerLoader eaiServerEntityService;
	
	public EAILogDAO() {
		// empty
	}

	/**
	 * 1. 기능 : 메시지의 Type이 EBCDIC인지 판단 2. 처리 개요 : - 로그시퀀스에 맞는 Adapter의 메시지 type을 비교 -
	 * EBC인지 판별 3. 주의사항
	 *
	 * @param srcIfType         String
	 * @param tgtIfType         String
	 * @param logPssSno         int
	 * @param srcAdapterMsgType String
	 * @param tgtAdapterMsgType String
	 * @return boolean
	 **/
	public boolean isEBC(String srcIfType, String tgtIfType, int logPssSno, String srcAdapterMsgType,
			String tgtAdapterMsgType) {

		boolean isEBCDIC = false;

		// SS. SA Type
		if (logPssSno == 100) {
			if (MessageType.EBC.equals(srcAdapterMsgType)) {
				isEBCDIC = true;
			}
		} else if (logPssSno == 200) {
			if (MessageType.EBC.equals(tgtAdapterMsgType)) {
				isEBCDIC = true;
			}
		} else if (logPssSno == 300) {
			if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) {
				if (MessageType.EBC.equals(srcAdapterMsgType)) {
					isEBCDIC = true;
				}
			} else {
				if (MessageType.EBC.equals(tgtAdapterMsgType)) {
					isEBCDIC = true;
				}
			}
		}
		// 400
		else if (logPssSno == 400) {
			if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) {
				if (MessageType.EBC.equals(tgtAdapterMsgType)) {
					isEBCDIC = true;
				}
			} else {
				if (MessageType.EBC.equals(srcAdapterMsgType)) {
					isEBCDIC = true;
				}
			}
		}
		// 900
		else {
			if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) {
				if (MessageType.EBC.equals(tgtAdapterMsgType)) {
					isEBCDIC = true;
				}
			} else {
				if (MessageType.EBC.equals(srcAdapterMsgType)) {
					isEBCDIC = true;
				}
			}
		}
		return isEBCDIC;
	}

	public boolean isUTF8(String srcIfType, String tgtIfType, int logPssSno, String srcAdapterMsgEncode,
			String tgtAdapterMsgEncode) {
		boolean isUTF = false;
		if (logger.isInfo()) {
			logger.info(String.format("EAILogDAO] isUTF8 %s  %s  %s  %s  %s", srcIfType, tgtIfType, logPssSno,
					srcAdapterMsgEncode, tgtAdapterMsgEncode));
		}

		String adapterMsgEncode = "";
		// SS. SA Type
		if (logPssSno == 100) {
			adapterMsgEncode = srcAdapterMsgEncode;
		} else if (logPssSno == 200) {
			adapterMsgEncode = tgtAdapterMsgEncode;
		} else if (logPssSno == 300) {
			if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) {
				adapterMsgEncode = srcAdapterMsgEncode;
			} else {
				adapterMsgEncode = tgtAdapterMsgEncode;
			}
		}
		// 400
		else if (logPssSno == 400) {
			if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) {
				adapterMsgEncode = tgtAdapterMsgEncode;
			} else {
				adapterMsgEncode = srcAdapterMsgEncode;
			}
		}
		// 900
		else {
			if (EAIMessageKeys.ASYNC_SVC.equals(srcIfType) && EAIMessageKeys.ASYNC_SVC.equals(tgtIfType)) {
				adapterMsgEncode = tgtAdapterMsgEncode;
			} else {
				adapterMsgEncode = srcAdapterMsgEncode;
			}
		}
		isUTF = StringUtils.equalsIgnoreCase(adapterMsgEncode, "UTF-8");
		return isUTF;
	}

	/**
	 * 1. 기능 : EAI 서비스 로그 셋팅 2. 처리 개요 : - TSEAILG01(EAI서비스로그) 로그값 셋팅 -
	 * TSEAILG03(EAI로그업무데이터서브정보) insert 여부 결정 3. 주의사항
	 *
	 * @param message EAIMessage
	 * @exception DAOException
	 **/
	public void addEAISvcLog(EAIMessage message, Properties prop) throws Exception {
		String apndBwkDataYn = "N"; // 추가업무데이터 여부

		// 개별메시지
		String bizMsg = message.getStandardMessage().getBizData();

		ServiceMessage svcMsg = message.getCurrentSvcMsg();
		String bizMsgStr = "";

		// transformer 적용
		String svcTsmtUsgTp = message.getSvcTsmtUsgTp(); // 기동 Syunc/Async
		String psvItfTp = svcMsg.getPsvItfTp(); // 수동 Syunc/Async
		int logPssSno = message.getLogPssSno();
		String rspErrCd = message.getRspErrCd();

		// Duplication Error 방지를 위해
		// 원 로그처리일련번호를 저장 : 2009.07.13
		int orglogPssSno = logPssSno;

		int svcLogLvl = message.getSvcLogLvl();
		boolean loggingBizData = true;

		// 특정거래에 대해 업무데이터를 저외함.
		if (svcLogLvl > 3) {
			loggingBizData = false;
		}
		if (logger.isInfo())
			logger.info("EAILogDAO] loggingBizData - " + loggingBizData);

		// 복합거래인 경우 2X1,3X1 -> 200, 2X2,3X2 -> 300 처럼 처리한다.
		if ((logPssSno > 200 && logPssSno < 300) || (logPssSno > 300 && logPssSno < 400)) {
			if ((logPssSno % 2) == 1) {
				logPssSno = 200;
			} else {
				logPssSno = 300;
			}
		}

		// 업무테이터 처리
		// 1. Get Source, Target Adapter Group Name
		String srcAdapterGroupName = message.getSngSysItfTp();
		String tgtAdapterGroupName = message.getCurrentSvcMsg().getPsvSysItfTp();

		// 2. Get Source, Target Adapter GroupVO
		AdapterManager adapterManager = AdapterManager.getInstance();
		AdapterGroupVO srcAdapterGrpVO = adapterManager.getAdapterGroupVO(srcAdapterGroupName);
		AdapterGroupVO tgtAdapterGrpVO = adapterManager.getAdapterGroupVO(tgtAdapterGroupName);

		// 3. Get Source, Target Adapter Message Type
		String srcAdapterMsgType = null;
		String srcAdptrMsgPtrnCd = null;
		String tgtAdapterMsgType = null;
		String tgtAdptrMsgPtrnCd = null;

		String srcAdapterMsgEncode = null;
		String tgtAdapterMsgEncode = null;

		if (srcAdapterGrpVO == null) {
			srcAdapterMsgType = MessageType.ASC;
			srcAdapterMsgEncode = Charset.defaultCharset().name();
			if (logger.isWarn()) {
				logger.warn("EAILogDAO] Source Adapter null. eai service code=" + message.getEAISvcCd());
			}
		} else {
			srcAdapterMsgType = srcAdapterGrpVO.getMessageType();
			srcAdptrMsgPtrnCd = srcAdapterGrpVO.getAdptrMsgPtrnCd();
			srcAdapterMsgEncode = StringUtils.defaultIfBlank(srcAdapterGrpVO.getMessageEncode(),
					Charset.defaultCharset().name());
		}
		
		if (tgtAdapterGrpVO == null) {
			tgtAdapterMsgType = MessageType.ASC;
			tgtAdapterMsgEncode = Charset.defaultCharset().name();
			if (logger.isWarn()) {
				logger.warn("EAILogDAO] Target Adapter null. eai service code=" + message.getEAISvcCd());
			}
		} else {
			tgtAdapterMsgType = tgtAdapterGrpVO.getMessageType();
			tgtAdptrMsgPtrnCd = tgtAdapterGrpVO.getAdptrMsgPtrnCd();
			tgtAdapterMsgEncode = StringUtils.defaultIfBlank(tgtAdapterGrpVO.getMessageEncode(),
					Charset.defaultCharset().name());
		}
		
		// SUBSTANDARD Logging
		StandardMessage subMessage = message.getSubMessage();
		boolean isSubLogging = false;
		if(subMessage != null) {
			isSubLogging = checkSubLogging(svcTsmtUsgTp, psvItfTp, srcAdptrMsgPtrnCd, tgtAdptrMsgPtrnCd, logPssSno);
			if (logger.isDebug()) {
				logger.debug( String.format("EAILogDAO] SUBSTANDARD-LOGGING checkSubLogging %s-%s %s-%s %d => %s", 
						svcTsmtUsgTp, psvItfTp, srcAdptrMsgPtrnCd, tgtAdptrMsgPtrnCd, logPssSno, isSubLogging) );
			}
		}
		if(isSubLogging) {
			String headerData  = subMessage.toFixedString(false, EncodingVar.flatEncoding);
			if (logger.isDebug()) {
				logger.debug( String.format("EAILogDAO] SUBSTANDARD-LOGGING UUID: %s, LOGSEQ: %s, HEADER: %s", 
						message.getSvcOgNo(), logPssSno, headerData) );
			}
			try {
				String layoutName = StandardMessageManager.getInstance().getVersionLayoutName();
				
				SubMessageLog subMessageLog = (SubMessageLog) applicationContext.getBean(RollingTable.class, SubMessageLog.class,
						message.getMsgRcvTm());
				SubMessageLogId subLogId = new SubMessageLogId();
				subMessageLog.setId(subLogId);
				subLogId.setEaisvcserno(message.getSvcOgNo());
				subLogId.setLogprcssserno(String.valueOf(orglogPssSno));
				subMessageLog.setLayoutname(layoutName);
				subMessageLog.setHeaderdata(headerData);
				subMessageLogLogger.save(subMessageLog);
			}
			catch(Exception ex) {
				logger.error( String.format("EAILogDAO] SUBSTANDARD-LOGGING ERROR UUID: %s, LOGSEQ: %s, HEADER: %s", 
						message.getSvcOgNo(), logPssSno, headerData), ex);
			}
		}
		
		String bwkData = "";
		String addBwkData = "";
		String refMsgID = "";

		if (loggingBizData) {
			// ---------------------------------------------------
			// LogMasking 을 위해 변환이 등록된 경우에만
			// 변환을 통해 처리하도록 수정
			// ---------------------------------------------------
			boolean isMasked = false;
			boolean isMasking = false;

			// 변환이 등록된 경우
			if ("1".equals(svcMsg.getCnvEn())) {
				TransformManager manager = TransformManager.getManager();
				Transform info = null;
				Layout l = null;

				// AA - 요청변환에서
				if (EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.ASYNC_SVC.equals(psvItfTp)) {
					info = manager.getTransform(svcMsg.getCnvMsgID()); // 요청변환메시지ID명
				}
				// AA이 아닌 경우
				// - 100, 200 요청변환에서
				// - 300, 400 응답변환에서
				else {
					if (logPssSno == 100 || logPssSno == 200) {
						info = manager.getTransform(svcMsg.getCnvMsgID()); // 요청변환메시지ID명
					} else {
						if (rspErrCd.equals(EAIMessageKeys.BWK_ERRMSG_CODE)) { // 업무에러(RIBEAI999999)
							info = manager.getTransform(svcMsg.getErrRspCnvMsgID()); // 오류응답변환메시지ID명
							if (info == null) {
								info = manager.getTransform(svcMsg.getBsRspCnvMsgID()); // 기본응답변환메시지ID명
							}
						} else if (MessageUtil.checkRspErrCd(rspErrCd)) {
							info = manager.getTransform(svcMsg.getBsRspCnvMsgID()); // 기본응답변환메시지ID명
						}
					}
				}

				// 등록된 변환이 있는 경우
				if (info != null) {
					if (logger.isInfo())
						logger.info("EAILogDAO] Masking Log Message - " + message.getEAISvcCd());

					// 변환은 등록되어 있으나 레이아웃정보가 삭제된 경우
					// 정삭적인 Case 가 아님.
					try {
						if (logPssSno == 100 || logPssSno == 300 || logPssSno == 900)
							l = info.getSourceLayout(0);
						else
							l = info.getTargetLayout();
					} catch (Exception e) {
						if (logger.isInfo())
							logger.info("EAILogDAO] Layout not set");
					}

					// Layout 에 Mask 필드가 없는 경우 SKIP 하도록 한다.
					if (l != null) {
						try {
							Item root = l.getRootItem();
							isMasking = root.existMask();
						} catch (Exception e) {
							if (logger.isWarn())
								logger.info("EAILogDAO] Check Masking field Error - " + e.getMessage());
							isMasking = false;
						}
						if (logger.isInfo())
							logger.info(
									"EAILogDAO] Message has Masking field [" + l.getName() + "][ " + isMasking + "]");
					}

					if (isMasking) {
						try {
							bizMsgStr = LogMessageUtil.makeMaskData(message, bizMsg, l, logPssSno, tgtAdptrMsgPtrnCd,
									svcTsmtUsgTp, psvItfTp);
							isMasked = true;
						} catch (Exception e) {
							if (logger.isWarn())
								logger.warn("EAILogDAO] LogMasking Error - " + e.getMessage(), e);
							isMasked = false;
						}
					} else {
						if (logger.isInfo())
							logger.info("EAILogDAO] Masking is unnecessary - Skip Masking ");

						isMasked = false;
					}
				} else {
					if (logger.isInfo())
						logger.info("EAILogDAO]  Transform Not Found - Masking Unable");
					isMasked = false;
				}
				// Masking check END
			}

//			boolean isUtf8 = isUTF8(svcTsmtUsgTp, psvItfTp, logPssSno, srcAdapterMsgEncode, tgtAdapterMsgEncode);
			// 요청 변환이 등록되지 않은 경우 또는 Masking 처리를 실패한 경우
			if (!isMasked) {
				if (bizMsg == null) {
					if (logger.isInfo())
						logger.info("EAILogDAO] Message is NULL");
					bizMsgStr = "";
				} else {
					if (logger.isInfo())
						logger.info("EAILogDAO] Message is String Type");
					bizMsgStr = bizMsg;
				}
			}

			// EAI 업무 개별부(32,000bytes)
			/**
			 * 업무데이터에 대한정의 1. biz 데이터 2. 표준전문 JSON 데이터 3. 전장표
			 */
			StringBuilder sb = new StringBuilder();
			String biz = "";
			String header = message.getStandardMessage().toFixedString(false, EncodingVar.flatEncoding);
			
			String mdclData = "";
			if (bizMsgStr == null) {
				bizMsgStr = "";
			}

			// 암호화
			/*
			Charset hexaCharset = Charset.forName("euc-kr");
			if ("Y".equalsIgnoreCase(EncryptionManager.getInstance().getEncryptYN())) {
				try {
					biz = HexaConverter.bytesToHexa(bizMsgStr.getBytes(hexaCharset));
				} catch (Exception e) {
					logger.error("EAIFileLogger] bizMsgStr encryption Error - " + e.getMessage());
				}
				try {
					header = HexaConverter.bytesToHexa(header.getBytes(hexaCharset));
				} catch (Exception e) {
					logger.error("EAIFileLogger] header encryption Error - " + e.getMessage());
				}
				try {
					mdclData = HexaConverter.bytesToHexa(mdclData.getBytes(hexaCharset));
				} catch (Exception e) {
					logger.error("EAIFileLogger] mdclData encryption Error - " + e.getMessage());
				}
			} else {
				biz = bizMsgStr;
			}	
			*/	
			
			try {
				biz = EncryptionManager.getInstance().encryptDBData(bizMsgStr);
			} catch (Exception e) {
				logger.error("EAIFileLogger] bizMsgStr encryption Error - " + e.getMessage());
				biz = bizMsgStr;
			}
			
			// 임시코드 시작
			String logType = PropManager.getInstance().getProperty("BIZ_LOG_TYPE");
			if (!StringUtils.isBlank(logType)) {
				if ("ALL".equals(logType)) {
					sb.append(header).append("|").append(biz).append("|").append(mdclData);
				} else if ("HEADER".equals(logType)) {
					sb.append(header).append("|").append("|");
				} else if ("BODY".equals(logType)) {
					sb.append("|").append(biz).append("|");
				} else if ("NONE".equals(logType)) {
					sb.append("|").append("|");
				}
			} else {
				sb.append(header).append("|").append(biz).append("|").append(mdclData);
			}
			// 임시코드 종료

			bwkData = sb.toString();

			String[] refMsgIDs = svcMsg.getRefMsgIDs();

			// 입력메시지IDS 배열은 delimiter로 구분하여 200byte 만 insert
			StringBuilder sbMsgIds = new StringBuilder();
			if (refMsgIDs != null && refMsgIDs.length > 0) {
				for (int i = 0; i < refMsgIDs.length - 1; i++) {
					sbMsgIds.append(refMsgIDs[i]).append(", ");
				}
				sbMsgIds.append(refMsgIDs[refMsgIDs.length - 1]);
				refMsgID = sbMsgIds.toString();

				if (refMsgID.getBytes().length > 200) {
					refMsgID = StringUtil.chunkString(refMsgID, 200);
				}
			}
		} // 업무데이터 로깅을 할 경우에만 END loggingBizData

		EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, message.getMsgRcvTm());

		try {
			// 1/1000초로 변경
			String msgPssTm = DatetimeUtil.getCurrentTime(message.getMsgPssTm());

			String serverName = EAIServerManager.getInstance().getLocalServerName();
			String serverGroupName = EAIServerManager.getInstance().getServerType();

			// EAI 업무 공통부(100 bytes)
			EAILogId eaiLogId = new EAILogId();
			eaiLog.setId(eaiLogId);

			// EAI업무구분코드
			eaiLogId.setEaibzwkdstcd(message.getBwkCls());
			// 메시지수신시각
			eaiLogId.setMsgdpstyms(DatetimeUtil.getCurrentTime(message.getMsgRcvTm()));
			// EAI서비스일련번호
			eaiLogId.setEaisvcserno(message.getSvcOgNo());
			// 로그처리일련번호
			eaiLogId.setLogprcssserno(String.valueOf(orglogPssSno));
			// EAI서버인스탄스명
			eaiLog.setEaisevrinstncname(serverName);

			// EAI서비스명
			eaiLog.setEaisvcname(message.getEAISvcCd());
			// 서비스시각유무
			eaiLog.setSvchmseonot(message.getSvcTmEn());
			// 서비스동기사용구분코드
			eaiLog.setSvcmotivusedstcd(message.getSvcTsmtUsgTp());
			// 서비스처리구분명
			eaiLog.setSvcprcssdsticname(message.getSvcPssTp());
			// 흐름통제라우팅명
			eaiLog.setFlowctrlroutname(message.getFlwCntlRtnNm());

			// 통합구분명
			eaiLog.setIntgradsticname(message.getUnifTp());
			// 기동서비스구분명
			eaiLog.setGstatsvcdsticname(message.getSngSvcCls());
			// 서비스처리번호
			eaiLog.setSvcprcssno(String.valueOf(message.getSvcPssSeq()));
			// 서비스전컬럼로그여부
			eaiLog.setSvcbfclmnlogyn(message.getSvcWlColLogYn());
			// 표준메시지사용여부
			eaiLog.setStndmsguseyn(message.getStdMsgUsgCls());

			// 기동시스템어댑터업무그룹명
			eaiLog.setGstatsysadptrbzwkgroupname(message.getSngSysItfTp());
			// 현재메시지ID명
			eaiLog.setPrsntmsgidname(message.getLydMsgID());
			// 응답에러코드명
			eaiLog.setRspnserrcdname(message.getRspErrCd());
			// 메시지처리시각
			eaiLog.setMsgprcssyms(msgPssTm);
			// 서버로그레벨번호
			eaiLog.setSevrloglvelno(String.valueOf(message.getSvrLogLvl()));

			// 서비스로그레벨번호
			eaiLog.setSvcloglvelno(String.valueOf(message.getSvcLogLvl()));
			// 오류EAI서비스명
			eaiLog.setErreaisvcname(message.getErrEAISvcName());
			// 요청오류변환ID명
			eaiLog.setDmnderrchngidname(message.getDmndErrChngIDName());
			// 요청에러필드명
			eaiLog.setDmnderrfldname(message.getDmndErrFldName());
			// 응답오류변환ID명
			eaiLog.setRspnserrchngidname(message.getRspnsErrChngIDName());

			// 응답에러필드명
			eaiLog.setRspnserrfldname(message.getRspnsErrFldName());
			// 수동인터페이스구분명
			eaiLog.setPsvintfacdsticname(svcMsg.getPsvItfTp());
			// 수동업무시스템명
			eaiLog.setPsvbzwksysname(svcMsg.getPsvBwkSysNm());
			// 수동시스템ID명
			eaiLog.setPsvsysidname(svcMsg.getPsvSysID());
			// 수동시스템서비스구분명
			eaiLog.setPsvsyssvcdsticname(svcMsg.getPsvSysSvcCd());

			// 수동시스템어댑터업무그룹명
			eaiLog.setPsvsysadptrbzwkgroupname(svcMsg.getPsvSysItfTp());
			// 장애극복여부
			eaiLog.setFlovryn(svcMsg.getFlOvrCls());
			// 변환여부
			eaiLog.setChngyn(svcMsg.getCnvEn());
			// 변환메시지ID명
			eaiLog.setChngmsgidname(svcMsg.getCnvMsgID());
			// 입력메시지ID명
			eaiLog.setInptmsgidname(refMsgID);

			// 기본응답메시지비교내용
			eaiLog.setBascrspnsmsgcmprctnt(svcMsg.getBsRspMsgCprVl());
			// 기본응답변환여부
			eaiLog.setBascrspnschngyn(svcMsg.getBsRspCnvEn());
			// 기본응답변환메시지ID명
			eaiLog.setBascrspnschngmsgidname(svcMsg.getBsRspCnvMsgID());
			// 오류응답메시지비교내용
			eaiLog.setErrrspnsmsgcmprctnt(svcMsg.getErrRspMsgCprVl());
			// 오류응답변환여부
			eaiLog.setErrrspnschngyn(svcMsg.getErrRspCnvEn());

			// 오류응답변환메시지ID명
			eaiLog.setErrrspnschngmsgidname(svcMsg.getErrRspCnvMsgID());
			// 다음서비스처리번호
			eaiLog.setNextsvcprcssno(String.valueOf(svcMsg.getNxtSvcPssSeq()));
			// 아웃바운드라우팅명
			eaiLog.setOutbndroutname(svcMsg.getOutbRtnNm());
			// 타임아웃값
			eaiLog.setToutval(svcMsg.getTmoVl());
			// 보상서비스처리명
			eaiLog.setCmpensvcprcssname(svcMsg.getCpnsSvcPssCd());
			// 추가업무데이터여부
			eaiLog.setSupplbzwkdatayn(apndBwkDataYn);
			// 키관리메시지내용
			eaiLog.setKeymgtmsgctnt(svcMsg.getKeyMgtMsgVl());

			// SS,SA - Send - 100
			// AA - Send - 100
			// AA - Recv - 100, 300
			// AS - 100
			String telgmDmndDstcd = message.getMapper().getSendRecvDivision(message.getStandardMessage());
			if (prop != null && ((EAIMessageKeys.SYNC_SVC.equals(svcTsmtUsgTp) && logPssSno == 100)
					|| (EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.ASYNC_SVC.equals(psvItfTp)
							&& STDMessageKeys.SEND_RECV_CD_RECV.equals(telgmDmndDstcd)
							&& (logPssSno == 100 || logPssSno == 300))
					|| (EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.ASYNC_SVC.equals(psvItfTp)
							&& STDMessageKeys.SEND_RECV_CD_SEND.equals(telgmDmndDstcd) && logPssSno == 100)
					|| (EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.SYNC_SVC.equals(psvItfTp)
							&& logPssSno == 100))) {
				eaiLog.setTrackasiskey1ctnt(prop.getProperty(com.eactive.eai.common.logger.Keys.LOG_ALT_KEY1)); // 추적보조키1내용
				eaiLog.setTrackasiskey2ctnt(prop.getProperty(com.eactive.eai.common.logger.Keys.LOG_ALT_KEY2)); // 추적보조키2내용
				eaiLog.setTrackasiskey3ctnt(prop.getProperty(com.eactive.eai.common.logger.Keys.LOG_ALT_KEY3)); // 추적보조키3내용
				eaiLog.setTrackasiskey4ctnt(prop.getProperty(com.eactive.eai.common.logger.Keys.LOG_ALT_KEY4)); // 추적보조키4내용
			}

			// EAI서비스코드의 그룹회사코드
			eaiLog.setEaigroupcodstcd(message.getGroupCoCd());
			// PGUID
			eaiLog.setPguid(message.getMapper().getOrgGuid(message.getStandardMessage()));
			// 송수신구분
			eaiLog.setTrantype(message.getTranType());
			//
			eaiLog.setRspnschngmsgtype(message.getRspnsChngMsgType());

			// log level 'E' or 'F'
			if ("E".equals(message.getRspErrCd().substring(1, 2))
					|| "F".equals(message.getRspErrCd().substring(1, 2))) {
				// EAI에러코드
				eaiLog.setEaierrcd(message.getRspErrCd());
				// EAI에러내용
				eaiLog.setEaierrctnt(StringUtil.chunkString(message.getRspErrMsg(), 1000));
			}

			// 서버그룹명
			eaiLog.setSevrgroupname(serverGroupName);
			// 업체코드
			eaiLog.setCompanycode(message.getCompanyCode());
			// 전문크기, add 20190404
			eaiLog.setSplizlength(message.getSplizLength());
			// index 60
			// add 20190404 // adapterNickName
			eaiLog.setAdptrinsticode(message.getAdptrInstiCode());

			// 거래ID
			eaiLog.setTxid(message.getTxId());
			// 참조ID
			eaiLog.setRefkey(message.getRefKey());
			// 대외업무구분코드
			eaiLog.setExtbizcd(message.getExtBizCd());
			// EAI 업무 개별부(32,000bytes)
			if (bwkData == null || bwkData.equals(""))
				bwkData = " ";
			eaiLog.setBzwkdatactnt(bwkData);
			String standardLayoutName = System.getProperty("STANDARD_LAYOUT_NAME");
			// 표준전문레이아웃 명
			eaiLog.setStdlayoutname(standardLayoutName);
			
			// clientId 로그에 추가
			String clientId = message.getClientId();
			eaiLog.setClientid(clientId);

			// client IP 로그에 추가
			String clientIp = message.getClientIp();
			eaiLog.setClientip(clientIp);

			/**
			 * CLIENT ID 있을 경우 APP, 기관정보 로그에 추가
			 * TODO: ClientVO의 경우 spring security oauth의 ClientDetails를 상속받고 있어 OAUTH가 아닌 인증의 경우에 대한 처리 추가 필요
			 */
			if(StringUtils.isNotBlank(clientId)) {
				ClientVO clientVO = OAuth2Manager.getInstance().getClientVO(clientId);
				if (clientVO != null) {
					eaiLog.setClientname(clientVO.getClientName());
					eaiLog.setOrgid(clientVO.getOrgId());
					eaiLog.setOrgname(clientVO.getOrgName());
				}
			}

			eaiLogEntityService.save(eaiLog);

		} catch (Exception e) {
			logger.error(
					"DB Logging[MASTER] Failed - " + message.getEAISvcCd() + "|" + orglogPssSno + "|"
							+ message.getSvcOgNo() + "|" + message.getMapper().getGuid(message.getStandardMessage()),
					e);

			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG001"));
		}

		// 에러로그를 별도의 테이블에 저장하도록 한다.
		if (!MessageUtil.checkRspErrCd(message.getRspErrCd())) {
			try {
				// 거래통제, 유량제어에 의한 에러는 저장하지 않도록 한다.
				if (!(EAIMessageKeys.EAI_BLOCKED_CODE.equals(message.getRspErrCd())
						|| EAIMessageKeys.EAI_INFLOW_BLOCKED_CODE.equals(message.getRspErrCd()))) {
					addErrorLog(message); // 에러로그
				}
			} catch (Exception ex) {
				logger.warn("에러로그테이블 저장 SKIP 에러발생 - " + ex.getMessage());
			}
		}

	}

	public void addErrorLog(EAIMessage message) throws DAOException {
		try {
			String serverName = EAIServerManager.getInstance().getLocalServerName();

			EAIErrorLog eaiErrorLog = (EAIErrorLog) applicationContext.getBean(RollingTable.class, EAIErrorLog.class,
					message.getMsgRcvTm());

			// EAI업무구분코드
			EAIErrorLogId eaiErrorLogId = new EAIErrorLogId();
			eaiErrorLog.setId(eaiErrorLogId);

			eaiErrorLogId.setEaibzwkdstcd(message.getBwkCls());
			// 메시지수신시각
			eaiErrorLogId.setMsgdpstyms(DatetimeUtil.getCurrentTime(message.getMsgRcvTm()));
			// EAI거래일련번호
			eaiErrorLogId.setEaisvcserno(message.getSvcOgNo());
			// 로그처리일련번호
			eaiErrorLogId.setLogprcssserno(String.valueOf(message.getLogPssSno()));

			// EAI서비스명
			eaiErrorLog.setEaisvcname(message.getEAISvcCd());
			// 응답에러코드명
			eaiErrorLog.setRspnserrcdname(message.getRspErrCd());
			// 기동시스템어댑터업무그룹명
			eaiErrorLog.setGstatsysadptrbzwkgroupname(message.getSngSysItfTp());
			// 수동시스템어댑터업무그룹명
			eaiErrorLog.setPsvsysadptrbzwkgroupname(message.getCurrentSvcMsg().getPsvSysItfTp());

			if ("E".equals(message.getRspErrCd().substring(1, 2))
					|| "F".equals(message.getRspErrCd().substring(1, 2))) {
				// EAI에러코드
				eaiErrorLog.setEaierrcd(message.getRspErrCd());
				// EAI에러내용
				eaiErrorLog.setEaierrctnt(StringUtil.chunkString(message.getRspErrMsg(), 500));
			}

			// EAI서버인스턴스명
			eaiErrorLog.setEaisevrinstncname(serverName);
			// 로깅시스템ID
			EAIServerVO eaiServerVO = EAIServerManager.getInstance().getEAIServer(serverName);
			if(eaiServerVO != null) {
				eaiErrorLog.setLgingsysid(eaiServerVO.getHostName());
			}
			// 메시지처리일시
			eaiErrorLog.setMsgprcssyms(DatetimeUtil.getCurrentTime(message.getMsgPssTm()));
			// EAI그룹회사코드
			eaiErrorLog.setEaigroupcodstcd(message.getGroupCoCd());

		} catch (Exception e) {
			logger.error("DB Logging[ERROR_LOG] Failed - " + message.getEAISvcCd() + "|" + message.getLogPssSno() + "|"
					+ message.getSvcOgNo(), e);
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003"));
		}
	}

	public void addStaticLog(StatMonitorLogVO vo) throws DAOException {
		try {
			StatLog statLog = statLogMapper.toEntity(vo);
			statLogLogger.save(statLog);
		} catch (Exception e) {
			//logger.error("DB Logging[STATIC_LOG] Failed - " + vo.toString(), e);
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003"));
		}
	}

	public void addStaticTranCdLog(StatMonitorLogVO vo) throws DAOException {
		try {
			StatTranLog statTranLog = statTranLogMapper.toEntity(vo);
			statTranLogLogger.save(statTranLog);
		} catch (Exception e) {
			//logger.error("DB Logging[STATIC_TRANCD_LOG] Failed - " + vo.toString(), e);
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003"));
		}
	}

	public void addStaticAdapterLog(StatMonitorLogVO vo) throws DAOException {
		try {
			StatAdapterLog statAdapterLog = statAdapterLogMapper.toEntity(vo);
			statAdapterLogLogger.save(statAdapterLog);
		} catch (Exception e) {
			//logger.error("DB Logging[STATIC_ADAPTER_LOG] Failed - " + vo.toString(), e);
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003"));
		}
	}

	public boolean getCheck() throws DAOException {
		return eaiServerEntityService.checkConnection();
	}
	
	private boolean checkSubLogging(String svcTsmtUsgTp, String psvItfTp, String srcAdptrMsgPtrnCd, String tgtAdptrMsgPtrnCd, int logPssSno) {
		boolean isAsyncSvc = EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && EAIMessageKeys.ASYNC_SVC.equals(psvItfTp);
		boolean isSrcStandard = com.eactive.eai.adapter.Keys.IF_SUBSTANDARD.equals(srcAdptrMsgPtrnCd);
	    
//		// SOURCE : AA : 100, 300, ELSE: 100, 400
		if(isSrcStandard && ( (isAsyncSvc && (logPssSno == 100 || logPssSno == 300)) || 
				(!isAsyncSvc && (logPssSno == 100 || logPssSno == 400)) ) ) {
			return true;
		}
		
		boolean isTgtStandard = com.eactive.eai.adapter.Keys.IF_SUBSTANDARD.equals(tgtAdptrMsgPtrnCd);
//		// TARGET : AA : 200, 400, ELSE : 200, 300
	    if (isTgtStandard && ( (isAsyncSvc && (logPssSno == 200 || logPssSno == 400)) || 
	    		(!isAsyncSvc && (logPssSno == 200 || logPssSno == 300)) ) ) {
	    	return true;
	    }
	    return false;
	}

	
        /*
	private String EncryptSafeDb(String msg) {
		PropManager propManager = PropManager.getInstance();
		String safeDbPath = propManager.getProperty("SafeDB","safedb.path");
		
		SimpleSafeDB safedb = SimpleSafeDB.getInstance();
		boolean loginResult = false;
		if(!safedb.login()) {
			loginResult = safedb.getSafeDBConfigMgr().isLoginCheck();
		}
		
		String userName = "SAFEDB";
		String tableName = "SAFEDB.POLICY";
		String columnName1 = "bzwkdatactnt";
		
		byte[] byteMsg = msg.getBytes(StandardCharsets.UTF_8); 
		byte[] encryptedBytes1 = null;
		
		try {
			encryptedBytes1 = safedb.encrypt(userName, tableName, columnName1, byteMsg);
			// System.out.println("Encrypted Data : [" + new String(encryptedBytes1) + "]");
			
			byte[] decryptedBytes1 = safedb.decrypt(userName, tableName, columnName1, encryptedBytes1);
			
		} catch (SafeDBSDKException e) {
			e.printStackTrace();
			
		}
		
		String encryptedMsg = new String(encryptedBytes1, StandardCharsets.UTF_8);
		return encryptedMsg;
	}
	*/
	
}
