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

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.eactive.eai.common.dao.DAOFactory;
import com.eactive.eai.common.property.PropGroupVO;
import com.eactive.eai.common.property.PropertyDAO;
import com.eactive.eai.common.util.StringUtil;
import com.eactive.eai.common.util.SystemUtil;
import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageInfo;
import com.eactive.eai.rms.common.combo.ComboService;
import com.eactive.eai.rms.common.combo.ComboVo;
import com.eactive.eai.rms.data.entity.onl.stdmessage.ExtendedColumnDefinitionService;
import com.eactive.eai.rms.data.entity.onl.stdmessage.StandardMessageInfoService;
import com.eactive.eai.rms.onl.common.exception.BizException;
import com.eactive.eai.rms.onl.manage.rule.transform.TransformDao;

import edu.emory.mathcs.backport.java.util.TreeSet;

@Service
@Transactional
public class StdMessageManService {
	private final Logger logger = Logger.getLogger(StdMessageManService.class);

	@Autowired
	@Qualifier("transformDao")
	private TransformDao transformDao;

	@Autowired
	private ComboService comboService;

	@Autowired
	private StdMessageUIMapper stdMessageUIMapper;

	@Autowired
	private StandardMessageInfoService standardMessageInfoService;

	@Autowired
	private ExtendedColumnDefinitionService extendedColumnDefinitionService;

	@Autowired
	private ExtendedColumnDefinitionUIMapper extendedColumnDefinitionUIMapper;

	public Page<StdMessageUI> selectList(Pageable pageable, String searchBzwkSvcKeyName, String searchEaiSvcCode,
			String searchEaiSendRecv, String searchEaiDirection) {

		Page<StandardMessageInfo> pageResult = standardMessageInfoService
				.findAll(pageable, searchBzwkSvcKeyName, searchEaiSvcCode, searchEaiSendRecv, searchEaiDirection);
		
		return pageResult.map(stdMessageUIMapper::toVo);

	}

	public List<Map<String, Object>> selectListToExcel(String searchBzwkSvcKeyName, String searchEaiSvcCode,
			String searchEaiSendRecv, String searchEaiDirection) {

		return StreamSupport
				.stream(standardMessageInfoService
						.findAll(Pageable.unpaged(), searchBzwkSvcKeyName, searchEaiSvcCode, searchEaiSendRecv,
								searchEaiDirection)
						.spliterator(), false)
				.map(s -> {
					Map<String, Object> map = new HashMap<>();
					map.put("BZWKSVCKEYNAME", s.getBzwksvckeyname());
					map.put("EAISVCNAME", s.getEaisvcname());
					map.put("EAITRANNAME", s.getEaitranname());
					map.put("EAISENDRECV", s.getEaisendrecv());
					map.put("EAIDIRECTION", s.getEaidirection());
					return map;
				})
				.collect(Collectors.toList());
	}

	public StdMessageUI selectDetail(String bzwkSvcKeyName) {
		StandardMessageInfo standardMessageInfo = standardMessageInfoService.getById(bzwkSvcKeyName);
		return stdMessageUIMapper.toVo(standardMessageInfo);
	}

	public List<ExtendedColumnDefinitionUI> selectDetailForKey() {
		return StreamSupport
				.stream(extendedColumnDefinitionService.findKeys().spliterator(), false)
				.map(extendedColumnDefinitionUIMapper::toVo)
				.collect(Collectors.toList());
	}

	public void update(Map<String, Object> paramMap, StdMessageUI stdMessageUI) {

		StandardMessageInfo standardMessageInfo = standardMessageInfoService.getById(stdMessageUI.getBzwkSvcKeyName());

		List<StdMessageItemUI> stdMessageItemUIs = stdMessageUIMapper.map(paramMap);
		stdMessageUI.setStandardMessageItems(stdMessageItemUIs);

		stdMessageUIMapper.updateEntity(stdMessageUI, standardMessageInfo);
		standardMessageInfoService.save(standardMessageInfo);
	}

	public void insert(Map<String, Object> paramMap, StdMessageUI stdMessageUI) {

		List<StdMessageItemUI> stdMessageItemUIs = stdMessageUIMapper.map(paramMap);
		stdMessageUI.setStandardMessageItems(stdMessageItemUIs);

		StandardMessageInfo standardMessageInfo = stdMessageUIMapper.toEntity(stdMessageUI);
		standardMessageInfoService.save(standardMessageInfo);
	}

	public void delete(String bzwkSvcKeyName) {
		standardMessageInfoService.deleteById(bzwkSvcKeyName);
	}

