package com.eactive.eai.rms.bat.web.eims;

import java.util.HashMap;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.View;

import com.eactive.eai.agent.command.Command;
import com.eactive.eai.agent.command.CommonCommand;
import com.eactive.eai.common.util.NullControl;
import com.eactive.eai.rms.common.base.BatBaseAnnotationController;
import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.eai.rms.common.interceptor.InterceptorSkipController;
import com.eactive.eai.rms.common.mmilog.MMILogDao;
import com.eactive.eai.rms.common.util.CommonUtil;
import com.eactive.eai.rms.onl.common.util.DateUtil;

@Controller
public class EIMSBatController extends BatBaseAnnotationController implements InterceptorSkipController {

	private static final Logger logger = Logger.getLogger(EIMSBatController.class);

	@Autowired
	@Qualifier("eimsBatService")
	private EIMSBatService service;

	@Autowired
	@Qualifier("mmiLogDao")
	private MMILogDao mmiLogDao;

	private static final String RSLT_ENCODE = "UTF-8";
	private static final String RSLT_VER = "1.0";

	@RequestMapping(value = "/eimsbatcall.file", method = RequestMethod.POST)
	public View regsterBatEIMSXML(HttpServletRequest request, HttpServletResponse response) throws Exception {

		logger.debug("EIMSBatController eimsbatcall.file START =============================");
		DataSourceContextHolder.setDataSourceType(DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.BAT));

		StringBuilder frame = new StringBuilder();

		HashMap<String, String> interMap = null;
		HashMap<String, String> dbtdbmap = null;
		HashMap<String, String> filetfilemap = null;

		logger.debug("parseMessage content-Type=" + request.getContentType());
		logger.debug("parseMessage content-getParameterMap=" + request.getParameterMap());

		StringBuffer interXmlStrlog = new StringBuffer(); // INTERFACE XML 내용.

		try {
			for (String key : request.getParameterMap().keySet()) {
				
				String[] datas = request.getParameterValues(key);
				StringBuffer resultS = new StringBuffer();
				
				for (String data : datas) {
					resultS.append(data);
				}

				logger.debug("Batch receive Data " + key + "=" + resultS.toString());
				interXmlStrlog.append(resultS.toString()).append("\n");
				
				if (key.startsWith(EIMSBatConstants.FORM_INTERFACE)) {
					interMap = 
							parseOrException(resultS.toString(), EIMSBatConstants.KEYNUM_INTERFACE, EIMSBatConstants.FORM_INTERFACE);
				} else if (key.startsWith(EIMSBatConstants.FORM_DB2DB)) {
					dbtdbmap = 
							parseOrException(resultS.toString(), EIMSBatConstants.KEYNUM_DBTODB, EIMSBatConstants.FORM_DB2DB);
				} else if (key.startsWith(EIMSBatConstants.FORM_FILE2FILE)) {
					filetfilemap = 
							parseOrException(resultS.toString(), EIMSBatConstants.KEYNUM_FLIETOFILE, EIMSBatConstants.FORM_FILE2FILE);
				}
			}

			logger.debug("[ORG0] Batch interMap-->" + interMap);
			logger.debug("[ORG0] Batch dbtdbMap-->" + dbtdbmap);
			logger.debug("[ORG0] Batch filetfileMap-->" + filetfilemap);

			// ** 머지 작업이 필요함 (인터페이스와 DBtoDB와 FiletoFile에 따라 덮어씀 )
			HashMap<String, String> mergeMap = service.merge(interMap, dbtdbmap, filetfilemap);

			// ** 필수항목 체크 항목 파싱 validation 작업
			EIMSBatParser.validation(mergeMap);

			String delYn = "N";
			if (interMap.containsKey(EIMSBatConstants.DELYN)) {
				delYn = interMap.get(EIMSBatConstants.DELYN);
			}
			
			String intfId = mergeMap.get(EIMSBatConstants.INTFID);
			String batchType = mergeMap.get(EIMSBatConstants.BATCHTYPE);
			String deployResultMessage;
			
			if (delYn.equals("Y")) {
				
				service.deleteBatRegister(intfId, batchType);
				
				deployResultMessage = broadCastingAndGetMessage(new CommonCommand("com.eactive.eai.agent.scheduler.RemoveBatchInterfaceJobCommand", intfId));
				
			} else {
				
				mergeMap.put(EIMSBatConstants.DELYN, delYn.equals("N") ? "1" : "0");
				service.insertBatRegister(mergeMap);
				
				deployResultMessage = broadCastingAndGetMessage(new CommonCommand("com.eactive.eai.agent.scheduler.ReloadBatchInterfaceJobCommand", intfId));
			}

			frame.append(makeResultXml(interMap.get(EIMSBatConstants.INTFID).toString(), "True", deployResultMessage));

		} catch (Exception e) {
			
			logger.error("EIMSBatController error getMessage=" + e.getMessage(), e);
			frame.append(makeResultXml(interMap.get(EIMSBatConstants.INTFID).toString(), "False", e.getMessage()));

		}

