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

import java.io.File;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Vector;

import javax.transaction.Transactional;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.eactive.eai.data.entity.onl.property.Prop;
import com.eactive.eai.data.entity.onl.property.PropGroup;
import com.eactive.eai.data.entity.onl.property.PropId;
import com.eactive.eai.rms.common.base.OnlBaseService;
import com.eactive.eai.rms.common.datasource.DataSourceType;
import com.eactive.eai.rms.data.entity.onl.property.PropertyGroupService;
import com.eactive.eai.rms.onl.loader.service.TransactionLoaderService;

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

@Service("ioMapLoaderService")
public class IoMapLoaderService extends OnlBaseService {

	private static final Logger logger = Logger.getLogger("DYNAMIC_LOGGER");

	@Autowired
	@Qualifier("loaderService")
	private TransactionLoaderService loaderService;

	@Autowired
	@Qualifier("ioMapLoaderDao")
	private IoMapLoaderDao dao;

	@Autowired
	private PropertyGroupService propertyGroupService;

	private static final String BUSINESS_DAY_CHANGE = "BUSINESS_DAY_CHANGE";

	/**
	 * 인터페이스 목록으로 대상서버에 인터페이스가 존재하는지 확인 하는 메소드
	 * 
	 * @param downloadPath
	 * @param apCode
	 * @param pkgNumber
	 * @return
	 */
	public boolean insertTSEAIIL02AndCheck(String downloadPath, String apCode, String pkgNumber, String name)
			throws Exception {
		String filePath = "";
		// 서버구분코드별 검색
		filePath = downloadPath + apCode + File.separator + pkgNumber + File.separator + name + File.separator;
		File file = new File(filePath);
		if (!file.exists()) {
			return false;
		}

		dao.deleteTSEAIIL02(new HashMap() {
			{
				put("pkgNumber", pkgNumber);
			}
		});
		logger.info("IL02 테이블에서 패키지 기준으로 데이터 삭제 : " + pkgNumber);
		file = new File(filePath + IoMapLoaderKey.TRANSFORM);
		File[] fileList = file.listFiles();
		if (fileList != null && fileList.length > 0) {
			// EAI서비스코드 존재 여부 체크
			for (File f : fileList) {
				if (f.isFile()) {
					HashMap map = loaderService.parse(f.getAbsolutePath());
					List<HashMap> list = (List<HashMap>) map.get("INTERFACEINFO");
					for (HashMap row : list) {
						row.put("BASCRSPNSCHNGMSGIDNAME", pkgNumber);
						row.put("ERRRSPNSCHNGMSGIDNAME", "N");
						dao.insertTSEAIIL02UPPER(row);
						logger.info("IL02 테이블에 INTREACEINFO 기준으로 데이터 적재 : " + row);
					}
				}
			}
		}
		List<HashMap> list = dao.selectInterfaceListNonExist(new HashMap<String, String>() {
			{
				put("pkgNumber", pkgNumber);
			}
		});
		if (list != null && list.size() > 0) {
			// 오류
			logger.error("대상 시스템에 EAI 서비스 코드가 등록되어 있지 않습니다. EAI팀에 문의 해주십시요!!");
			for (HashMap map : list) {
				logger.error("CM PACKAGE NUMBER : " + pkgNumber + " , 서버타입 : " + name + " , EAI서비스코드  : "
						+ map.get("EAISVCNAME"));
			}
			throw new Exception("대상 시스템에 EAI 서비스 코드가 등록되어 있지 않습니다. EAI팀에 문의 해주십시요!!");
			// return false;
		}

		return true;
	}

