package com.eactive.eai.batch.job.jobHandle;

//import com.eactive.eai.batch.running.BatchRunningJobManager;
//import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.batch.job.jobModule.Component.JobComponentService;

import com.eactive.eai.batch.common.CalendarUtil;
import com.eactive.eai.batch.common.LogUtil;
import com.eactive.eai.batch.doc.BatchDoc;
import com.eactive.eai.batch.rule.nodeinfo.NodeInfoManager;
import com.eactive.eai.batch.rule.nodeinfo.NodeInfoVO;
import com.eactive.eai.batch.scheduler.SchedulerMessageManager;
import com.eactive.eai.common.util.Logger;

public class JobFinishHandler
{
    protected Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
    private String logHeader = "";

	private BatchDoc batchMsgDoc;
	private String gUUID     = "";
	private String subUUID     = "";
	private String gRuleCode = "";

	public JobFinishHandler(BatchDoc batchMsgDoc) {
		this.batchMsgDoc = batchMsgDoc;
		this.gUUID       = batchMsgDoc.getBatchMsg().getHeader().getUUID();
		this.subUUID     = batchMsgDoc.getBatchMsg().getBody().getSubUUID();
		this.gRuleCode   = batchMsgDoc.getBatchMsg().getHeader().getRuleCode();
		
		logger = batchMsgDoc.getLogger();
		
		logHeader = "["+ batchMsgDoc.getBatchMsg().getHeader().getUUID() +" / "+
		                 batchMsgDoc.getBatchMsg().getHeader().getProcessCode() +" / "+
		                 batchMsgDoc.getBatchMsg().getHeader().getInstitutionName() +" / "+
		                 batchMsgDoc.getBatchMsg().getHeader().getProcessType() +" / "+
		                 batchMsgDoc.getBatchMsg().getHeader().getFileName() +" / "+
		                 batchMsgDoc.getBatchMsg().getHeader().getRuleCode() +"] ";
	}


	//FlowController 관련 JPD 에서 오류 발생시 오류를 처리한다.
	public void handleErrorEnd(String errMsg) {
		try {
			//1. 에러메시지 설정
			if (errMsg != null && !errMsg.equals("")) {
				if (!batchMsgDoc.getBatchMsg().getBody().getErrorMsg().equals("")) {
					errMsg += "\n caused by..." + batchMsgDoc.getBatchMsg().getBody().getErrorMsg();
				}
				batchMsgDoc.getBatchMsg().getBody().setErrorMsg(errMsg);
			}
			//2. 에러종료 단계 수행
			executeFlowErrorEndPhase();

			//3. 작업 진행정보 제거
			deleteProcessingInfo();

			//4. 에러종료 DB Log
            batchMsgDoc.getBatchMsg().getBody().setPhaseEndTime(CalendarUtil.getCurrentTimeNoDash());
			LogUtil.setErrorLog(batchMsgDoc, batchMsgDoc.getBatchMsg().getBody().getErrorMsg());

		} catch (Exception e) {
			logger.error("[handleErrorEnd]처리 중 오류 발생 -" + e.getMessage(),e );
		}
	}

	public void handleSuccessEnd() {
		try {
			//1. 정상종료 단계 수행
			executeFlowSuccessEndPhase();
			//2. 작업 진행정보 제거
			deleteProcessingInfo();

			//3. 정상종료 DB Log
            batchMsgDoc.getBatchMsg().getBody().setPhaseEndTime(CalendarUtil.getCurrentTimeNoDash());
			LogUtil.setLog(batchMsgDoc);
			LogUtil.setEndLog(batchMsgDoc);

		} catch (Exception e) {
			logger.error("[handleSuccessEnd]처리 중 오류 발생 -" + e.getStackTrace() );
		}
	}

	/**
	 * Exception을 throw 하지 않는다.
	 */
	private void executeFlowErrorEndPhase() {
		logger.info("{"+logHeader+"}"+" ▷ 에러종료 단계("+ FlowController.PHASECODE_ERROR_END +") 수행......");
        NodeInfoVO nodeInfo = null;
		try {
			nodeInfo = NodeInfoManager.getInstance().getNodeInfo(gRuleCode, FlowController.PHASECODE_ERROR_END);
		} catch (Exception e) {
			logger.error(e.getLocalizedMessage(), e);
		}
		//해당 RuleCode에 에러종료 단계가 없으면 디폴트 에러종료 단계 설정
		try {
			if (nodeInfo == null) {
				logger.info("{"+logHeader+"}"+ "  => 해당 Rule 정보에 에러종료 단계 없음. 디폴트 에러종료 단계를 설정함.");
				nodeInfo = new NodeInfoVO();
				nodeInfo.setRuleCode(gRuleCode);
				nodeInfo.setPhaseCode(FlowController.PHASECODE_ERROR_END);
				nodeInfo.setPhaseType(FlowController.PHASECODE_ERROR_END);
				nodeInfo.setDesc("디폴트 에러종료 단계");
				nodeInfo.setLengthField(0);
				nodeInfo.setTelegramID("");
				nodeInfo.setFlowComp("com.eactive.eai.batch.job.jobModule.Component.EEND");
			}
			setPhaseInfoToBatchMsgDoc(nodeInfo);
			executeFlowPhase(nodeInfo.getFlowComp());
		} catch (Exception e) {
			logger.error(e.getLocalizedMessage(), e);
		}
	}

