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

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;

import org.apache.commons.io.FileUtils;
//import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;

import com.eactive.eai.rms.common.base.OnlBaseService;
import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.onl.common.exception.BizException;
import com.eactive.eai.rms.onl.common.util.FileWriteUtil;
import com.eactive.eai.rms.onl.common.util.HttpClientUploadUtil;
import com.eactive.eai.rms.onl.loader.service.TransactionLoaderService;
import com.google.gson.Gson;

@Service("eaiMsgCmFtpService")
public class EaiMsgCmFtpService extends OnlBaseService {
	private static final Logger logger = Logger.getLogger(EaiMsgController.class);
	
	@Autowired
	@Qualifier("monitoringContext")
	private MonitoringContext monitoringContext;
	
    @Autowired
    @Qualifier("loaderService") 
    private TransactionLoaderService loaderService; 
	
	static final String extUrl = "/cmFileUpload.file";
	
	public String[] getLocalFileList() throws BizException, Exception {
		String[] ret = null;
		
		Properties prop = monitoringContext.getProperties();
		String afterPath = prop.getProperty(MonitoringContext.CM_AFTER_PATH  , "/dat/eaiData/engineData/after/");
		File dir = new File(afterPath);
		if (!dir.exists()) {
			throw new BizException("시스템 폴더를 찾을 수 없습니다. - "+ afterPath);
		}
		File[] fileList = dir.listFiles();
		if (fileList != null){
			ret = Arrays.stream(fileList).filter(File::isDirectory).map(File::getName).toArray(String[]::new);
		}else{
			ret = new String[0];
		}
		
		return ret;
	}
	public String[] getLocalFileList(String path) throws BizException, Exception {
		String[] ret = null;
		
		if(path == null){
			throw new BizException("경로가 지정되지 않았습니다.");
		}
		
		File dir = new File(path);
		if (!dir.exists()) {
			throw new BizException("시스템 폴더를 찾을 수 없습니다. - "+ path);
		}
		File[] fileList = dir.listFiles();
		if (fileList != null){
			ret = Arrays.stream(fileList).filter(File::isDirectory).map(File::getName).toArray(String[]::new);
		}else{
			ret = new String[0];
		}
		
		return ret;
	}
	
	public String[] getFtpFileList() throws BizException, Exception {
		String[] ret = null;
		
		Properties prop = monitoringContext.getProperties();
		String targetBaseUrl = prop.getProperty(MonitoringContext.CM_TARGET_BASEURL  , "http://127.0.0.1:22080/monitoring");
		
		String data = HttpClientUploadUtil.post(targetBaseUrl+extUrl,new HashMap(){{put("cmd","select");}});
		logger.info("getFtpFileList receive data : " + data);
		data = data.trim();
		JSONParser parser = new JSONParser();
		JSONObject obj = (JSONObject)parser.parse(data);
		JSONArray rows = (JSONArray)obj.get("rows");
		ArrayList<String> al = new ArrayList<String>();
		for(int i=0;i<rows.size();i++){
			String o = (String)rows.get(i);
			al.add(o);
		}
		ret = new String[al.size()];
		al.toArray(ret);
		
		return ret;
	}
	