	public Map<String, List<ComboVo>> selectCombo() {

		// 전문요청구분
		List<ComboVo> listReqRes = comboService.getFromCode("REQRES_TYPE");

		// 내외부구분코드
		List<ComboVo> listStndTelgmWtinExtnlDstcd = comboService.getFromCode("STD_INOUT_TYPE");

		// EAI내외부구분코드
		List<ComboVo> listEAIStndtelgmwtinextnldstCd = comboService.getFromCode("EAI_INOUT_TYPE");

		// 취소구분코드
		List<ComboVo> listTrstdidfrCd = comboService.getFromCode("TRSTDIDFR_CD");

		Map<String, List<ComboVo>> map = new HashMap<>();

		map.put("reqResList", listReqRes);
		map.put("stndTelgmWtinExtnlDstcdList", listStndTelgmWtinExtnlDstcd);
		map.put("eaiStndtelgmwtinextnldstCdList", listEAIStndtelgmwtinextnldstCd);
		map.put("trstdidfr_CdList", listTrstdidfrCd);

		return map;

	}

	public Map<String, List<ComboVo>> selectDetailCombo() {

		// 전문요청구분
		List<ComboVo> listReqRes = comboService.getFromCode("REQRES_TYPE");

		// 내외부구분코드
		List<ComboVo> listStndTelgmWtinExtnlDstcd = comboService.getFromCode("STD_INOUT_TYPE");

		// EAI내외부구분코드
		List<ComboVo> listEAIStndtelgmwtinextnldstCd = comboService.getFromCode("EAI_INOUT_TYPE");

		// 시스템 운영환경 구분코드
		List<ComboVo> listSysOperEvirnDstcd = comboService.getFromCode("SYSTEM_TYPE");

		// 원거래 복원 여부
		List<ComboVo> listOgtranRstrYn = comboService.getFromCode("RECOVER_TYPE");

		// 채널유형코드
		List<ComboVo> listChnlDstcd = comboService.getFromCode("CHNL_DST_CD");

		// 채널상세유형코드
		List<ComboVo> listChnlDvDstcd = comboService.getFromCode("CHNL_DV_DST_CD");

		// 그룹회사코드
		List<ComboVo> listGroupCoCd = comboService.getFromCode("GROUPCOCD");

		// 복합거래요청구분코드
		List<ComboVo> listCmpstrCd = comboService.getFromCode("CMPSTR_CD");

		// 취소구분코드
		List<ComboVo> listTrstdidfrCd = comboService.getFromCode("TRSTDIDFR_CD");

		// 매체구분코드
		List<ComboVo> listMdiadstCd = comboService.getFromCode("MDIADSTCD");

		// 은행코드
		List<ComboVo> listBnkCd = comboService.getFromCode("BNKCD");

		// 입출력구분
		List<ComboVo> listIoCd = comboService.getFromCode("IO_CD");

		// 당타발구분
		List<ComboVo> listDtCd = comboService.getFromCode("DT_CD");

		// 여부(당발응답정상여부)
		List<ComboVo> listYnCd = comboService.getFromCode("YN");

		Map<String, List<ComboVo>> map = new HashMap<>();

		map.put("reqResList", listReqRes);
		map.put("stndTelgmWtinExtnlDstcdList", listStndTelgmWtinExtnlDstcd);
		map.put("eaiStndtelgmwtinextnldstCdList", listEAIStndtelgmwtinextnldstCd);
		map.put("sysOperEvirnDstcdList", listSysOperEvirnDstcd);
		map.put("ogtranRstrYnList", listOgtranRstrYn);
		map.put("chnlDstcdList", listChnlDstcd);
		map.put("chnlDvDstcdList", listChnlDvDstcd);

		map.put("groupCoCdList", listGroupCoCd);
		map.put("cmpstrCdList", listCmpstrCd);
		map.put("trstdidfr_CdList", listTrstdidfrCd);
		map.put("mdiadst_CdList", listMdiadstCd);
		map.put("bnk_CdList", listBnkCd);

		map.put("io_CdList", listIoCd);
		map.put("dt_CdList", listDtCd);
		map.put("yn_CdList", listYnCd);

		return map;

	}

