package com.eactive.eai.common.inflow;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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.inflow.loader.InflowControlGroupLoader;
import com.eactive.eai.common.inflow.loader.InflowControlGroupMappingLoader;
import com.eactive.eai.common.inflow.loader.InflowControlLoader;
import com.eactive.eai.common.inflow.loader.InflowControlLogLogger;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.data.entity.onl.inflow.InflowControl;
import com.eactive.eai.data.entity.onl.inflow.InflowControlGroup;
import com.eactive.eai.data.entity.onl.inflow.InflowControlGroupMapping;
import com.eactive.eai.data.entity.onl.inflow.InflowControlLog;
import com.eactive.eai.data.entity.onl.inflow.InflowControlLogId;

@Service
@Transactional
public class InflowControlDAO extends BaseDAO {

	private static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);

	@Autowired
	private InflowControlLoader inflowControlLoader;

	@Autowired
	private InflowControlLogLogger inflowControlLogLogger;

	@Autowired
	private InflowControlGroupLoader inflowControlGroupLoader;

	@Autowired
	private InflowControlGroupMappingLoader inflowControlGroupMappingLoader;

	// -------------------------------------------------------------------------
	// Enum 기반 범용 메서드 — type 코드를 직접 노출하지 않음
	// -------------------------------------------------------------------------

	public List<InflowTargetVO> getInflowList(InflowType type) throws DAOException {
		return getInflowList(type.code());
	}

	public Map<String, InflowTargetVO> getInflowMap(InflowType type, String name) throws DAOException {
		return getInflowMap(type.code(), name);
	}

	// -------------------------------------------------------------------------
	// 기존 명명 메서드 — enum 기반 메서드로 위임
	// -------------------------------------------------------------------------

	public List<InflowTargetVO> getInflowAdapterList() throws DAOException {
		return getInflowList(InflowType.ADAPTER);
	}

	public List<InflowTargetVO> getInflowInterfaceList() throws DAOException {
		return getInflowList(InflowType.INTERFACE);
	}

	public Map<String, InflowTargetVO> getInflowTargetByAdater(String name) throws DAOException {
		return getInflowMap(InflowType.ADAPTER, name);
	}

	public Map<String, InflowTargetVO> getInflowTargetByInterface(String name) throws DAOException {
		return getInflowMap(InflowType.INTERFACE, name);
	}

	private List<InflowTargetVO> getInflowList(String type) throws DAOException {
		try {
			Iterable<InflowControl> inflowControls = inflowControlLoader.findByConditions(type, "");
			List<InflowTargetVO> targetList = new ArrayList<>();
			logger.info("[ @@ Load InflowControl Configuration - starting >>>>>>>>>>>>>>>>> ]");

			for (InflowControl inflowControl : inflowControls) {
				InflowTargetVO vo = new InflowTargetVO();
				vo.setName(inflowControl.getId().getName());
				vo.setThreshold(inflowControl.getThreshold());
				vo.setThresholdPerSecond(inflowControl.getThresholdpersecond());
				vo.setThresholdTimeUnit(inflowControl.getThresholdtimeunit());
				vo.setActivate(!"0".equals(inflowControl.getUseyn()));
				targetList.add(vo);
			}
			logger.info("[>>Load InflowControl Configuration - ended ]");
			return targetList;
		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
		}
	}

	private Map<String, InflowTargetVO> getInflowMap(String type, String name) throws DAOException {
		try {
			Iterable<InflowControl> inflowControls = inflowControlLoader.findByConditions(type, name);
			Map<String, InflowTargetVO> targetList = new HashMap<>();
			logger.info("[ @@ Load InflowControl getInflowMap Configuration - starting >>>>>>>>>>>>>>>>> ]");

			for (InflowControl inflowControl : inflowControls) {
				InflowTargetVO vo = new InflowTargetVO();
				vo.setName(inflowControl.getId().getName());
				vo.setThreshold(inflowControl.getThreshold() == null ? 0 : inflowControl.getThreshold());
				vo.setThresholdPerSecond(
						inflowControl.getThresholdpersecond() == null ? 0 : inflowControl.getThresholdpersecond());
				vo.setThresholdTimeUnit(inflowControl.getThresholdtimeunit());
				vo.setActivate(!"0".equals(inflowControl.getUseyn()));
				targetList.put(vo.getName(), vo);
			}
			logger.info("[>>Load InflowControl getInflowMap Configuration - ended ]");
			return targetList;
		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
		}
	}

	/**
	 * 1. 기능 : 유량제어 로그를 INSERT하는 메서드 2. 처리 개요 : 파라미터의 코드, 메시지를 테이블에 INSERT한다. - 3.
	 * 주의사항
	 *
	 * @param EAIBzwkDstcd      EAI업무구분코드
	 * @param MsgDpstYMS        메시지수신일시
	 * @param EAISvcSerno       EAI서비스일련번호
	 * @param EAISevrInstncName EAI서버인스턴스명
	 * @param EAISvcName        EAI서비스명
	 * @param EAIOsidInstiCd    EAI대외기관코드
	 * @exception DAOException JDBC 관련 오류(SQLException)
	 **/
	// bzwkDstcd + msgDpstYMS + eAISvcSerno

