package com.eactive.eai.rms.onl.manage.serviceinfo.eaimsg;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.eactive.eai.agent.command.CommonCommand;
import com.eactive.eai.agent.eaimessage.ReloadEAIMessageCommand;
import com.eactive.eai.agent.eaimessage.RemoveEAIMessageCommand;
import com.eactive.eai.common.util.StringUtil;
import com.eactive.eai.common.util.SystemUtil;
import com.eactive.eai.rms.common.combo.ComboService;
import com.eactive.eai.rms.common.combo.ComboVo;
import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.common.datasource.DataSourceType;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.eai.rms.common.login.SessionManager;
import com.eactive.eai.rms.common.spring.BaseController;
import com.eactive.eai.rms.common.spring.LocaleMessage;
import com.eactive.eai.rms.common.util.CommonUtil;
import com.eactive.eai.rms.common.util.IpUtil;
import com.eactive.eai.rms.common.vo.GridResponse;
import com.eactive.eai.rms.data.entity.onl.eaimsg.EAIMessageUISearch;
import com.eactive.eai.rms.onl.common.exception.EMSRuntimeException;
import com.eactive.eai.rms.onl.loader.service.HistoryService;
import com.eactive.eai.rms.onl.loader.service.TransactionLoaderService;
import com.eactive.eai.rms.onl.manage.adapter.adapter.AdapterManService;
import com.eactive.eai.rms.onl.manage.adapter.adapter.ui.AdapterGroupUI;
import com.eactive.eai.rms.onl.manage.serviceinfo.eaimsg.ui.EAIMessageUI;
import com.eactive.eai.rms.onl.manage.serviceinfo.eaimsg.ui.ServiceMessageUI;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

@Controller
public class EaiMsgController extends BaseController {

	@Autowired
	private EaiMsgManService service;

	@Autowired
	private ComboService comboService;

	@Autowired
	private AdapterManService adapterManService;

	@Autowired
	private HistoryService historyService;

	@Autowired
	private TransactionLoaderService loaderService;

	@Autowired
	private MonitoringContext monitoringContext;

	@Autowired
	private LocaleMessage localeMessage;

	@Autowired
	private ObjectMapper objectMapper;

	@GetMapping(value = "/onl/admin/service/eaiMsgMan.view")
	public String view() {
		return "/onl/admin/service/eaiMsgMan";
	}

	@GetMapping(value = "/onl/admin/service/eaiMsgMan.view", params = "cmd=DETAIL")
	public String viewDetail() {
		return "/onl/admin/service/eaiMsgManDetail";
	}

	@GetMapping(value = "/onl/admin/service/eaiMsgMan.view", params = "cmd=SVC")
	public String viewSvc() {
		return "/onl/admin/service/eaiMsgManSvc";
	}
	
	@GetMapping(value = "/onl/admin/service/eaiMsgMan.view", params = "cmd=POPUP CALENDAR")
	public String viewPopupCalendar() {
		return "/onl/admin/service/eaiMsgManPopupCalendar";
	}
	