	public boolean migrationToProdKbMessageService(String userId, String listMsgName, String cmDate, String cmTime)
			throws BizException, Exception {
		boolean ret = false;

		String[] msgNameList = listMsgName.split("\\&");
		String[] eaiSystemCode = new String[msgNameList.length];

		if (!SystemUtil.isDevServer() && !SystemUtil.isStagingServer()) {
			throw new BizException("해당 시스템에선 사용할 수 없습니다.");
		}
		PropertyDAO propertyDAO = (PropertyDAO) DAOFactory.newInstance().create(PropertyDAO.class);
		PropGroupVO prop = propertyDAO.getProperties("CM_CONFIG");
		if (prop == null) {
			throw new Exception("프라퍼티 정보가 없습니다. - CM_CONFIG");
		}

		int i = 0;
		boolean isDebug = logger.isDebugEnabled();
		String txtLocalPath = prop.getProperty("eaimsg.sql.path");
		String schemaId = (SystemUtil.isDevServer() ? prop.getProperty("eaimsg.sql.test.schemaId")
				: prop.getProperty("eaimsg.sql.prod.schemaId"));
		// String sysOperEvirnDstcd = SystemUtil.isDevServer() ? "S" : "O";

		StringBuilder sb = new StringBuilder();
		for (String msgName : msgNameList) {
			if (isDebug) {
				logger.debug("Start 내부표준메시지  migration To Prod (bzwkSvcKeyName=" + msgName + ")");
			}

			HashMap<String, String> paramMap = new HashMap<String, String>();
			paramMap.put("bzwkSvcKeyName", msgName);
			List<HashMap> list1 = transformDao.selectHS04ForMigration(paramMap);
			List<HashMap> list2 = transformDao.selectHS05ForMigration(paramMap);

			if (isDebug) {
				if (list1 == null) {
					logger.debug("list1 is null !");
					list1 = Collections.<HashMap>emptyList();
				} else {
					logger.debug("list1 returned count is : " + list1.size());
				}
				if (list2 == null) {
					logger.debug("list2 is null !");
					list2 = Collections.<HashMap>emptyList();
				} else {
					logger.debug("list2 returned count is : " + list2.size());
				}
			}

			for (int j = 0; j < list1.size(); j++) {
				HashMap map1 = list1.get(j);
				// DELETE
				if (j == 0) {
					sb.append(String.format(StdMessageMigQuery.MIG_DEL_HS04, schemaId, msgName)).append("\n");
				}
				// INSERT
				sb
						.append(String
								.format(StdMessageMigQuery.MIG_INS_HS04, schemaId, msgName,
										StringUtil.getNullStr(map1.get("EAISVCNAME")),
										StringUtil.getNullStr(map1.get("EAITRANNAME")),
										StringUtil.getNullStr(map1.get("EAISEVRDSTCD")),
										StringUtil.getNullStr(map1.get("MODFIMGTSTUSDSTCD")),
										StringUtil.getNullStr(map1.get("EAILASTAMNDYMS")))
								.replaceAll("' '", "''"))
						.append("\n");
				for (int k = 0; k < list2.size(); k++) {
					HashMap map2 = list2.get(k);
					String colName = StringUtil.getNullStr(map2.get("COLUMNNAME"));
					String colValue = StringUtil.getNullStr(map2.get("COLUMNVALUE"));
					// DELETE
					if (k == 0) {
						sb.append(String.format(StdMessageMigQuery.MIG_DEL_HS05, schemaId, msgName)).append("\n");
					}
					// 시스템운영환경구분코드
					if (StringUtils.equals(colName, "COMMON_sysOperEvirnDstcd")) {
						colValue = (SystemUtil.isStagingServer() ? "O" : "S");
					}
					// INSERT
					sb
							.append(String
									.format(StdMessageMigQuery.MIG_INS_HS05, schemaId, msgName, colName, colValue)
									.replaceAll("' '", "''"))
							.append("\n");
					if (StringUtils.equals(colName, "COMMON_inoPartlDstcd")) {
						eaiSystemCode[i] = colValue;
					}
				}
			}
			i++;
		}

		// 배열값의 중복제거 로직
		String eaiSystem = "";
		TreeSet tSet = new TreeSet(Arrays.asList(eaiSystemCode));
		if (tSet.size() > 1) {
			// 서버구분코드 통일되지 않을 경우 리턴
			throw new BizException("CM대상 자원의 EAI서버구분코드가 통일되지 않았습니다.");
		}
		switch (StringUtil.getNullStr(tSet.first())) {
		case "1":
			eaiSystem = "N";
		case "2":
			eaiSystem = "D";
		case "3":
			eaiSystem = "K";
		case "4":
			eaiSystem = "Z";
		case "5":
			eaiSystem = "A";
		default:
		}

		String txtLocalFullPath = txtLocalPath + cmDate + cmTime + "_" + userId + "_" + eaiSystem + "_SQL";
		BufferedWriter bw = null;
		try {
			File dir = new File(txtLocalPath);
			dir.mkdirs();

			bw = new BufferedWriter(new FileWriter(txtLocalFullPath, true));
			bw.write(sb.toString());
			bw.close();
			ret = true;
		} catch (SecurityException se) {
			logger.error("ERROR: " + se.toString());
			ret = false;
		} catch (IOException ie) {
			logger.error("ERROR: " + ie.toString());
			ret = false;
		} finally {
			if (bw != null)
				try {
					bw.close();
				} catch (Exception ee) {
					logger.error("bw close error");
				}
		}

		return ret;
	}

	public List<ExtendedColumnDefinitionUI> selectColumnList() {

		List<ExtendedColumnDefinitionUI> list = StreamSupport
				.stream(extendedColumnDefinitionService.findAll().spliterator(), false)
				.map(extendedColumnDefinitionUIMapper::toVo)
				.collect(Collectors.toList());

		list.forEach(ui -> ui.setComboList(comboService.getFromCode(ui.getComboName())));
		return list;
	}

}