//	String bzwkDstcd, String msgDpstYMS, String eAISvcSerno,
//	 String eAISevrInstncName, String eAISvcName, String adapterGroupName, 
//	 long limitPerSecond, long limit, String timeUnit
	public void addInflowServicetLog(String bzwkDstcd, String msgDpstYMS, String eAISvcSerno, String eAISevrInstncName,
			String eAISvcName, String adapterGroupName, long limitPerSecond, long limit, String timeUnit)
			throws DAOException {
		try {
			InflowControlLog inflowControlLog = new InflowControlLog();
			InflowControlLogId id = new InflowControlLogId();

			id.setEaibzwkdstcd(bzwkDstcd);
			id.setMsgdpstyms(msgDpstYMS);
			id.setEaisvcserno(eAISvcSerno);

			inflowControlLog.setId(id);
			inflowControlLog.setEaisevrinstncname(eAISevrInstncName);
			inflowControlLog.setEaisvcname(eAISvcName);
			inflowControlLog.setAdptrbzwkgroupname(adapterGroupName);
			inflowControlLog.setThresholdpersecond((int) limitPerSecond);
			inflowControlLog.setThreshold((int) limit);
			inflowControlLog.setThresholdtimeunit(timeUnit);

			inflowControlLogLogger.save(inflowControlLog);

		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
		}
	}

	// ==================== 그룹 관련 메서드 ====================

	/**
	 * 활성화된 유량제어 그룹 목록 조회
	 */
	public List<InflowGroupVO> getInflowGroupList() throws DAOException {
		try {
			Iterable<InflowControlGroup> groups = inflowControlGroupLoader.findActiveGroups();
			List<InflowGroupVO> groupList = new ArrayList<>();
			logger.info("[ @@ Load InflowControlGroup Configuration - starting >>>>>>>>>>>>>>>>> ]");

			for (InflowControlGroup group : groups) {
				InflowGroupVO vo = convertToGroupVO(group);
				// 그룹에 속한 인터페이스 목록 조회
				Iterable<InflowControlGroupMapping> mappings = inflowControlGroupMappingLoader.findActiveByGroupId(group.getGroupId());
				for (InflowControlGroupMapping mapping : mappings) {
					vo.addInterface(mapping.getInterfaceId());
				}
				groupList.add(vo);
			}
			logger.info("[>>Load InflowControlGroup Configuration - ended. count=" + groupList.size() + " ]");
			return groupList;
		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
		}
	}

	/**
	 * 인터페이스ID → 그룹ID 매핑 조회
	 */
	public Map<String, String> getInterfaceToGroupMap() throws DAOException {
		try {
			Iterable<InflowControlGroupMapping> mappings = inflowControlGroupMappingLoader.findActiveMappings();
			Map<String, String> interfaceToGroupMap = new HashMap<>();
			logger.info("[ @@ Load InterfaceToGroupMap Configuration - starting >>>>>>>>>>>>>>>>> ]");

			for (InflowControlGroupMapping mapping : mappings) {
				interfaceToGroupMap.put(mapping.getInterfaceId(), mapping.getGroupId());
			}
			logger.info("[>>Load InterfaceToGroupMap Configuration - ended. count=" + interfaceToGroupMap.size() + " ]");
			return interfaceToGroupMap;
		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
		}
	}

	/**
	 * 특정 그룹 조회
	 */
	public Map<String, InflowGroupVO> getInflowTargetByGroup(String groupId) throws DAOException {
		try {
			Iterable<InflowControlGroup> groups = inflowControlGroupLoader.findByConditions(groupId);
			Map<String, InflowGroupVO> groupMap = new HashMap<>();
			logger.info("[ @@ Load InflowControlGroup getInflowTargetByGroup Configuration - starting >>>>>>>>>>>>>>>>> ]");

			for (InflowControlGroup group : groups) {
				InflowGroupVO vo = convertToGroupVO(group);
				// 그룹에 속한 인터페이스 목록 조회
				Iterable<InflowControlGroupMapping> mappings = inflowControlGroupMappingLoader.findActiveByGroupId(group.getGroupId());
				for (InflowControlGroupMapping mapping : mappings) {
					vo.addInterface(mapping.getInterfaceId());
				}
				groupMap.put(vo.getGroupId(), vo);
			}
			logger.info("[>>Load InflowControlGroup getInflowTargetByGroup Configuration - ended ]");
			return groupMap;
		} catch (Exception e) {
			throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
		}
	}

	/**
	 * Entity → VO 변환
	 */
	private InflowGroupVO convertToGroupVO(InflowControlGroup group) {
		InflowGroupVO vo = new InflowGroupVO();
		vo.setGroupId(group.getGroupId());
		vo.setGroupName(group.getGroupName());
		vo.setThreshold(group.getThreshold() != null ? group.getThreshold() : 0);
		vo.setThresholdPerSecond(group.getThresholdPerSecond() != null ? group.getThresholdPerSecond() : 0);
		vo.setThresholdTimeUnit(group.getThresholdTimeUnit());
		vo.setActivate(!"0".equals(group.getUseYn()));
		return vo;
	}

}