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

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 org.apache.commons.lang3.StringUtils;
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.PageImpl;
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.bizkey.BizKey;
import com.eactive.eai.data.entity.onl.transformer.layout.LayoutItemEntity;
import com.eactive.eai.rms.common.base.OnlBaseService;
import com.eactive.eai.rms.common.combo.ComboService;
import com.eactive.eai.rms.common.combo.ComboVo;
import com.eactive.eai.rms.data.entity.onl.bizkey.BizKeyService;
import com.eactive.eai.rms.data.entity.onl.eaimsg.EAIMessageService;
import com.eactive.eai.rms.data.entity.onl.layout.LayoutService;
import com.eactive.eai.rms.onl.common.exception.BizException;
import com.eactive.eai.rms.onl.manage.rule.layout.mapper.LayoutPopupUIMapper;
import com.eactive.eai.rms.onl.manage.rule.layout.ui.LayoutPopupUI;
import com.eactive.eai.rms.onl.manage.rule.transform.TransformDao;

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

@Service("fieldExtractInfoService")
@Transactional
public class FieldExtractInfoService extends OnlBaseService {

	private ComboService comboService;

	@Qualifier("transformDao")
	private TransformDao transformDao;

	private BizKeyService bizKeyService;
	private FieldExtractInfoUIMapper fieldExtractInfoUIMapper;
	private EAIMessageService eaiMessageQueryService;
	private LayoutService layoutService;
	private LayoutPopupUIMapper layoutPopupUIMapper;
	
	@Autowired
	public FieldExtractInfoService(ComboService comboService, BizKeyService bizKeyService, 
			FieldExtractInfoUIMapper fieldExtractInfoUIMapper,EAIMessageService eaiMessageQueryService,
			LayoutService layoutService, LayoutPopupUIMapper layoutPopupUIMapper) {
		this.comboService = comboService;
		this.bizKeyService = bizKeyService;
		this.fieldExtractInfoUIMapper = fieldExtractInfoUIMapper;
		this.eaiMessageQueryService = eaiMessageQueryService;
		this.layoutService = layoutService;
		this.layoutPopupUIMapper = layoutPopupUIMapper;
	}

	public Page<FieldExtractInfoUI> selectList(String searchEaiSvcName, Pageable pageable) {
		return bizKeyService.findAll(searchEaiSvcName, pageable).map(fieldExtractInfoUIMapper::toVo);
	}

	public Map<String, Object>[] selectListToExcel(String eaiSvcName) {
		@SuppressWarnings("unchecked")
		Map<String, Object>[] mapArray = bizKeyService.findAll(eaiSvcName, Pageable.unpaged()).stream().map(b -> {
			Map<String, Object> map = new HashMap<>();
			map.put("EAISVCNAME", b.getId().getEaisvcname());
			map.put("ETRACTDSTCD", b.getId().getEtractdstcd());
			map.put("FLDPRCSSNO", String.valueOf(b.getId().getFldprcssno()));
			map.put("MSGDSTCD", b.getMsgdstcd());
			map.put("BZWKFLDNAME", b.getBzwkfldname());
			return map;
		}).toArray(HashMap[]::new);
		return mapArray;
	}

	public List<FieldExtractInfoUI> selectDetail(String eaiSvcName, String etractDstcd) {
		List<FieldExtractInfoUI> list = bizKeyService
				.findByIdEaisvcnameAndIdEtractdstcd(eaiSvcName, etractDstcd)
				.stream()
				.map(fieldExtractInfoUIMapper::toVo)
				.collect(Collectors.toList());

		String eaiSvcDesc = eaiMessageQueryService.findById(eaiSvcName).map(e -> e.getEaisvcdesc()).orElse(null);

		list.forEach(v -> v.setEaiSvcDesc(eaiSvcDesc));

		return list;
	}

	public void update(FieldExtractInfoUI fieldExtractInfoUI) {
		delete(fieldExtractInfoUI.getEaiSvcName(), fieldExtractInfoUI.getEtractDstcd());
		insert(fieldExtractInfoUI);
	}

	public void insert(FieldExtractInfoUI fieldExtractInfoUI) {
		List<String> bzwkFldNames = Arrays
				.stream(fieldExtractInfoUI.getBzwkFldNames())
				.filter(StringUtils::isNotBlank)
				.collect(Collectors.toList());

		int i = 0;
		for (String bzwkFldName : bzwkFldNames) {
			fieldExtractInfoUI.setFldprcssno(++i);
			fieldExtractInfoUI.setBzwkFldName(bzwkFldName);
			BizKey bizKey = fieldExtractInfoUIMapper.toEntity(fieldExtractInfoUI);
			bizKeyService.save(bizKey);
		}
	}

