package com.eactive.eai.common.stdmessage;

import java.util.HashMap;
import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.eactive.eai.common.dao.BaseDAO;
import com.eactive.eai.common.dao.DAOException;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.message.EAIMessage;
import com.eactive.eai.common.message.EAIMessageManager;
import com.eactive.eai.common.stdmessage.loader.StandardMessageInfoLoader;
import com.eactive.eai.common.stdmessage.loader.StandardMessageRestoreService;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageInfo;
import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageItem;
import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageRestore;
import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageRestoreId;
import com.eactive.eai.message.StandardMessage;
import com.eactive.eai.message.manager.StandardMessageManager;
import com.eactive.eai.message.parser.ReaderType;
import com.eactive.eai.message.parser.StandardReader;
import com.eactive.eai.message.service.InterfaceMapper;

@Service
@Transactional
public class STDMessageDAO extends BaseDAO {
	private static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);

	@Autowired
	private StandardMessageInfoLoader standardMessageInfoLoader;

	@Autowired
	private StandardMessageRestoreService standardMessageRestoreService;

	public HashMap<String, StandardMessage> getAllSTDMessages() throws DAOException {
		HashMap<String, StandardMessage> all = new HashMap<>();

		StandardMessageManager standardManager = StandardMessageManager.getInstance();
		StandardMessage vo = null;
		InterfaceMapper mapper = standardManager.getMapper();

		try {
			List<StandardMessageInfo> list = standardMessageInfoLoader.findAll();
			for (StandardMessageInfo info : list) {
				vo = standardManager.getStandardMessage();
				vo.setServiceKey(info.getBzwksvckeyname());
				vo.setEaiSvcCd(info.getEaisvcname());
				// TODO
				// to be defined...
//				mapper.setInterfaceId(vo, info.getEaitranname());
				mapper.setSendRecvDivision(vo, info.getEaisendrecv()); // S | R
				mapper.setInExDivision(vo, info.getEaidirection()); // 1 | 2
				List<StandardMessageItem> items = info.getStandardMessageItems();
				for (StandardMessageItem item : items) {
					vo.setData(item.getId().getColumnname(), item.getColumnvalue());
				}
				all.put(vo.getServiceKey(), vo);
			}
			return all;
		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICKE102"), e);
		}
	}

	public StandardMessage getSTDMessage(String serviceKey) throws DAOException {
		StandardMessageManager standardManager = StandardMessageManager.getInstance();
		try {
			Optional<StandardMessageInfo> optional = standardMessageInfoLoader.findById(serviceKey);
			if (optional.isPresent()) {
				StandardMessageInfo info = optional.get();
				StandardMessage vo = standardManager.getStandardMessage();
				vo.setServiceKey(info.getBzwksvckeyname());

				InterfaceMapper mapper = standardManager.getMapper();
				mapper.setInterfaceId(vo, info.getEaitranname());
				mapper.setSendRecvDivision(vo, info.getEaisendrecv()); // S | R
				mapper.setInExDivision(vo, info.getEaidirection()); // 1 | 2

				List<StandardMessageItem> items = info.getStandardMessageItems();
				for (StandardMessageItem item : items) {
					vo.setData(item.getId().getColumnname(), item.getColumnvalue());
				}
				return vo;
			} else {
				throw new DAOException("RECEAICKE110");
			}
		} catch (DAOException e) {
			throw e;
		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICKE111"));
		}
	}

	// --------------------------------------------------------------------
	// STD 표준메시지헤더 복원 관련 Methods
	// --------------------------------------------------------------------

	// 내부표준헤더 복원정보를 저장
	public void addRestoreMessage(String applCd, String traceKey, String flatMessage) throws DAOException {

		try {
			StandardMessageRestore entity = new StandardMessageRestore();
			StandardMessageRestoreId id = new StandardMessageRestoreId();
			id.setNwuapplcd(applCd);
			id.setKeymgtmsgctnt(traceKey);
			entity.setId(id);
			entity.setMsghdrctnt(flatMessage);
			standardMessageRestoreService.save(entity);
		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICKE118"));
		}
	}

	public void addRestoreSTDMessage(String applCd, String keyMgtMsgCtnt, StandardMessage stdmessage)
			throws DAOException {
		try {
			addRestoreMessage(applCd, keyMgtMsgCtnt, stdmessage.toFixedString(false));
		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICKE118"));
		}
	}

	public void updateRestoreMessage(String applCd, String traceKey, String flatMessage) throws DAOException {
		try {
			StandardMessageRestoreId id = new StandardMessageRestoreId();
			id.setNwuapplcd(applCd);
			id.setKeymgtmsgctnt(traceKey);

			Optional<StandardMessageRestore> optional = standardMessageRestoreService.findById(id);
			if (optional.isPresent()) {
				StandardMessageRestore entity = optional.get();
				entity.setMsghdrctnt(flatMessage);
			} else {
				StandardMessageRestore entity = new StandardMessageRestore();
				entity.setId(id);
				entity.setMsghdrctnt(flatMessage);
				standardMessageRestoreService.save(entity);
			}
		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICKE118"));
		} finally {
			this.disconnect();
		}
	}

	// 내부표준헤더 복원정보를 저장
	public void updateRestoreSTDMessage(String applCd, String keyMgtMsgCtnt, StandardMessage stdmessage)
			throws DAOException {
		try {
			updateRestoreMessage(applCd, keyMgtMsgCtnt, stdmessage.toFixedString(false));
		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICKE118"));
		}
	}

	public StandardMessage getRestoreSTDMessage(String applCd, String keyMgtMsgCtnt) throws DAOException {
		StandardMessageManager standardManager = StandardMessageManager.getInstance();
		try {
			StandardMessage standardMessage = new StandardMessage();

			StandardMessageRestoreId id = new StandardMessageRestoreId();
			id.setNwuapplcd(applCd);
			id.setKeymgtmsgctnt(keyMgtMsgCtnt);

			Optional<StandardMessageRestore> optional = standardMessageRestoreService.findById(id);
			if (optional.isPresent()) {
				StandardMessageRestore entity = optional.get();
				String headerString = entity.getMsghdrctnt();
				StandardReader parser = standardManager.getReader(ReaderType.FLAT);
				if (parser == null) {
					throw new Exception("STDMessageParser not found - " + ReaderType.FLAT);
				}
				parser.parse(standardMessage, headerString);
				return standardMessage;
			} else {
				throw new Exception("Can not find stored StandardMessage [applCd=" + applCd + ", keyMgtMsgCtnt="
						+ keyMgtMsgCtnt + "]");
			}
		} catch (DAOException e) {
			throw e;
		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICKE111"));
		}
	}

	public void deleteRestoreSTDMessage(String applCd, String keyMgtMsgCtnt) throws DAOException {
		try {
			StandardMessageRestoreId id = new StandardMessageRestoreId();
			id.setNwuapplcd(applCd);
			id.setKeymgtmsgctnt(keyMgtMsgCtnt);
			standardMessageRestoreService.deleteById(id);
		} catch (Exception e) {
			try {
				this.conn.rollback();
			} catch (Exception ex) {
				logger.error("rollback error", ex);
			}
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICKE114"));
		}
	}

	public String getRestoreMessage(String applCd, String keyMgtMsgCtnt) throws DAOException {
		try {
			StandardMessageRestoreId id = new StandardMessageRestoreId();
			id.setNwuapplcd(applCd);
			id.setKeymgtmsgctnt(keyMgtMsgCtnt);

			Optional<StandardMessageRestore> optional = standardMessageRestoreService.findById(id);
			if (optional.isPresent()) {
				StandardMessageRestore entity = optional.get();
				String headerString = entity.getMsghdrctnt();
				return headerString;
			} else {
				throw new Exception("Can not find stored StandardMessage [applCd=" + applCd + ", keyMgtMsgCtnt="
						+ keyMgtMsgCtnt + "]");
			}
		} catch (DAOException e) {
			throw e;
		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICKE111"));
		}
	}
	
	// jwhong 추가
	public StandardMessageInfo getSTDMsgByPath(String apiFullPath) throws DAOException {
	    Optional<StandardMessageInfo> optional = standardMessageInfoLoader.findByApiFullPath(apiFullPath);
	    return optional.orElseThrow(() -> new DAOException("해당 full path의 TSEAIHS04 에 데이터가 없습니다."));
	}

	// Path Variable 처리를 위한 Method/FullURL 베이스 처리.
	public HashMap<String, STDMsgInfoAddOnVO> getAllStdMsgInfos() throws DAOException {
		HashMap<String, STDMsgInfoAddOnVO> apiInfo = new HashMap<>();
		
		EAIMessageManager eaiManager = EAIMessageManager.getInstance();
		EAIMessage eaiMsg = null;
		STDMsgInfoAddOnVO vo = null;
		try {
			List<StandardMessageInfo> list = standardMessageInfoLoader.findAll();
			for (StandardMessageInfo info : list) {
				eaiMsg = eaiManager.getEAIMessage(info.getEaisvcname());
				vo = new STDMsgInfoAddOnVO();
				vo.setBzwksvckeyname(info.getBzwksvckeyname());
				vo.setEaiSvcCd(info.getEaisvcname());
				vo.setApiFullPath(info.getApifullpath());
				vo.setAdapterGroupName(eaiMsg.getSngSysItfTp());
				apiInfo.put(vo.getApiFullPath(), vo);
			}
			return apiInfo;
		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICKE102"), e);
		}
	}
	
	public STDMsgInfoAddOnVO getUrlStdMsgInfo(String apiFullPath) throws DAOException {
		EAIMessageManager eaiManager = EAIMessageManager.getInstance();
		EAIMessage eaiMsg = null;
		STDMsgInfoAddOnVO vo = null;
		try {
			Optional<StandardMessageInfo> optional = standardMessageInfoLoader.findByApiFullPath(apiFullPath);
			if (optional.isPresent()) {
				StandardMessageInfo info = optional.get();
				eaiMsg = eaiManager.getEAIMessage(info.getEaisvcname());
				vo = new STDMsgInfoAddOnVO();
				vo.setBzwksvckeyname(info.getBzwksvckeyname());
				vo.setEaiSvcCd(info.getEaisvcname());
				vo.setApiFullPath(info.getApifullpath());
				vo.setAdapterGroupName(eaiMsg.getSngSysItfTp());
			}
			return vo;
		} catch (Exception e) {
			throw new DAOException("RECEAICKE110");
		}
	}

	public String getApiFullPath(String serviceKey) throws DAOException {
		try {
		    Optional<StandardMessageInfo> optional = standardMessageInfoLoader.findById(serviceKey);
			if (optional.isPresent()) {
				StandardMessageInfo info = optional.get();
				return info.getApifullpath();
			} else {
				throw new DAOException("RECEAICKE110");
			}
		} catch (DAOException e) {
			throw e;
		} catch(Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICKE111"));
		}
	}

}