	@GetMapping(value = "/onl/admin/service/eaiMsgMan.view", params = "cmd=DETAILPOPUP")
	public String viewDetailPopup() {
		return "/onl/admin/service/eaiMsgManDetailpopup";
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=LIST")
	public ResponseEntity<GridResponse<EAIMessageUI>> selectList(EAIMessageUISearch eaiMessageUISearch,
			Pageable pageable, String sortname,  String sortorder) {
		Page<EAIMessageUI> page = service.selectList(eaiMessageUISearch, pageable, sortname, sortorder);
		return ResponseEntity.ok(new GridResponse<>(page));
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=DETAIL")
	public ResponseEntity<EAIMessageUI> selectDetail(String eaiSvcName) {
		EAIMessageUI eaiMessageUI = service.selectDetail(eaiSvcName);
		return ResponseEntity.ok(eaiMessageUI);
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=INSERT")
	public ResponseEntity<Void> insert(EAIMessageUI eaiMessageUI) throws Exception {
		service.insert(eaiMessageUI);
		CommonCommand command = new CommonCommand(ReloadEAIMessageCommand.class.getName(),
				eaiMessageUI.getEaiSvcName());
		agentUtilService.broadcast(command);
		return ResponseEntity.ok().build();
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=UPDATE")
	public ResponseEntity<Void> update(EAIMessageUI eaiMessageUI) throws Exception {

		service.update(eaiMessageUI);
		CommonCommand command = new CommonCommand(ReloadEAIMessageCommand.class.getName(),
				eaiMessageUI.getEaiSvcName());
		agentUtilService.broadcast(command);
		return ResponseEntity.ok().build();
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=CHANGE_TRANTYPE")
	public ResponseEntity<Void> updateTranType(String eaiSvcName, String tranType) throws Exception {

		service.updateTranType(eaiSvcName, tranType);
		CommonCommand command = new CommonCommand(ReloadEAIMessageCommand.class.getName(), eaiSvcName);
		agentUtilService.broadcast(command);
		return ResponseEntity.ok().build();
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=DELETE")
	public ResponseEntity<Void> delete(String eaiSvcName) throws Exception {
		service.delete(eaiSvcName);
		CommonCommand command = new CommonCommand(RemoveEAIMessageCommand.class.getName(), eaiSvcName);
		agentUtilService.broadcast(command);
		return ResponseEntity.ok().build();
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=DETAIL_SVC")
	public ResponseEntity<ServiceMessageUI> selectDetailSvc(String eaiSvcName, Integer svcPrcssNo) {
		ServiceMessageUI map = service.selectDetailSvc(eaiSvcName, svcPrcssNo);
		return ResponseEntity.ok(map);
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=DETAIL_SVC_ALL")
	public ResponseEntity<EAIMessageUI> selectDetailSvcAll(String eaiSvcName) {
		return selectDetail(eaiSvcName);
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=DELETE_LIST")
	public ResponseEntity<Map<String, String>> deleteMulti(
			@RequestParam(name = "eaiSvcName", defaultValue = "") List<String> eaiSvcNames) throws Exception {

		service.deleteAll(eaiSvcNames);

		CommonCommand command = new CommonCommand("com.eactive.eai.agent.eaimessage.RemoveEAIMessageListCommand",
				new Vector<>(eaiSvcNames));

		HashMap<String, Object> returnMap = agentUtilService.broadcast(command);

		String message = "총" + eaiSvcNames.size() + "건을 삭제하였습니다";
		message += CommonUtil.getMapString(returnMap, true);

		return ResponseEntity.ok(Collections.singletonMap("message", message));

	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=INSERT_SVC")
	public ResponseEntity<Void> insertSvc(ServiceMessageUI serviceMessageUI) throws Exception {

		service.insertSvc(serviceMessageUI);
		CommonCommand command = new CommonCommand(ReloadEAIMessageCommand.class.getName(),
				serviceMessageUI.getEaiSvcName());
		agentUtilService.broadcast(command);

		return ResponseEntity.ok().build();
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=UPDATE_SVC")
	public ResponseEntity<Void> updateSvc(ServiceMessageUI serviceMessageUI) throws Exception {

		service.updateSvc(serviceMessageUI);
		CommonCommand command = new CommonCommand(ReloadEAIMessageCommand.class.getName(),
				serviceMessageUI.getEaiSvcName());
		agentUtilService.broadcast(command);
		return ResponseEntity.ok().build();

	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=DELETE_SVC")
	public ResponseEntity<Void> deleteSVC(ServiceMessageUI serviceMessageUI) throws Exception {
		service.deleteSvc(serviceMessageUI);
		CommonCommand command = new CommonCommand(ReloadEAIMessageCommand.class.getName(),
				serviceMessageUI.getEaiSvcName());
		agentUtilService.broadcast(command);
		return ResponseEntity.ok().build();
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=LIST_INIT")
	public ResponseEntity<Map<String, Object>> listInitCombo(String codeGroupArr) {

		List<String> codeGroupList = Optional
				.ofNullable(codeGroupArr)
				.map(a -> Arrays.asList(a.split(",")))
				.orElse(new ArrayList<>());

		List<Map<String, Object>> listCombo = comboService.getFromCodeByGroups(codeGroupList);

		List<ComboVo> listFlowControl = comboService.getFromRouting("F");
		List<ComboVo> listInoutTypeCd = comboService.getFromCode("INOUT_TYPE");// EAI서버구분코드

		Map<String, Object> resultMap = new HashMap<>();

		resultMap.put("list", listCombo);
		resultMap.put("listFlowControl", listFlowControl);
		resultMap.put("listInoutType", listInoutTypeCd);

		return ResponseEntity.ok(resultMap);
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=LIST_INIT_COMBO")
	public ResponseEntity<Map<String, Object>> initCombo() {

		List<ComboVo> listBiz = comboService.getFromBusinessType();
		List<ComboVo> listSvcTimeExist = comboService.getFromCode("SVC_TIME_EXIST");// 업무운영 시간여부
		List<ComboVo> listSvcSameTimeType = comboService.getFromCode("SVC_SAME_TIME_TYPE");// 인터페이스 사용유형
		List<ComboVo> listSvcProcessType = comboService.getFromCode("SVC_PROCESS_TYPE");// 서비스 처리유형
		List<ComboVo> listFlowControl = comboService.getFromRouting("F");// Flow Control 라우팅명
		List<ComboVo> listUnitType = comboService.getFromCode("UNIT_TYPE");// 거래유형
		List<ComboVo> listInternalExternalDvcd = comboService.getFromCode("EAI_INOUT_TYPE");// 보조 로그 사용여부
		List<AdapterGroupUI> listInAdapter = adapterManService.selectListComboForAdptrIoDstcd("IN");// 기동 인터페이스 유형
		List<ComboVo> listServerLogLevel = comboService.getFromCode("SERVER_LOG_LEVEL");// 서버로그 레벨
		List<ComboVo> listSvcLogLevel = comboService.getFromCode("SVC_LOG_LEVEL");// 서비스 로그레벨
		List<ComboVo> listSim = comboService.getFromCode("SIM_YN");// 시뮬레이터 여부

		// he02
		List<ComboVo> listPsvItfType = comboService.getFromCode("PSV_ITF_TYPE");// 수동 인터페이스 유형
		// 수동업무구분 <==같이
		// List listPsvId = comboService.selectListComboForTable("TSEAISY01",
		// "SYSDOMNNAME","SYSDOMNDESC");//수동시스템ID
		List<AdapterGroupUI> listOuAdapter = adapterManService.selectListComboForAdptrIoDstcd("OU");// 수동시스템인터페이스유형
		List<ComboVo> listFailOverCls = comboService.getFromCode("FAIL_OVER_CLS");// FailOver여부
		List<ComboVo> listCnvExistNot = comboService.getFromCode("CNV_EXIST_NOT");// 변환유무
		List<ComboVo> listBsRspCnvExistNot = comboService.getFromCode("BS_RSP_CNV_EXIST_NOT");// 기본응답변환유무
		List<ComboVo> listErrRspCnvExistNot = comboService.getFromCode("ERR_RSP_CNV_EXIST_NOT");// 오류응답변환유무
		List<ComboVo> listOutBoundRouting = comboService.getFromRouting();

		List<ComboVo> listAddDelYn = comboService.getFromCode("ADD_DEL_YN");// 추가삭제여부
		List<ComboVo> listHdrCtlCd = comboService.getFromCode("HDR_CTL_CD");// 헤더제어구분코드

		List<ComboVo> listInoutTypeCd = comboService.getFromCode("INOUT_TYPE");// EAI서버구분코드
		List<ComboVo> listGroupCoCd = comboService.getFromCode("EAIGROUPCOCD");// EAI그룹회사코드
		List<ComboVo> listTranType = comboService.getFromCode("TRAN_TYPE");// 거래구분코드
		List<ComboVo> listTranTypeDev = comboService.getFromCode("TRAN_TYPE_DEV");// 거래구분코드 개발자용
		List<ComboVo> listUseYn = comboService.getFromCode("USE_YN");// 사용여부 USE_YN

		Map<String, Object> resultMap = new HashMap<>();
		// he01
		resultMap.put("bizRows", listBiz);
		resultMap.put("svcTimeExistRows", listSvcTimeExist);
		resultMap.put("svcSameTimeTypeRows", listSvcSameTimeType);
		resultMap.put("svcProcessTypeRows", listSvcProcessType);
		resultMap.put("flowControlRows", listFlowControl);
		resultMap.put("unitTypeRows", listUnitType);
		resultMap.put("internalExternalDvcdRows", listInternalExternalDvcd);
		resultMap.put("inAdapterRows", listInAdapter);
		resultMap.put("serverLogLevelRows", listServerLogLevel);
		resultMap.put("svcLogLevelRows", listSvcLogLevel);
		resultMap.put("simRows", listSim);
		// he02
		resultMap.put("psvItfTypeRows", listPsvItfType);
		resultMap.put("ouAdapterRows", listOuAdapter);
		resultMap.put("failOverClsRows", listFailOverCls);
		resultMap.put("cnvExistNotRows", listCnvExistNot);
		resultMap.put("bsRspCnvExistNotRows", listBsRspCnvExistNot);
		resultMap.put("errRspCnvExistNotRows", listErrRspCnvExistNot);
		resultMap.put("outBoundRoutingRows", listOutBoundRouting);
		resultMap.put("addDelYnRows", listAddDelYn);
		resultMap.put("hdrCtlCdRows", listHdrCtlCd);

		resultMap.put("inoutTypeRows", listInoutTypeCd);
		resultMap.put("groupCoCdRows", listGroupCoCd);
		resultMap.put("tranTypeRows", listTranType);
		resultMap.put("tranTypeDevRows", listTranTypeDev);
		resultMap.put("useYnRows", listUseYn);

		return ResponseEntity.ok(resultMap);
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=LIST_SVC")
	public ResponseEntity<Map<String, Object>> selectListSvc(String eaiSvcName) throws Exception {

		List<ServiceMessageUI> list = service.selectListSvc(eaiSvcName);
		Map<String, Object> resultMap = new HashMap<>();
		resultMap.put("rows", list);

		return ResponseEntity.ok(resultMap);
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=INITIALIZES")
	public ResponseEntity<Map<String, Object>> initializes() throws Exception {
		CommonCommand command = new CommonCommand(ReloadEAIMessageCommand.class.getName(), "ALL");

		Map<String, Object> returnMap = agentUtilService.broadcast(command);

		Map<String, Object> map = new HashMap<>();
		map.put("message", CommonUtil.getMapString(returnMap, true));

		return ResponseEntity.ok(map);
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=INITIALIZE")
	public ResponseEntity<Map<String, Object>> initialize(String eaiSvcName) throws Exception {
		CommonCommand command = new CommonCommand(ReloadEAIMessageCommand.class.getName(), eaiSvcName);
		Map<String, Object> returnMap = agentUtilService.broadcast(command);

		Map<String, Object> map = new HashMap<>();
		map.put("message", CommonUtil.getMapString(returnMap, true));

		return ResponseEntity.ok(map);
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=LIST_INITIALIZE")
	public ResponseEntity<Map<String, Object>> listInitialize(String chkItems) throws Exception {
		CommonCommand command = new CommonCommand(ReloadEAIMessageCommand.class.getName(), chkItems);
		Map<String, Object> returnMap = agentUtilService.broadcast(command);
		Map<String, Object> map = new HashMap<>();
		map.put("message", CommonUtil.getMapString(returnMap, true));

		return ResponseEntity.ok(map);
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.excel", params = "cmd=LIST_GRID_TO_EXCEL")
	public ModelAndView listGridToExcel(EAIMessageUISearch eaiMessageUISearch,
			@RequestParam Map<String, Object> paramMap) throws JsonProcessingException {
		Map<String, Object> resultMap = new HashMap<>();

		String[] headers = objectMapper.readValue((String) paramMap.get("header"), String[].class);
		String[] headerTitles = objectMapper.readValue((String) paramMap.get("headerTitle"), String[].class);

		Map<String, Object>[] datas = service.selectListToExcel(eaiMessageUISearch);

		HashMap<String, Object>[] lmerge = null;
		String merge = (String) paramMap.get("merge");
		if (merge != null) {
			lmerge = objectMapper.readValue(merge, new TypeReference<HashMap<String, Object>[]>() {
			});
		}

		resultMap.put("headers", headers);
		resultMap.put("headerTitles", headerTitles);
		resultMap.put("datas", datas);
		resultMap.put("fileName", paramMap.get("fileName"));
		resultMap.put("merge", lmerge);
		return new ModelAndView("excelView", resultMap);
	}

	@PostMapping(value = "/onl/admin/service/eaiMsgMan.json", params = "cmd=CLONETOPROD")
	public ModelAndView cloneToProdByEms(HttpServletRequest request, @RequestParam Map<String, Object> paramMap)
			throws Exception {
		if (SystemUtil.isProdServer()) {
			throw new EMSRuntimeException("only support dev, stage server");
		}

		HashMap<String, Object> resultMap = new HashMap<>();
		String userId = SessionManager.getUserId(request);
		String serviceKey = SessionManager.getServiceTypeKey(request);
		String cmTitle = MapUtils.getString(paramMap, "CmTitle", "Deploy Interface/Layout/LayoutMap");
		String cmDate = StringUtil.getNullStr(paramMap.get("CmDate"));
		String cmTime = StringUtil.getNullStr(paramMap.get("CmTime"));
		String listSvcName = StringUtil.getNullStr(paramMap.get("ListSvcName"));
		String[] eaiSvcNames = listSvcName.split("\\,");
		String downloadPath = monitoringContext.getStringProperty(MonitoringContext.IOMAP_DOWNLOAD_PATH);
		downloadPath = StringUtils.removeEnd(downloadPath, File.separator) + File.separator + serviceKey
				+ File.separator;
		String targetName = monitoringContext.getStringProperty(MonitoringContext.IOMAP_DEPLOY_TARGET_NAME);
		String targetUrl = monitoringContext.getStringProperty(MonitoringContext.IOMAP_DEPLOY_TARGET_URL);
		targetUrl = StringUtils.removeEnd(targetUrl, "/");

		String userIp = IpUtil.getClientIp(request);

		if (logger.isInfoEnabled()) {
			logger.info("-------------------------------------------");
			logger.info("userId=" + userId);
			logger.info("userIp=" + userIp);
			logger.info("serviceKey=" + serviceKey);
			logger.info("cmDate=" + cmDate);
			logger.info("cmTime=" + cmTime);
			logger.info("listSvcName=" + listSvcName);
			logger.info("downloadPath=" + downloadPath);
			logger.info("targetName=" + targetName); // 스테이징, 운영서버
			logger.info("targetUrl=" + targetUrl); // http://127.0.0.1:20100
			logger.info("-------------------------------------------");
		}

		DataSourceType dt = DataSourceTypeManager.getDataSourceType(serviceKey);
		String items = "";

		for (String svcName : eaiSvcNames) {
			// 0. 서브 배포 목록 확보
			HashMap<String, ArrayList<HashMap<String, String>>> listMap = historyService
					.userHistoryListByInterface(dt, svcName);

			if (listMap != null && listMap.size() > 0) {
				// 1. 파일 생성
				try {
					loaderService.makeDataFiles(dt, downloadPath, listMap);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
					throw new EMSRuntimeException("Make Datafile error:" + e.getMessage());
				}

				// 2. 파일 배포
				try {
					if (StringUtils.isBlank(targetUrl)) {
						throw new EMSRuntimeException("Set EMS property:" + MonitoringContext.IOMAP_DEPLOY_TARGET_URL);
					}

					String url = targetUrl + "/monitoring/loader.do";
					loaderService.deployDataToTargetSystem(url, downloadPath, listMap, serviceKey);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
					throw new EMSRuntimeException(
							"Deploy to target System(" + targetName + ") error:" + e.getMessage());
				}

				items += historyService.parseSimple(serviceKey, "", listMap);
			}
		}

		// 3. 데이터 적용 또는 스케쥴 등록
		try {
			String url = targetUrl + "/monitoring/loader.do";
			loaderService.scheduleDeployDataApply(url, userId, userIp, serviceKey, cmTitle, cmDate, cmTime, items);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new EMSRuntimeException("Apply DeployData or Apply Schedule error:" + e.getMessage());
		}

		resultMap.put("message", localeMessage.getMessage("ruleDeploy.msg4"));

		ModelAndView modelAndView = new ModelAndView("jsonView", resultMap);
		return modelAndView;
	}


}