	public void delete(String eaiSvcName, String etractDstcd) {
		bizKeyService.delete(eaiSvcName, etractDstcd);
	}

	public Map<String, List<ComboVo>> selectListInitCombo() {
		List<ComboVo> exrClassTypeList = comboService.getFromCode("EXR_CLASS_TYPES");
		Map<String, List<ComboVo>> map = new HashMap<>();

		map.put("exrClassTypeList", exrClassTypeList);

		return map;
	}

	public Map<String, List<ComboVo>> selectListDetailCombo() {
		List<ComboVo> exrClassTypeList = comboService.getFromCode("EXR_CLASS_TYPES");
		List<ComboVo> msgTypeList = comboService.getFromCode("MSG_TYPES");
		Map<String, List<ComboVo>> map = new HashMap<>();

		map.put("exrClassTypeList", exrClassTypeList);
		map.put("msgTypeList", msgTypeList);
		return map;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public boolean migrationToProdBizKeyService(String userId, String listSvcName, String cmDate, String cmTime)
			throws BizException, Exception {

		boolean ret = false;

		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[] eaiSvcNameList = listSvcName.split("\\&");
		String[] eaiSystemCode = new String[eaiSvcNameList.length];

		StringBuffer sb = new StringBuffer();
		for (String tmp : eaiSvcNameList) {
			String[] arr = tmp.split(":");
			String eaiSvcName = arr[0];
			String etractDstCd = arr[1];
			if (isDebug) {
				logger.debug("Start BizKey 서비스  migration To Prod (eaiSvcName=" + eaiSvcName + ")");
			}

			HashMap params = new HashMap<String, String>();
			params.put("eaiSvcName", eaiSvcName);
			String eaisevrDstcd = transformDao.selectEAISvrCode(params);
			if (StringUtils.isEmpty(eaisevrDstcd)) {
				throw new BizException("EAI서버구분코드가 등록되지 않은 자원이 있습니다.");
			}
			if (StringUtils.isEmpty(eaiSystemCode[i])) {
				eaiSystemCode[i] = eaisevrDstcd;
			}

			HashMap<String, String> paramMap = new HashMap<String, String>();
			paramMap.put("eaiSvcName", eaiSvcName);
			paramMap.put("etractDstCd", etractDstCd);
			List<HashMap> list1 = transformDao.selectFR03ForMigration(paramMap);

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

			String deleteQueryFR03 = "DELETE FROM %s.TSEAIFR03 WHERE EAISVCNAME = '%s';";
			String insertQueryFR03 = "INSERT INTO %s.TSEAIFR03 " + "( EAISVCNAME" + ", ETRACTDSTCD" + ", FLDPRCSSNO"
					+ ", MSGDSTCD" + ", BZWKFLDNAME" + ", EAISEVRDSTCD" + ", MODFIMGTSTUSDSTCD" + ", EAILASTAMNDYMS "
					+ ") VALUES ( '%s', '%s', %s, '%s', '%s', '%s', '%s', '%s' );";

			for (int j = 0; j < list1.size(); j++) {
				HashMap map = list1.get(j);
				// DELETE
				if (j == 0) {
					sb.append(String.format(deleteQueryFR03, schemaId, eaiSvcName)).append("\n");
				}
				// INSERT
				sb
						.append(String
								.format(insertQueryFR03, schemaId, eaiSvcName,
										StringUtil.getNullStr(map.get("ETRACTDSTCD")), map.get("FLDPRCSSNO"),
										StringUtil.getNullStr(map.get("MSGDSTCD")),
										StringUtil.getNullStr(map.get("BZWKFLDNAME")),
										StringUtil.getNullStr(map.get("EAISEVRDSTCD")),
										StringUtil.getNullStr(map.get("MODFIMGTSTUSDSTCD")),
										StringUtil.getNullStr(map.get("EAILASTAMNDYMS")))
								.replaceAll("' '", "''"))
						.append("\n");
			}
			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) {
				bw.close();
			}
		}

		return ret;
	}

	public Page<LayoutPopupUI> selectLayoutItems(String loutName) {
		List<LayoutItemEntity> layoutItemEntities = layoutService
														.getById(loutName).getLayoutItemEntities();
		
		List<LayoutPopupUI> layoutPopupUIs = layoutPopupUIMapper.map(layoutItemEntities);
		
//		List<LayoutPopupUI> layoutItemUIs = layoutService
//				.getById(loutName)
//				.getLayoutItemEntities()
//				.stream()
//				.map(layoutPopupUIMapper::toVo)
//				.collect(Collectors.toList());
		return new PageImpl<>(layoutPopupUIs);
	}

}
