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

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;

import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
import com.eactive.eai.rms.common.datasource.DataSourceType;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.eai.rms.common.util.CommonUtil;
import com.eactive.eai.rms.onl.dashboard.service.Dashboard2RepositoryService;


public class ItsmDashErrorLogServiceJob implements Job {
	private static final Logger logger = Logger.getLogger(ItsmDashErrorLogServiceJob.class);
	private transient static MonitoringContext monitoringContext;
	
    @Autowired
    @Qualifier("dashboard2RepositoryService")
    private static Dashboard2RepositoryService dashboard2Repository;
    
	private static DashboardTargetService dashboardTargetService;
	
	//모니터링 프라퍼티 필수등록 : timeout_error_codes (타임아웃 에러코드), biz_error_codes (업무에러코드) 
	
    @Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
    	
    	if(logger.isInfoEnabled()) logger.info("START ItsmDashErrorLogServiceJob");

   		ApplicationContext appContext = null;
   		try {
   			appContext = (ApplicationContext)context.getScheduler().getContext().get("applicationContext");
   			dashboard2Repository = (Dashboard2RepositoryService)appContext.getBean("dashboard2RepositoryService");
   			dashboardTargetService = (DashboardTargetService)appContext.getBean("DashboardTargetService");
   			monitoringContext    = (MonitoringContext)appContext.getBean("monitoringContext");	
   			
   		} catch (SchedulerException e) {
   			logger.error("applicationContext get module error",e);
   			return ;
   		}  
   		
