package com.eactive.eai.rms.onl.manage.rule.transform2;

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

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

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.MediaType;
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.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.IpUtil;
import com.eactive.eai.rms.common.vo.GridResponse;
import com.eactive.eai.rms.common.vo.SimpleResponse;
import com.eactive.eai.rms.onl.common.exception.BizException;
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.rule.layout.LayoutManService;
import com.eactive.eai.rms.onl.manage.rule.layout.ui.LayoutItemUI;
import com.eactive.eai.rms.onl.manage.rule.layout.ui.LayoutUI;
import com.eactive.eai.rms.onl.manage.rule.layout.ui.LayoutUISearch;
import com.eactive.eai.rms.onl.manage.rule.transform2.ui.TransformSourceResultUI;
import com.eactive.eai.rms.onl.manage.rule.transform2.ui.TransformUI;

@Controller
public class Transform2Controller extends BaseController {

	@Autowired
	private LocaleMessage localeMessage;

	@Autowired
	private Transform2Service service;

	@Autowired
	private ComboService comboService;

	@Autowired
	private HistoryService historyService;

	@Autowired
	private TransactionLoaderService loaderService;

	@Autowired
	private MonitoringContext monitoringContext;

	@Autowired
	private LayoutManService layoutManService;

	@GetMapping(value = "/onl/admin/rule/transform2/transform2Man.view")
	public String view() {
		return "/onl/admin/rule/transform2/transform2Man";
	}

	@GetMapping(value = "/onl/admin/rule/transform2/transform2Man.view", params = "cmd=DETAIL")
	public String detailView() {
		return "/onl/admin/rule/transform2/transform2ManDetail";
	}

	@GetMapping(value = "/onl/admin/rule/transform2/transform2Man.view", params = "cmd=DETAIL*POPUP")
	public String detailPopupView() {
		return "/onl/admin/rule/transform2/transform2ManDetailPopup";
	}

	@GetMapping(value = "/onl/admin/rule/transform2/transform2Man.view", params = "cmd=LAYOUT")
	public String layoutView() {
		return "/onl/admin/rule/transform2/transform2ManLayout";
	}

	@GetMapping(value = "/onl/admin/rule/transform2/transform2Man.view", params = "cmd=NEW")
	public String newView() {
		return "/onl/admin/rule/transform2/transform2ManNew";
	}

	@GetMapping(value = "/onl/admin/rule/transform2/transform2Man.view", params = "cmd=POPUP CALENDAR")
	public String popupCalendarView() {
		return "/onl/admin/rule/transform2/transform2ManPopupCalendar";
	}
	