	public HashMap<String, HashMap<String, Vector<String>>> insertDB(String downloadPath, String apCode,
			String pkgNumber, DataSourceType dt, HashMap<String, HashMap<String, Vector<String>>> result)
			throws Exception {

		String filePath = "";

		// HashMap<String, HashMap<String, Vector<String>>> result = new
		// HashMap<String,HashMap<String,Vector<String>>>();
		HashMap<String, Vector<String>> serverType = null;

		Vector<String> layoutV = null;
		Vector<String> transformV = null;
		Vector<String> interfaceV = null;

		File file = null;
		File[] fileList = null;

		// for(DataSourceType dt : DataSourceTypeManager.getOnlineDataSourceTypes()){
		filePath = downloadPath + apCode + File.separator + pkgNumber + File.separator + dt.getName() + File.separator;
		// 서버구분체크
		file = new File(filePath);
		if (!file.exists()) { // 서버구분이 없을 경우
			return null;
		}
		serverType = new HashMap<String, Vector<String>>();
		layoutV = new Vector<String>();
		transformV = new Vector<String>();
		interfaceV = new Vector<String>();
		serverType.put(IoMapLoaderKey.LAYOUT, layoutV);
		serverType.put(IoMapLoaderKey.TRANSFORM, transformV);
		serverType.put(IoMapLoaderKey.INTERFACE, interfaceV);
		result.put(dt.getName(), serverType);

		// layout insert
		file = new File(filePath + IoMapLoaderKey.LAYOUT);
		fileList = file.listFiles();
		if (fileList != null && fileList.length > 0) {
			for (File f : fileList) {
				if (f.isFile()) {
					if (f.getParentFile() != null) { // 취약점소스 수정 2020.08.25
						loaderService.insertLayoutLoading(dt, f.getParentFile().getAbsolutePath() + File.separator,
								f.getName());
					}
					String name = f.getName().replaceAll(".txt", "");
					layoutV.add(name);
					logger.info("레이아웃 등록 리스트 : " + name);
				}
			}
		}
		// transform insert
		file = new File(filePath + IoMapLoaderKey.TRANSFORM);
		fileList = file.listFiles();
		if (fileList != null && fileList.length > 0) {
			for (File f : fileList) {
				if (f.isFile()) {
					if (f.getParentFile() != null) { // 취약점소스 수정 2020.08.25
						loaderService.insertTransformLoading(dt, f.getParentFile().getAbsolutePath() + File.separator,
								f.getName());
					}
					String name = f.getName().replaceAll(".txt", "");
					transformV.add(name);
					logger.info("변환 등록 리스트 : " + name);
				}
			}
		}
		// DataSourceContextHolder.setDataSourceType(dt);
		// cm layout 관련 변환 목록 추출
		for (String key : layoutV) {
			List<String> list = dao.selectTransformListForLayout(new HashMap() {
				{
					put("loutName", key);
				}
			});
			for (String cnvsnName : list) {
				transformV.add(cnvsnName);
				logger.info("레이아웃 관련 변환 리스트 : " + cnvsnName);
			}
		}
		// il02 기준으로 eai서비스코드의 변환값 저장
		// transform insert
		List<HashMap> list = dao.selectTSEAIIL02(new HashMap() {
			{
				put("pkgNumber", pkgNumber);
				put("applyYn", "N");
			}
		});
		for (HashMap map : list) {
			String eaiSvcName = (String) map.get("EAISVCNAME");
			String tranType = (String) map.get("APLYCHNGMSGFLDNAME"); // AplyChngMsgFldName
			tranType = tranType.toUpperCase();
			String tranTypeYnName = "";
			if (IoMapLoaderKey.REQ_TRAN_UPPER.equals(tranType)) {
				tranTypeYnName = IoMapLoaderKey.REQ_TRAN_YN_UPPER;
			} else if (IoMapLoaderKey.RES_TRAN_UPPER.equals(tranType)) {
				tranTypeYnName = IoMapLoaderKey.RES_TRAN_YN_UPPER;
			} else if (IoMapLoaderKey.ERR_TRAN_UPPER.equals(tranType)) {
				tranTypeYnName = IoMapLoaderKey.ERR_TRAN_YN_UPPER;
			}
			map.put("TRANTYPEYNNAME", tranTypeYnName);
			map.put("TRANTYPEYNVALUE", "1");
			logger.debug("IL02 테이블에서 만든 데이터  :" + map);
			dao.updateTSEAIHE02(map);
			interfaceV.add(eaiSvcName);
			logger.debug("변환 update 한  EAI 서비스코드 리스트 : " + eaiSvcName);
		}
		// }

		return result;
	}

	@Transactional
	public void deleteAndInsertBusinessDayChange(String workDay) throws Exception {
		PropGroup propGroup = propertyGroupService.getById(BUSINESS_DAY_CHANGE);

		List<Prop> props = propGroup.getProps();
		props.clear();

		Prop businessDayProp = new Prop();
		businessDayProp.setId(new PropId(BUSINESS_DAY_CHANGE, "BUSINESS_DAY"));
		businessDayProp.setPrpty2val(workDay);
		businessDayProp.setPropGroup(propGroup);
		props.add(businessDayProp);

		Prop changeStatusProp = new Prop();
		changeStatusProp.setId(new PropId(BUSINESS_DAY_CHANGE, "CHANGE_STATUS"));
		changeStatusProp.setPrpty2val("C");
		changeStatusProp.setPropGroup(propGroup);
		props.add(changeStatusProp);

		propertyGroupService.save(propGroup);
	}