	public Map<String, List<Map<String, String>>> getLocalFileDetail(String fileName) throws Exception {
		Map<String, List<Map<String, String>>> ret = new HashMap<String, List<Map<String, String>>>();
	
		Properties prop = monitoringContext.getProperties();
		String afterPath = prop.getProperty(MonitoringContext.CM_AFTER_PATH  , "/dat/eaiData/engineData/after/");
		
		String localPath = afterPath + fileName;
		File f = new File(localPath);
		File[] folders = f.listFiles();
		if(folders != null){ //취약점소스 수정 2020.08.27
			for (File folder : folders){
				if (FileWriteUtil.INTERFACE.equals(folder.getName())){
					File[] files = folder.listFiles();
					if(files != null){//취약점소스 수정 2020.08.27
						for(File file : files){
							HashMap map = loaderService.parse(file.getAbsolutePath());
							dataPut(ret, map,"TSEAIHE01","EAISVCNAME","EAISvcCode");
							dataPut(ret, map,"TSEAIFR03","EAISVCNAME","FieldInfo");
							dataPut(ret, map,"TSEAIHS04","BZWKSVCKEYNAME","KBStdCode");
							dataPut(ret, map,"TSEAIFR06","EAISVCNAME","B2BExt");
						}
					}
				}else if  (FileWriteUtil.B2B.equals(folder.getName())){
					File[] files = folder.listFiles();
					if(files != null){//취약점소스 수정 2020.08.27
						for(File file : files){
							HashMap map = loaderService.parse(file.getAbsolutePath());
							dataPut(ret, map,"TSEAIHE03","EXTNLINSTIIDNFINAME","B2BSvc");
						}
					}
					
				}else if  (FileWriteUtil.C2R.equals(folder.getName())){
					File[] files = folder.listFiles();
					if(files != null){//취약점소스 수정 2020.08.27
						for(File file : files){
							HashMap map = loaderService.parse(file.getAbsolutePath());
							dataPut(ret, map,"TSEAIHE04","EXTNLINSTIIDNFINAME","C2RSvc");
						}
					}
				}else if  (FileWriteUtil.ADAPTER.equals(folder.getName())){
					File[] files = folder.listFiles();
					if(files != null){//취약점소스 수정 2020.08.27
						for(File file : files){
							HashMap map = loaderService.parse(file.getAbsolutePath());
							dataPut(ret, map,"TSEAIAD01","ADPTRBZWKGROUPNAME","AdapterGroupName");
						}
					}
				}
			}
		}
		
		for(String key : ret.keySet()){ //취약점소스 수정 2020.08.27
			if(ret.get(key) == null) continue;	
			if (ret.get(key).size() > 0 ){
				ArrayList<Map<String,String>> retData = (ArrayList<Map<String,String>>)ret.get(key);
				ArrayList<Map<String,String>> list2 = (ArrayList<Map<String, String>>) retData.parallelStream().distinct().collect(Collectors.toList());
				ret.put(key, list2);
			}
		}
		return ret;
	}
	
	public Map<String, List<Map<String, String>>> getLocalFileDetail(String path, String fileName) throws Exception {
		Map<String, List<Map<String, String>>> ret = new HashMap<String, List<Map<String, String>>>();
	
		String localPath = path + fileName;
		File f = new File(localPath);
		File[] folders = f.listFiles();
		if(folders != null){ //취약점소스 수정 2020.08.27
			for (File folder : folders){
				if (FileWriteUtil.INTERFACE.equals(folder.getName())){
					File[] files = folder.listFiles();
					if(files != null){//취약점소스 수정 2020.08.27
						for(File file : files){
							HashMap map = loaderService.parse(file.getAbsolutePath());
							dataPut(ret, map,"TSEAIHE01","EAISVCNAME","EAISvcCode");
							dataPut(ret, map,"TSEAIFR03","EAISVCNAME","FieldInfo");
							dataPut(ret, map,"TSEAIHS04","BZWKSVCKEYNAME","KBStdCode");
							dataPut(ret, map,"TSEAIFR06","EAISVCNAME","B2BExt");
						}
					}
				}else if  (FileWriteUtil.B2B.equals(folder.getName())){
					File[] files = folder.listFiles();
					if(files != null){//취약점소스 수정 2020.08.27
						for(File file : files){
							HashMap map = loaderService.parse(file.getAbsolutePath());
							dataPut(ret, map,"TSEAIHE03","EXTNLINSTIIDNFINAME","B2BSvc");
						}
					}
					
				}else if  (FileWriteUtil.ADAPTER.equals(folder.getName())){
					File[] files = folder.listFiles();
					if(files != null){//취약점소스 수정 2020.08.27
						for(File file : files){
							HashMap map = loaderService.parse(file.getAbsolutePath());
							dataPut(ret, map,"TSEAIAD01","ADPTRBZWKGROUPNAME","AdapterGroupName");
						}
					}
				}
			}
		}
		
		for(String key : ret.keySet()){ //취약점소스 수정 2020.08.27
			if(ret.get(key) == null) continue;	
			if (ret.get(key).size() > 0 ){
				ArrayList<Map<String,String>> retData = (ArrayList<Map<String,String>>)ret.get(key);
				ArrayList<Map<String,String>> list2 = (ArrayList<Map<String, String>>) retData.parallelStream().distinct().collect(Collectors.toList());
				ret.put(key, list2);
			}
		}
		return ret;
	}
	