   		try {
   			
   			int errorInterval = monitoringContext.getIntProperty(MonitoringContext.ITSM_ERROR_INTERVAL, 10);
   			
   			if(errorInterval < 0 || errorInterval > 60) {
   				throw new Exception("통합관제 제공용 에러추출 간격이 유효하지 않습니다 PROPERTY : " + errorInterval);
   			}
   			
   			/** date parameter **/
   			Calendar cal = Calendar.getInstance();
   	    	cal.setTime(new Date());
   	    	SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss");
   	    	String endDt = dateF.format(cal.getTime());
   	    	cal.add(Calendar.MINUTE, -errorInterval); // default 10분 간격
   	    	String startDt = dateF.format(cal.getTime());
   			
   	    	/** core **/
   			setMemOnlineErrorList(startDt, endDt);
   			setMemBatchErrorList(startDt, endDt);
   			
   			if(logger.isInfoEnabled()) logger.info("END ItsmDashErrorLogServiceJob");
   		} catch (Exception e) {
			logger.error("ItsmDashErrorLogServiceJob error : ",e);
		}
			
   		
   	}

    /** ONLINE **/
	private void setMemOnlineErrorList(String startDt, String endDt) throws Exception {
		
    	String bizErrorCodes = getErrorCodes(MonitoringContext.BIZ_ERROR_CODES);
		String timeOutCodes  = getErrorCodes(MonitoringContext.TIMEOUT_ERROR_CODES);
		
		String tableName = CommonUtil.getLogErrTable(endDt.substring(0,8));
		
		List<HashMap<String, String>> totalBizList  = new ArrayList<HashMap<String, String>>();
		List<HashMap<String, String>> totalTimeList = new ArrayList<HashMap<String, String>>();
		List<HashMap<String, String>> totalConnList = new ArrayList<HashMap<String, String>>();
    	
		for(DataSourceType datasource : DataSourceTypeManager.getOnlineDataSourceTypes()) {
			DataSourceContextHolder.setDataSourceType(datasource);
			
			HashMap<String, String> bizParamMap  = bizParamMap(startDt, endDt, tableName, bizErrorCodes, datasource);
			HashMap<String, String> timeParamMap = timeParamMap(startDt, endDt, tableName, timeOutCodes, datasource);
			HashMap<String, String> connParamMap = connParamMap(startDt, endDt, tableName, bizErrorCodes, timeOutCodes, datasource);
			
			List<HashMap<String, String>> bizErrorMap  = dashboardTargetService.getItsmErrorLogList(bizParamMap);
			List<HashMap<String, String>> timeErrorMap = dashboardTargetService.getItsmErrorLogList(timeParamMap);
			List<HashMap<String, String>> connErrorMap = dashboardTargetService.getItsmErrorLogList(connParamMap);
			
			setErrorMapContents(bizErrorMap, datasource);
			setErrorMapContents(timeErrorMap, datasource);
			setErrorMapContents(connErrorMap, datasource);
			
			totalBizList.addAll(bizErrorMap);
			totalTimeList.addAll(timeErrorMap);
			totalConnList.addAll(connErrorMap);
			
		}
		
		dashboard2Repository.setItsmDashBizErrorMap(timeKeyMap(totalBizList));
		dashboard2Repository.setItsmDashTimeoutErrorMap(timeKeyMap(totalTimeList));
		dashboard2Repository.setItsmDashConnectErrorMap(timeKeyMap(totalConnList));
		
	}
	
	private void setErrorMapContents(List<HashMap<String, String>> errorMapList, DataSourceType datasource) {
		
		errorMapList.forEach(map -> {
			map.put("ERRORMSG", map.get("EAIERRCTNT"));
			map.put("GROUP", datasource.getText());
			map.put("SERVICETYPE", datasource.getName());
		});
		
	}


	private HashMap<String, HashMap<String, String>> timeKeyMap(List<HashMap<String, String>> totalList) throws Exception {
		
		HashMap<String, HashMap<String, String>> totErrMap = new HashMap<String,HashMap<String, String>>();
		
		totalList.forEach(it -> {
			totErrMap.put((String)it.get("MSGDPSTYMS"), it);
		});
		
		return totErrMap;
		
	}

	private HashMap<String, String> bizParamMap(String startDt, String endDt, String tableName, String bizErrorCodes, DataSourceType d) {
		
		HashMap<String, String> paramMap = new HashMap<>();
  		paramMap.put("startDt",startDt); 
  		paramMap.put("endDt",endDt);
  		paramMap.put("tableName",tableName);
  		paramMap.put("errortype","bizerror");
  		paramMap.put("bizErrorCodes",bizErrorCodes);
    	paramMap.put("schemaId", d.getSchema());
    	
    	return paramMap;
	}
	
	private HashMap<String, String> timeParamMap(String startDt, String endDt, String tableName, String timeOutCodes, DataSourceType d) {
		
		HashMap<String, String> paramMap = new HashMap<>();
  		paramMap.put("startDt",startDt); 
  		paramMap.put("endDt",endDt);
  		paramMap.put("tableName",tableName);
  		paramMap.put("errortype","timeout");
  		paramMap.put("timeOutCodes",timeOutCodes);
    	paramMap.put("schemaId", d.getSchema());
    	
    	return paramMap;
	}
	
	private HashMap<String, String> connParamMap(String startDt, String endDt, String tableName, String bizErrorCodes, String timeOutCodes, DataSourceType d) {
		
		HashMap<String, String> paramMap = new HashMap<>();
  		paramMap.put("startDt",startDt); 
  		paramMap.put("endDt",endDt);
  		paramMap.put("tableName",tableName);
  		paramMap.put("errortype","connectError");
  		paramMap.put("bizErrorCodes",bizErrorCodes);
  		paramMap.put("timeOutCodes",timeOutCodes);
    	paramMap.put("schemaId", d.getSchema());
    	
    	return paramMap;
	}
	
	/** BATCH **/
	private void setMemBatchErrorList(String startDt, String endDt) throws Exception {
		
		/** BAT **/
		DataSourceType batDatasource = DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.BAT);
		DataSourceContextHolder.setDataSourceType(batDatasource);
		List<HashMap<String, String>> eaiError = dashboardTargetService.getEaiBatchErrorList(batchParameterMap(startDt, endDt, batDatasource));
		setErrorMapContents(eaiError, batDatasource);
		dashboard2Repository.setItsmDashFepBatchErrorList(timeKeyMap(eaiError));
		
		/** BAP **/
		DataSourceType bapDatasource = DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.BAP);
		DataSourceContextHolder.setDataSourceType(bapDatasource);
		List<HashMap<String, String>> fepError = dashboardTargetService.getFepBatchErrorList(batchParameterMap(startDt, endDt, bapDatasource));
		setErrorMapContents(fepError, bapDatasource);
		dashboard2Repository.setItsmDashFepBatchErrorList(timeKeyMap(fepError));
	}

	private HashMap<String, String> batchParameterMap(String startDt, String endDt, DataSourceType d) {
    	
    	HashMap<String, String> paramMap = new HashMap<>();
    	paramMap.put("startDt",startDt); 
  		paramMap.put("endDt",endDt);
  		paramMap.put("schemaId", d.getSchema());
  		
  		return paramMap;
	}

	private static String getErrorCodes(String propertyKey) {
    	String errorCodes = monitoringContext.getStringProperty(propertyKey, "");
		if(!"".equals(errorCodes)){
			errorCodes = "'"+errorCodes+"'";
			errorCodes = errorCodes.replaceAll(",", "','");
		}
		return errorCodes;
	}

    public static String getErrorMsg(String eaiErrcd) {
    	
    	if(eaiErrcd.equals("S9OSA001")) return " SNA Adapter 호출 오류" ;
    	if(eaiErrcd.equals("S9OSA002")) return " SNA-NR송신오류수신";
    	if(eaiErrcd.equals("S9OSP003")) return " 가용소켓연결없음";
    	if(eaiErrcd.equals("S9OHP002")) return " HTTP응답포맷오류";
    	if(eaiErrcd.equals("S9OSP010")) return " SA타임아웃";
    	if(eaiErrcd.equals("S9OSA010")) return " SA타임아웃";
    	if(eaiErrcd.equals("S9OHP030")) return " 응답변환에러" ;
    	if(eaiErrcd.equals("S9OSA888")) return " SNA G/W오류발생" ;
    	if(eaiErrcd.equals("S9OSA020")) return " 변환에러";
    	if(eaiErrcd.equals("S9OHP022")) return " 요청변환설정에러" ;
    	if(eaiErrcd.equals("S9FBF001")) return " Outbound호출에러";
    	if(eaiErrcd.equals("S9FBR001")) return " Outbound호출에러" ;
    	if(eaiErrcd.equals("S9FBR003")) return " 어댑터초기화실패" ;
    	if(eaiErrcd.equals("S9OSP020")) return " 변환중오류발생";
    	if(eaiErrcd.equals("S9OSP030")) return " 응답메세지변환오류" ;
    	if(eaiErrcd.equals("S9OCO000")) return " 송신전처리에러";
    	
    	else return " 오류 발생 , 즉시 확인조치바람";
    }
	
}