	public void deleteAndInsertChangeStatus(String status) {
		PropGroup propGroup = propertyGroupService.getById(BUSINESS_DAY_CHANGE);

		List<Prop> props = propGroup.getProps();
		props.removeIf(prop -> prop.getId().getPrptyname().equals("CHANGE_STATUS"));

		Prop changeStatusProp = new Prop();
		changeStatusProp.setId(new PropId(BUSINESS_DAY_CHANGE, "CHANGE_STATUS"));
		changeStatusProp.setPrpty2val(status);
		changeStatusProp.setPropGroup(propGroup);
		props.add(changeStatusProp);

		propertyGroupService.save(propGroup);
	}

	public void deleteAllTSEAIDC01() throws Exception {
		// HashMap 으로 해야 schemaId 가 셋팅됨
		dao.deleteAllTSEAIDC01(new HashMap<String, Object>() {
		});
	}

	public void insertTSEAIDC01(String downloadPath, String apCode, String pkgNumber, String nextTime,
			DataSourceType dt) throws Exception {
		String filePath = downloadPath + apCode + File.separator + pkgNumber + File.separator + dt.getName()
				+ File.separator;
		File file = new File(filePath);
		if (!file.exists()) {
			return;
		}

		file = new File(filePath + IoMapLoaderKey.TRANSFORM);
		File[] fileList = file.listFiles();
		HashMap<String, String> param = new HashMap<String, String>(); // Interface 중복 제거
		if (fileList != null && fileList.length > 0) {
			// EAI서비스코드 존재 여부 체크
			for (File f : fileList) {
				if (f.isFile()) {
					HashMap map = loaderService.parse(f.getAbsolutePath());
					List<HashMap> list = (List<HashMap>) map.get("INTERFACEINFO");
					for (HashMap row : list) {
						String eaiSvcName = (String) row.get("EAISVCNAME");
						param.put(eaiSvcName, eaiSvcName);
					}
				}
			}
		}
		HashMap row = null;
		for (String key : param.keySet()) {
			row = new HashMap();
			row.put("eaiSvcName", key);
			row.put("splizValdYmd", nextTime);
			dao.insertTSEAIDC01(row);
			logger.info("DC01 에 데이터 등록 : " + row);
		}

	}

	public List<LinkedHashMap> interfaceInfoDownLoading(String path, String cnvsnName, String eaiSevrName)
			throws Exception {
		String eaiSevrDstcd = IoMapLoaderKey.getEaiSevrDstcd(eaiSevrName);
		List<LinkedHashMap> all = new ArrayList<LinkedHashMap>();
		List<LinkedHashMap> list = dao.selectInterfaceInfo(new HashMap() {
			{
				put("cnvsnName", cnvsnName);
				put("eaiSevrDstcd", eaiSevrDstcd);
			}
		});
		if (list == null || list.size() == 0) {
			return new ArrayList<LinkedHashMap>();
		}
		all.addAll(list);
		// 2020-02-28 TRANSFORM_EAI 로 시작되는건 이미 MMI 배포시에 셋팅되어 있어서 인터페이스 이행시 상관없음
//    	//추가 적으로 공통에러 변환 처리 로직 필요
//    	//예)TRANSFORM_EAI_EBCTOASC_ERR , TRANSFORM_EAI_EBCTOXML_ERR
//    	//로직) selectInterfaceInfo 에서 조회 한 인터페이스를 기준으로 에러 응답이 있으면 추출해서 셋팅한다.
//    	for(LinkedHashMap m : list){
//    		String eaiSvcName = (String)m.get("EAISVCNAME");
//    		List<LinkedHashMap> listCommonError = null;
//    		if (eaiSvcName != null){
//    			listCommonError = inboundErrorInfoDao.selectInterfaceInfoForCommonError(new HashMap(){{put("eaiSvcName",eaiSvcName);}}); 
//    			if (listCommonError != null && listCommonError.size() > 0 ){
//    				for(LinkedHashMap lm : listCommonError){
//    					if (!all.contains(lm)){//중복제거
//    						all.add(lm);
//    					}
//    				}
//    			}
//    		}
//    	}
		// sorting
		Collections.sort(all, new Comparator<LinkedHashMap>() {
			@Override
			public int compare(LinkedHashMap first, LinkedHashMap second) {
				String firstEAISvcName = (String) first.get("EAISVCNAME");
				String secondEAISvcName = (String) second.get("EAISVCNAME");
				return firstEAISvcName.compareTo(secondEAISvcName);
			}
		});

		return all;
	}

}