	private void dataPut(Map<String, List<Map<String, String>>> result, HashMap parsingMap, String tableName, String keyColumn, String hashKey){
		List<Map<String,String>> data = null;
		List<HashMap> list = (List<HashMap>)parsingMap.get(tableName);
		if (list != null && list.size() > 0){
			if (result.containsKey(hashKey)){
				data = result.get(hashKey);
			}else {
				data = new ArrayList<Map<String,String>>();
			}
			for(HashMap m : list){
				if (m.containsKey(keyColumn)){
					if(data != null){  //취약점소스 수정 2020.08.27
						data.add(new HashMap(){{put("CODE",(String)m.get(keyColumn));}});
					}
				}
			}
			result.put(hashKey, data);
		}
	}
	
	public Map<String, List<Map<String, String>>> getFtpFileDetail(String fileName) throws Exception {
		
		Properties prop = monitoringContext.getProperties();
		String targetBaseUrl = prop.getProperty(MonitoringContext.CM_TARGET_BASEURL  , "http://127.0.0.1:22080/monitoring");
		
		String data = HttpClientUploadUtil.post(targetBaseUrl+extUrl,new HashMap(){{put("cmd","detail");put("fileName",fileName);}});
		logger.info("getFtpFileList receive data : " + data);

		data = data.trim();
		
    	Gson gson = new Gson();
    	@SuppressWarnings("unchecked")
    	Map<String, List<Map<String, String>>>ret = gson.fromJson(data, Map.class);
		
		return ret;
	}
	public boolean deleteFiles(String localFiles,String fileList ) throws Exception{
		boolean local = deleteFiles(localFiles);
		boolean remote = remoteDeleteFiles(fileList);
		if (local || remote){
			return true;
		}else{
			return false;
		}
	}
	public boolean deleteFiles(String localFiles) throws BizException, Exception {
		Properties prop = monitoringContext.getProperties();
		String afterPath = prop.getProperty(MonitoringContext.CM_AFTER_PATH  , "/dat/eaiData/engineData/after/");
		
		// LOCAL 파일 삭제
		String[] arrLocalFile = localFiles.split("\\&");
		for (String fileName : arrLocalFile) {
			if (StringUtils.isEmpty(fileName)) {
				continue;
			}
			File f = new File(afterPath + fileName);
    		if (!f.exists()){
    			throw new Exception("folder("+f.getAbsolutePath()+") 가 존재 하지 않습니다.");
    		}
    		if (f.isDirectory()){
    			FileUtils.deleteDirectory(f);
    		}
		}

		return true;
	}
	public boolean remoteDeleteFiles(String fileList) throws BizException, Exception {
		Properties prop = monitoringContext.getProperties();
		String targetBaseUrl = prop.getProperty(MonitoringContext.CM_TARGET_BASEURL  , "http://127.0.0.1:22080/monitoring");

		String data = HttpClientUploadUtil.post(targetBaseUrl+extUrl,new HashMap(){{put("cmd","delete");put("fileList",fileList);}});
		logger.info("remoteDeleteFiles receive data : "+ data);
		
		data = data.trim();

		JSONParser parser = new JSONParser();
		JSONObject obj = (JSONObject)parser.parse(data);
		String status = (String)obj.get("status");
		if (status != null && "success".equals(status)){
			return true;
		}
		return false;
	}
	