	@GetMapping(value = "/onl/admin/rule/transform2/transform2Man.view", params = "cmd=API_POPUP")
	public String apiPopupView() {
		return "/onl/admin/rule/transform2/transform2ManApiPopup";
	}

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=LIST_INIT_COMBO")
	public ResponseEntity<Map<String, Object>> initCombo(HttpServletRequest request, String eaiSvcName, String cnvsnName) {

		String roleId = SessionManager.getRoleIdString(request);
		String isAdmin = "N";
		if (roleId.indexOf("admin") > -1) {
			// admin 일경우
			isAdmin = "Y";
		}

		List<ComboVo> listFunction = comboService.getFromFunction();

		List<ComboVo> listTransform = comboService.getFromTransform(eaiSvcName, cnvsnName);

		List<ComboVo> listCnvsnType = comboService.getFromCode("CNVSN_TYPE");
		List<ComboVo> listSvrDstcd = comboService.getFromCode("INOUT_TYPE");
		List<ComboVo> listUseYn = comboService.getFromCode("USE_YN");

		Map<String, Object> resultMap = new HashMap<>();
		resultMap.put("functionRows", listFunction);
		resultMap.put("transformRows", listTransform);
		resultMap.put("cnvsnType", listCnvsnType);
		resultMap.put("svrDstcd", listSvrDstcd);
		resultMap.put("isAdmin", isAdmin);
		resultMap.put("useYnRows", listUseYn);

		return ResponseEntity.ok(resultMap);
	}

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=LIST_EAISVCNAME_COMBO")
	public ResponseEntity<Map<String, Object>> eaiSvcNameCombo(HttpServletRequest request,
			HttpServletResponse response) {

		List<ComboVo> listCnvsnType = comboService.getFromCode("CNVSN_TYPE");
		List<ComboVo> listInoutTypeCd = comboService.getFromCode("INOUT_TYPE");
		List<ComboVo> listUseYn = comboService.getFromCode("USE_YN");

		Map<String, Object> resultMap = new HashMap<>();
		resultMap.put("cnvsnTypeRows", listCnvsnType);
		resultMap.put("inoutTypeRows", listInoutTypeCd);
		resultMap.put("useYnRows", listUseYn);

		return ResponseEntity.ok(resultMap);
	}

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=LIST_LAYOUT_ITEM")
	public ResponseEntity<GridResponse<LayoutItemUI>> listLayoutItem(String loutName) {
		List<LayoutItemUI> list = service.selectLayoutItems(loutName);
		return ResponseEntity.ok(new GridResponse<>(list));
	}

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=LIST")
	public ResponseEntity<GridResponse<TransformUI>> list(Pageable pageable, String searchCnvsnName,
			String searchCnvsnDesc, String searchBizCode, String searchIfSvcCd) {

		Page<TransformUI> page = service
				.selectList(pageable, searchCnvsnName, searchCnvsnDesc, searchBizCode, searchIfSvcCd);
		return ResponseEntity.ok(new GridResponse<>(page));
	}

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=INSERT")
	public ResponseEntity<Void> insert(TransformUI transformUI) {

		service.insert(transformUI);
		CommonCommand
				.builder()
				.name(CommonCommand.RELOAD_TRANSFORM_COMMAND)
				.args(transformUI.getCnvsnName())
				.build()
				.broadcast(agentUtilService);

		String eaiSvcName = transformUI.getEaiSvcName();
		if (eaiSvcName != null && !"".equals(eaiSvcName)) {
			CommonCommand
					.builder()
					.name(CommonCommand.RELOAD_EAI_MESSAGE_COMMAND)
					.args(eaiSvcName)
					.build()
					.broadcast(agentUtilService);
		}

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

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=DELETE")
	public ResponseEntity<Void> delete(String cnvsnName, String eaiSvcName, String cnvsnType) {

		service.delete(cnvsnName, eaiSvcName, cnvsnType);
		CommonCommand
				.builder()
				.name(CommonCommand.REMOVE_TRANSFORM_COMMAND)
				.args(cnvsnName)
				.build()
				.broadcast(agentUtilService);

		if (eaiSvcName != null && !"".equals(eaiSvcName)) {

			CommonCommand
					.builder()
					.name(CommonCommand.RELOAD_EAI_MESSAGE_COMMAND)
					.args(eaiSvcName)
					.build()
					.broadcast(agentUtilService);

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

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=DELETE_LIST")
	public ResponseEntity<SimpleResponse> deleteMulti(String[] cnvsnNames, String[] eaiSvcNames, String[] cnvsnTypes) {
		String message = "";

		int idx = 0;
		for (String cnvsnName : cnvsnNames) {
			if(StringUtils.isBlank(eaiSvcNames[idx])){
				service.delete(cnvsnName, "", cnvsnTypes[idx]);
			} else {
				service.delete(cnvsnName, eaiSvcNames[idx], cnvsnTypes[idx]);
			}
			
			CommonCommand
					.builder()
					.name(CommonCommand.REMOVE_TRANSFORM_COMMAND)
					.args(cnvsnName)
					.build()
					.broadcast(agentUtilService);
			if (eaiSvcNames[idx] != null && !"".equals(eaiSvcNames[idx])) {
				CommonCommand
						.builder()
						.name(CommonCommand.RELOAD_EAI_MESSAGE_COMMAND)
						.args(eaiSvcNames[idx])
						.build()
						.broadcast(agentUtilService);
			}
			idx++;
		}

		message = "총" + idx + "건을 삭제하였습니다";
		return ResponseEntity.ok(SimpleResponse.of(message));
	}

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=LIST_TRANSFORM_SOURCE_RESULT")
	public ResponseEntity<GridResponse<TransformSourceResultUI>> transformSourceResult(String cnvsnName) {
		List<TransformSourceResultUI> list = service.selectTransformSourceResult(cnvsnName);
		return ResponseEntity.ok(new GridResponse<>(list));
	}

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=LIST_TRANSFORM_ITEM")
	public ResponseEntity<GridResponse<LayoutItemUI>> transformItem(String cnvsnName, String loutName,
			String srcLayoutName) {
		List<LayoutItemUI> list = service.selectTransformItems(cnvsnName, loutName, srcLayoutName);
		return ResponseEntity.ok(new GridResponse<>(list));
	}

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=UPDATE")
	public ResponseEntity<Void> update(TransformUI transformUI) {
		service.transaction(transformUI);

		CommonCommand
				.builder()
				.name(CommonCommand.RELOAD_TRANSFORM_COMMAND)
				.args(transformUI.getCnvsnName())
				.build()
				.broadcast(agentUtilService);
		if (StringUtils.isNotBlank(transformUI.getEaiSvcName())) {
			CommonCommand
					.builder()
					.name(CommonCommand.RELOAD_EAI_MESSAGE_COMMAND)
					.args(transformUI.getEaiSvcName())
					.build()
					.broadcast(agentUtilService);
		}

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

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=INITIALIZES")
	public ResponseEntity<SimpleResponse> initializes() {
		String message = CommonCommand
				.builder()
				.name(CommonCommand.RELOAD_TRANSFORM_COMMAND)
				.args("ALL")
				.build()
				.broadcast(agentUtilService)
				.getMessage(true);

		return ResponseEntity.ok(SimpleResponse.of(message));
	}

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=INITIALIZE")
	public ResponseEntity<SimpleResponse> initialize(String cnvsnName) {
		String message = CommonCommand
				.builder()
				.name(CommonCommand.RELOAD_TRANSFORM_COMMAND)
				.args(cnvsnName)
				.build()
				.broadcast(agentUtilService)
				.getMessage(true);

		return ResponseEntity.ok(SimpleResponse.of(message));
	}

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=LIST_INITIALIZE")
	public ResponseEntity<SimpleResponse> listInitialize(String[] chkItems) {

		Vector<String> vec = new Vector<>();
		for (String chkItem : chkItems) {
			vec.add(chkItem);
		}

		String message = CommonCommand
				.builder()
				.name(CommonCommand.RELOAD_TRANSFORM_LIST_COMMAND)
				.args(vec)
				.build()
				.broadcast(agentUtilService)
				.getMessage(true);

		return ResponseEntity.ok(SimpleResponse.of(message));
	}

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=LIST_LAYOUT")
	public ResponseEntity<GridResponse<LayoutUI>> selectLoutList(Pageable pageable, LayoutUISearch layoutUISearch) {
		Page<LayoutUI> page = layoutManService.selectList(pageable, layoutUISearch);
		return ResponseEntity.ok(new GridResponse<>(page));
	}

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=CHANGE_EXPORT")
	public ModelAndView exportData(HttpServletRequest request, @RequestParam HashMap<String, Object> paramMap)
			throws Exception {
		HashMap<String, Object> resultMap = new HashMap<>();
		String userId = SessionManager.getUserId(request);
		if (!SystemUtil.isDevServer()) {
			throw new EMSRuntimeException("only support dev server ");
		}
		try {
			String cnvsnNames = (String) paramMap.get("cnvsnNames");
			// 취약점소스 수정 2020.08.25
			String[] arrCnvsnNames = null;
			if (cnvsnNames != null) {
				arrCnvsnNames = cnvsnNames.split("\\,");
				paramMap.put("userId", userId);
				paramMap.put("arrCnvsnNames", arrCnvsnNames);

				service.exportData(paramMap);
			}

			resultMap.put("message", "전송이 성공적으로 완료되었습니다");
		} catch (BizException be) {
			throw new Exception(be.getMessage());
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw new Exception(localeMessage.getString("errors.checklog"));
		}

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

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.excel", params = "cmd=LIST_GRID_TO_EXCEL")
	public ModelAndView listGridToExcel(String searchCnvsnName, String searchCnvsnDesc, String searchBizCode,
			String searchIfSvcCd) throws Exception {
		HashMap<String, Object> resultMap = new HashMap<>();
		List<Map<String, Object>> datas = service
				.selectListToExcel(searchCnvsnName, searchCnvsnDesc, searchBizCode, searchIfSvcCd);
		resultMap.put("datas", datas);

		return new ModelAndView("excelView", resultMap);
	}

	@PostMapping(value = "/onl/admin/rule/transform2/transform2Man.json", params = "cmd=CLONETOPROD")
	public ModelAndView cloneToProd(HttpServletRequest request, @RequestParam HashMap<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 Layout Mapping");
		String cmDate = StringUtil.getNullStr(paramMap.get("CmDate"));
		String cmTime = StringUtil.getNullStr(paramMap.get("CmTime"));
		String listTransformName = StringUtil.getNullStr(paramMap.get("ListTransformName"));
		String[] transformNames = listTransformName.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("listTransformName=" + listTransformName);
			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 = "";

		// 0. 서브 배포 목록 확보
		HashMap<String, ArrayList<HashMap<String, String>>> listMap = historyService
				.userHistoryListByTransform(dt, transformNames);

		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;
	}
}