	/**
	 * Exception을 throw 하지 않는다.
	 */
	private void executeFlowSuccessEndPhase()  {
		logger.info("{"+"logHeader"+"}"+" ▷ 정상종료 단계("+ FlowController.PHASECODE_NORMAL_END +") 수행......");
        NodeInfoVO nodeInfo = null;
		try {
			nodeInfo = NodeInfoManager.getInstance().getNodeInfo(gRuleCode, FlowController.PHASECODE_NORMAL_END);
		} catch (Exception e) {
			logger.error(e.getLocalizedMessage(), e);
		}
		//해당 RuleCode에 에러종료 단계가 없으면 디폴트 에러종료 단계 설정
		try {
			if (nodeInfo == null) {
				logger.info("{"+"logHeader"+"}"+" 해당 Rule 정보에 정상종료 단계 없음. 디폴트 정상종료 단계를 설정함.");
				nodeInfo = new NodeInfoVO();
				nodeInfo.setRuleCode(gRuleCode);
				nodeInfo.setPhaseCode(FlowController.PHASECODE_NORMAL_END);
				nodeInfo.setPhaseType(FlowController.PHASECODE_NORMAL_END);
				nodeInfo.setDesc("디폴트 정상종료 단계");
				nodeInfo.setLengthField(0);
				nodeInfo.setTelegramID("");
				nodeInfo.setFlowComp("com.eactive.eai.batch.job.jobModule.Component.END");
			}
			setPhaseInfoToBatchMsgDoc(nodeInfo);
			executeFlowPhase(nodeInfo.getFlowComp());
		} catch (Exception e) {
			logger.error(e.getLocalizedMessage(), e);
		}
	}

	private void setPhaseInfoToBatchMsgDoc(NodeInfoVO nodeInfo) {
        //body 쪽 단계정보 설정
        batchMsgDoc.getBatchMsg().getBody().setFlowPhaseCode(nodeInfo.getPhaseCode());
        batchMsgDoc.getBatchMsg().getBody().setPhaseType(nodeInfo.getPhaseType());
        //Phase 쪽 단계정보 설정
		batchMsgDoc.getBatchMsg().getPhaseinfo().setRuleCode          (nodeInfo.getRuleCode());
		batchMsgDoc.getBatchMsg().getPhaseinfo().setPhaseCode         (nodeInfo.getPhaseCode());
		batchMsgDoc.getBatchMsg().getPhaseinfo().setPhaseType         (nodeInfo.getPhaseType());
		batchMsgDoc.getBatchMsg().getPhaseinfo().setFlowClassName     (nodeInfo.getFlowComp());
		batchMsgDoc.getBatchMsg().getPhaseinfo().setLengthFieldIndex  (nodeInfo.getLengthField());
		batchMsgDoc.getBatchMsg().getPhaseinfo().setLengthTelegramID  (nodeInfo.getTelegramID());
		batchMsgDoc.getBatchMsg().getPhaseinfo().setLengthClassName   ("");
		batchMsgDoc.getBatchMsg().getPhaseinfo().setLengthMsgCode     ("");
		batchMsgDoc.getBatchMsg().getPhaseinfo().setPhaseSeq          ("");
		batchMsgDoc.getBatchMsg().getPhaseinfo().setPhaseTelegramID   ("");
		batchMsgDoc.getBatchMsg().getPhaseinfo().setPhaseClassName    ("");
		batchMsgDoc.getBatchMsg().getPhaseinfo().setPhaseMsgCode      ("");
		batchMsgDoc.getBatchMsg().getPhaseinfo().setTelegramTypeValue ("");
		batchMsgDoc.getBatchMsg().getPhaseinfo().setBizCodeValue      ("");
		batchMsgDoc.getBatchMsg().getPhaseinfo().setControlCodeValue  ("");
		batchMsgDoc.getBatchMsg().getPhaseinfo().setResponseCodeValue ("");
	}

	private void executeFlowPhase(String className) throws Exception {
		JobComponentService phaseExecuteObj = (JobComponentService) Class.forName(className).newInstance();
		phaseExecuteObj.setEAIBatchMessage(batchMsgDoc);

		//해당 클래스를 수행
		logger.info("{"+"logHeader"+"}   => ############################ ClassName: [" + className + "] ############################");
		batchMsgDoc = phaseExecuteObj.execute();
	}

	private void deleteProcessingInfo() throws Exception {
		logger.info("{"+logHeader+"} ▷ JobProcessData 에서 해당 UUID 정보 삭제... [UUID: "+ gUUID +"]" );
        JobProcessData.getInstance().delBatchStageData(gUUID);

        logger.info("{"+logHeader+"} ▷ Schedule Processing 테이블 (TSEAIBS04) 에서 해당 UUID 정보 삭제... [UUID: "+ gUUID +"]");
        SchedulerMessageManager.getInstance().deleteJobFromProcessing(gUUID, subUUID);
	}
}