		// ** 5-1. 최종 처리결과를 전송 함
		// MMI Log data
		HashMap<String, Object> mmiLogMap = new HashMap<String, Object>();

		try {

			DataSourceContextHolder.setDataSourceType(DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.MONITORING));
			
			mmiLogMap.put("schemaId", DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.MONITORING).getSchema());
			mmiLogMap.put("msgDpstHMS", DateUtil.getDateTimeMilliSecound());
			mmiLogMap.put("eaiSvcName", NullControl.addSpace(interMap.get(EIMSBatConstants.APPCD)));
			mmiLogMap.put("eaiSevrDstcd", "B");
			mmiLogMap.put("cnvsnName", NullControl.addSpace(interMap.get(EIMSBatConstants.BATCHTYPE)));
			mmiLogMap.put("loutName", NullControl.addSpace(interMap.get(EIMSBatConstants.INFDSTCD)));
			mmiLogMap.put("reqDstcd", NullControl.addSpace(interXmlStrlog.toString()));
			mmiLogMap.put("resDstcd", NullControl.addSpace(frame.toString()));
			mmiLogMap.put("interfaceId", NullControl.addSpace(interMap.get(EIMSBatConstants.INTFID)));
			mmiLogMap.put("deployId", NullControl.addSpace(interMap.get(EIMSBatConstants.AUTHORID)));

			mmiLogDao.insert(mmiLogMap);

		} catch (Exception e) {
			logger.error("bat log insert error : " + mmiLogMap.toString(), e);
		}

		ServletOutputStream sos = null;
		try {
			sos = response.getOutputStream();
			sos.write(frame.toString().getBytes(RSLT_ENCODE));
		} catch (Exception e) {
			logger.error(" error", e);
		} finally {
			if (sos != null)
				sos.close();
		}

		return null;

	}

	private String broadCastingAndGetMessage(Command command) {
		
		HashMap<String, Object> broadcastResult = null;
		
		try {
			broadcastResult = agentUtilService.broadcast(command);
		} catch (Exception e) {
			logger.error(e);
			return "데이터 정상배포되었으나, 엔진 동기화 중 오류가 발생했습니다. EAI배치 담당자에게 문의하세요. MSG : " + e.getMessage();
		}
		
		if(broadcastResult.entrySet().stream().allMatch(entry -> entry.getValue().equals("success"))) {
			// 모든 인스턴스 메모리 동기화에 성공
			return "정상처리되었습니다.";
		} else {
			String mapString = CommonUtil.getMapString(broadcastResult, false);
			return "데이터 정상배포되었으나, 메모리 반영 중 실패 인스턴스가 있습니다. EAI배치 담당자에게 문의하세요. MSG : " + mapString;
		}
		
	}

	private HashMap<String, String> parseOrException(String xmlString, int keynumInterface, String type) throws Exception {
		if(StringUtils.isNotBlank(xmlString)) {
			return EIMSBatParser.parseInfoMap(xmlString, keynumInterface);
		} else {
			throw new Exception("EIMS 에서 수신한 " + type + " xml이 Null입니다.");
		}
	}

	/**
	 * 결과값 XML생성 처리.
	 * 
	 * @param sysInfId
	 * @param result
	 * @param resultMessage
	 * @return
	 */
	private String makeResultXml(String sysInfId, String result, String resultMessage) {

		Document document = DocumentHelper.createDocument();

		Element root = document.addElement("Results");
		root.addAttribute("sysInfId", sysInfId);
		root.addAttribute("ver", RSLT_VER);

		root.addElement("Result").addText(result);

		root.addElement("ResultMessage").addText(resultMessage == null ? "Result Message is NULL" : resultMessage);

		return "<?xml version=\"1.0\" encoding=\"" + RSLT_ENCODE + "\"?>".concat(root.asXML());
	}

}