	public void ftpUpload(String localFiles) throws BizException, Exception {
		Properties prop = monitoringContext.getProperties();
		String afterPath     = prop.getProperty(MonitoringContext.CM_AFTER_PATH     , "/dat/eaiData/engineData/after/");
		String targetBaseUrl = prop.getProperty(MonitoringContext.CM_TARGET_BASEURL , "http://127.0.0.1:22080/monitoring");
		
		String[] arrLocalFile = localFiles.split("\\&");
		for (String fileName : arrLocalFile) {
			MultiValueMap<String, Object> linkedMultiValueMap = HttpClientUploadUtil.buildFileUploadData( afterPath, fileName);
			HashMap<String,String> params = new HashMap<String,String>();
			params.put("cmFolder", fileName);
			HttpClientUploadUtil.upload(targetBaseUrl+extUrl,params,linkedMultiValueMap);
			File localFile = new File(afterPath + fileName);
			if (localFile.isDirectory()){
				FileUtils.deleteDirectory(localFile);
			}
		}
	}
	public boolean ftpUploadForStage(String localFolder, String type, String[] validList) throws BizException, Exception {
		
		HashMap<String,String> valids = new HashMap<String,String>();
		HashMap<String,String> notValids = new HashMap<String,String>();
		
		//대상 File만 보내기 위해서 key 생성
		for(String key : validList){
			String data = type + "_" + key + ".txt";
			logger.debug("ftpUploadForStage : valid key =" + data);
			valids.put(data,data);
		}
		
		Properties prop = monitoringContext.getProperties();
		String afterPath     = prop.getProperty(MonitoringContext.CM_AFTER_PATH     , "/dat/eaiData/engineData/after/");
		String targetBaseUrl = prop.getProperty(MonitoringContext.CM_STAGE_BASEURL , "http://127.0.0.1:22080/monitoring");
		
		MultiValueMap<String, Object> linkedMultiValueMap = HttpClientUploadUtil.buildFileUploadData(afterPath, localFolder);
		
		//제거목록 생성
		for(String key : linkedMultiValueMap.keySet()){
			if (!valids.containsKey(key)){
				notValids.put(key,key);
			}
		}
		//목록제거
		for(String key : notValids.keySet()){
			logger.debug("ftpUploadForStage : remove key =" + key);
			linkedMultiValueMap.remove(key);
		}
		
		HashMap<String,String> params = new HashMap<String,String>();
		params.put("cmFolder", localFolder);
		params.put("cmd","realtimeApply");
		HttpClientUploadUtil.upload(targetBaseUrl+extUrl,params,linkedMultiValueMap);
		
		return true;
	}
	public boolean deleteFolder(String localFolder) throws BizException, Exception {
		
		Properties prop = monitoringContext.getProperties();
		String afterPath = prop.getProperty(MonitoringContext.CM_AFTER_PATH  , "/dat/eaiData/engineData/after/");
		
		File f = new File(afterPath + localFolder);
		if (!f.exists()){
			throw new Exception("folder("+f.getAbsolutePath()+") 가 존재 하지 않습니다.");
		}
		if (f.isDirectory()){
			FileUtils.deleteDirectory(f);
		}
		return true;
	}
	public void moveForRetry(String localFiles) throws BizException, Exception {
		//스케줄러가 적용 될 수있도록 (fail 폴더에서 download 폴더로 이동)
		Properties prop = monitoringContext.getProperties();
		String failPath     = prop.getProperty(MonitoringContext.CM_FAIL_PATH     , "/dat/eaiData/engineData/fail/");
		String downPath     = prop.getProperty(MonitoringContext.CM_DOWNLOAD_PATH     , "/dat/eaiData/engineData/download/");
		
		String[] arrLocalFile = localFiles.split("\\&");
		for (String fileName : arrLocalFile) {
			File failF = new File(failPath+File.separator+fileName);
			if(failF.isDirectory()){
				failF.renameTo(new File(downPath + File.separator + fileName+"_PROD"));
			}
		}
	}
}
