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

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;

import javax.transaction.Transactional;

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.Pageable;
import org.springframework.stereotype.Service;

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.adapter.AdapterGroup;
import com.eactive.eai.data.entity.onl.b2bservice.B2BService;
import com.eactive.eai.data.entity.onl.b2bservice.B2BServiceId;
import com.eactive.eai.rms.common.base.BaseService;
import com.eactive.eai.rms.common.combo.ComboService;
import com.eactive.eai.rms.common.combo.ComboVo;
import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
import com.eactive.eai.rms.common.datasource.DataSourceType;
import com.eactive.eai.rms.data.entity.onl.adapter.AdapterGroupService;
import com.eactive.eai.rms.data.entity.onl.b2bservice.B2bServiceService;
import com.eactive.eai.rms.onl.common.exception.BizException;
import com.eactive.eai.rms.onl.common.util.FileWriteUtil;
import com.eactive.eai.rms.onl.loader.service.TransactionLoaderService;
import com.eactive.eai.rms.onl.manage.adapter.adapter.AdapterManService;
import com.eactive.eai.rms.onl.manage.adapter.adapter.ui.AdapterGroupUI;
import com.eactive.eai.rms.onl.manage.rule.transform.TransformDao;
import com.eactive.eai.rms.onl.manage.serviceinfo.eaimsg.EaiMsgCmFtpService;

@Service
@Transactional
public class B2bServiceManService extends BaseService {

	@Autowired
	@Qualifier("transformDao")
	private TransformDao transformDao;

	@Autowired
	@Qualifier("comboService")
	public ComboService comboService;

	@Autowired
	private AdapterManService adapterManService;

	@Autowired
	private TransactionLoaderService loaderService;

	@Autowired
	@Qualifier("monitoringContext")
	private MonitoringContext monitoringContext;

	@Autowired
	private EaiMsgCmFtpService eaiMsgCmFtpService;

	@Autowired
	private B2bServiceService service;

	@Autowired
	private B2bServiceManMapper mapper;
	
	@Autowired
	private AdapterGroupService adapterGroupService;

	public Page<B2bServiceUI> selectList(Pageable pageable, B2bServiceUISearch uiSearch) {
		Page<B2BService> page = service.findPage(pageable, uiSearch);
		return page.map(mapper::toVo);
	}

	public Map<String, List<?>> selectListToExcel(B2bServiceUISearch uiSearch) {
		Iterable<B2BService> b2bServices = service.findAll(uiSearch);
		ArrayList<HashMap<String, Object>> list = new ArrayList<>();
		for (B2BService item : b2bServices) {
			HashMap<String, Object> row = new HashMap<>();
			row.put("extnlinstiidnfiname", item.getId().getExtnlinstiidnfiname());
			row.put("svcprcssno", item.getId().getSvcprcssno());
			row.put("psvintfacdsticname", item.getPsvintfacdsticname());
			row.put("psvsysbzwkdstcd", item.getPsvsysbzwkdstcd());
			row.put("psvsysadptrbzwkgroupname", item.getPsvsysadptrbzwkgroupname());
			row.put("flovryn", item.getFlovryn());
			row.put("nextsvcprcssno", item.getNextsvcprcssno());
			row.put("outbndroutname", item.getOutbndroutname());
			row.put("useyn", item.getUseyn());
			row.put("eaisevrdstcd", item.getEaisevrdstcd());
			list.add(row);
		}

		HashMap<String, List<?>> map = new HashMap<>();
		map.put("list", list);

		return map;
	}

	public B2bServiceUI selectDetail(String extnlInstiIdnfiName, String svcPrcssNo) {
		B2BServiceId id = new B2BServiceId();
		id.setExtnlinstiidnfiname(extnlInstiIdnfiName);
		id.setSvcprcssno(Integer.parseInt(svcPrcssNo));
		B2BService entity = service.getById(id);
		B2bServiceUI uiVo = mapper.toVo(entity);
		if (!StringUtils.isEmpty(entity.getPsvsysadptrbzwkgroupname())) {
			Optional<AdapterGroup> optionalAadapterGroup = adapterGroupService
					.findById(entity.getPsvsysadptrbzwkgroupname());
			optionalAadapterGroup.ifPresent(adapterGroup -> uiVo.setAdptrNickName(adapterGroup.getAdptrnickname()));
		}
		return uiVo;
	}

	public void update(B2bServiceUI ui) {
		B2BService entity = service.getById(mapper.toEntity(ui).getId());
		mapper.updateToEntity(ui, entity);
		service.save(entity);
	}

	public void insert(B2bServiceUI ui) {
		B2BService entity = mapper.toEntity(ui);
		service.save(entity);
	}

	public void delete(String extnlInstiIdnfiName, String svcPrcssNo) {
		B2BServiceId id = new B2BServiceId();
		id.setExtnlinstiidnfiname(extnlInstiIdnfiName);
		id.setSvcprcssno(Integer.parseInt(svcPrcssNo));
		service.deleteById(id);
	}

	public Map<String, Object> selectListDetailCombo(String userId) throws Exception {
		List<ComboVo> listBiz = comboService.getFromBusinessType();

		// he02
		List<ComboVo> listPsvItfType = comboService.getFromCode("PSV_ITF_TYPE");// 수동 인터페이스 유형
		// 수동업무구분 <==같이
//        List listPsvId             = comboService.selectListComboForTable("TSEAISY01", "SYSDOMNNAME","SYSDOMNDESC");//수동시스템ID
		List<AdapterGroupUI> listOuAdapter = adapterManService.selectListComboForAdptrIoDstcd("OU");// 수동시스템인터페이스유형
		List<ComboVo> listFailOverCls = comboService.getFromCode("FAIL_OVER_CLS");// FailOver여부
		List<ComboVo> listCnvExistNot = comboService.getFromCode("CNV_EXIST_NOT");// 변환유무
		List<ComboVo> listBsRspCnvExistNot = comboService.getFromCode("BS_RSP_CNV_EXIST_NOT");// 기본응답변환유무
		List<ComboVo> listErrRspCnvExistNot = comboService.getFromCode("ERR_RSP_CNV_EXIST_NOT");// 오류응답변환유무
		List<ComboVo> listOutBoundRouting = comboService.getFromRouting(); // Outbound라우팅명
		
		List<ComboVo> listAddDelYn = comboService.getFromCode("ADD_DEL_YN");// 추가삭제여부
		List<ComboVo> listHdrCtlCd = comboService.getFromCode("HDR_CTL_CD");// 헤더제어구분코드

		List<ComboVo> listSvcPrcssNo = comboService.getFromCode("SVC_PRCSS_NO");// 서비스 처리 순서
		List<ComboVo> listInoutTypeCd = comboService.getFromCode("INOUT_TYPE");// EAI서버구분코드

		List<ComboVo> listUseYn = comboService.getFromCode("USE_YN");// 사용여부
		HashMap<String, Object> map = new HashMap<>();
		map.put("bizRows", listBiz);

		// he02
		map.put("psvItfTypeRows", listPsvItfType);
//		map.put("psvIdRows"             , listPsvId            ); 
		map.put("ouAdapterRows", listOuAdapter);
		map.put("failOverClsRows", listFailOverCls);
		map.put("cnvExistNotRows", listCnvExistNot);
		map.put("bsRspCnvExistNotRows", listBsRspCnvExistNot);
		map.put("errRspCnvExistNotRows", listErrRspCnvExistNot);
		map.put("outBoundRoutingRows", listOutBoundRouting);
		map.put("addDelYnRows", listAddDelYn);
		map.put("hdrCtlCdRows", listHdrCtlCd);
		map.put("svcPrcssNo", listSvcPrcssNo);
		map.put("inoutTypeRows", listInoutTypeCd);
		map.put("useYnRows", listUseYn);
		return map;
	}

	public Map<String, Object> selectListInitCombo(String userId) throws Exception {
		List<ComboVo> listFailOverCls = comboService.getFromCode("FAIL_OVER_CLS");// FailOver여부
		List<ComboVo> listInoutTypeCd = comboService.getFromCode("INOUT_TYPE");// EAI서버구분코드
		List<ComboVo> listUseYn = comboService.getFromCode("USE_YN");// 사용여부
		List<ComboVo> listBiz = comboService.getFromBusinessType();

		HashMap<String, Object> map = new HashMap<>();
		map.put("failOverClsRows", listFailOverCls);
		map.put("inoutTypeRows", listInoutTypeCd);
		map.put("useYnRows", listUseYn);
		map.put("bizRows", listBiz);
		return map;
	}

	public void clone(B2bServiceUI ui) throws Exception {
		ui.setExtnlInstiIdnfiName(ui.getNewExtnlInstiIdnfiName());
		ui.setSvcPrcssNo(ui.getNextSvcPrcssNo());
		B2BService cloneEntity = mapper.toEntity(ui);
		Optional<B2BService> optionalEntity = service.findById(cloneEntity.getId());
		if (optionalEntity.isPresent()) {
			throw new Exception("기존에 등록된 라우팅 B2B 기관 정보 입니다.");
		}
		service.save(cloneEntity);
	}

	public boolean migrationToProdB2BService(String userId, String listNames, String cmDate, String cmTime,
			String sysCode) 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");
		}

		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[] extnlInstiIdnfiNameList = listNames.split("\\&");

		StringBuffer sb = new StringBuffer();
		for (String extnlInstiIdnfiName : extnlInstiIdnfiNameList) {
			if (isDebug) {
				logger.debug("Start B2B 기관 서비스  migration To Prod (extnlInstiIdnfiName=" + extnlInstiIdnfiName + ")");
			}

			HashMap<String, String> paramMap = new HashMap<String, String>();
			paramMap.put("extnlInstiIdnfiName", extnlInstiIdnfiName);
			List<HashMap> list1 = transformDao.selectHE03ForMigration(paramMap);

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

			for (int j = 0; j < list1.size(); j++) {
				HashMap map = list1.get(j);
				// DELETE
				if (j == 0) {
					sb.append(String.format(B2bServiceQuery.MIG_DEL_HE03, schemaId, extnlInstiIdnfiName)).append("\n");
				}
				// INSERT
				sb.append(String.format(B2bServiceQuery.MIG_INS_HE03, schemaId, extnlInstiIdnfiName,
						map.get("SVCPRCSSNO"), StringUtil.getNullStr(map.get("PSVINTFACDSTICNAME")),
						StringUtil.getNullStr(map.get("PSVSYSBZWKDSTCD")),
						StringUtil.getNullStr(map.get("PSVSYSIDNAME")),
						StringUtil.getNullStr(map.get("PSVSYSSVCDSTICNAME")),
						StringUtil.getNullStr(map.get("PSVSYSADPTRBZWKGROUPNAME")),
						StringUtil.getNullStr(map.get("FLOVRYN")), StringUtil.getNullStr(map.get("CHNGEONOT")),
						StringUtil.getNullStr(map.get("CHNGMSGIDNAME")),
						StringUtil.getNullStr(map.get("BASCRSPNSMSGCMPRCTNT")),
						StringUtil.getNullStr(map.get("BASCRSPNSCHNGEONOT")),
						StringUtil.getNullStr(map.get("BASCRSPNSCHNGMSGIDNAME")),
						StringUtil.getNullStr(map.get("ERRRSPNSMSGCMPRCTNT")),
						StringUtil.getNullStr(map.get("ERRRSPNSCHNGEONOT")),
						StringUtil.getNullStr(map.get("ERRRSPNSCHNGMSGIDNAME")), map.get("NEXTSVCPRCSSNO"),
						StringUtil.getNullStr(map.get("OUTBNDROUTNAME")), map.get("TOUTVAL"),
						StringUtil.getNullStr(map.get("CMPENSVCPRCSSDSTICNAME")),
						StringUtil.getNullStr(map.get("SUPPLDELYN")), StringUtil.getNullStr(map.get("HDRCTRLDSTCD")),
						StringUtil.getNullStr(map.get("HDRREFCLSNAME")), StringUtil.getNullStr(map.get("EAISEVRDSTCD")),
						StringUtil.getNullStr(map.get("MODFIMGTSTUSDSTCD")),
						StringUtil.getNullStr(map.get("EAILASTAMNDYMS")),
						StringUtil.getNullStr(map.get("ADPTRBZWKGROUPDESC"))).replaceAll("' '", "''")).append("\n");
			}
		}

		String txtLocalFullPath = txtLocalPath + cmDate + cmTime + "_" + userId + "_" + sysCode + "_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)
				try {
					bw.close();
				} catch (Exception ee) {
					logger.error("bw close error");
				}
		}

		return ret;
	}

	public boolean extractB2B(String userId, String selectedList, String cmDate, String cmTime, String sysCode,
			String serviceType) throws BizException, Exception {
		boolean ret = false;

		if (SystemUtil.isProdServer()) {
			throw new BizException("해당 시스템에선 사용할 수 없습니다.");
		}

		Properties prop = monitoringContext.getProperties();

		if (prop == null ? true : prop.size() == 0) {
			throw new Exception("프라퍼티 정보가 없습니다. - CM_CONFIG");
		}

		if (serviceType == null ? true : serviceType.isEmpty()) {
			throw new Exception("serviceType is null");
		}

		boolean isDebug = logger.isDebugEnabled();
		String localPath = (String) prop.getProperty(MonitoringContext.CM_AFTER_PATH, "/dat/eaiData/engineData/after/");
		String[] extnlInstiIdnfiNames = selectedList.split("\\&");

		HashMap<String, String> eaiSystemCode = new HashMap<String, String>();
		for (String extnlInstiIdnfiName : extnlInstiIdnfiNames) {
			if (isDebug) {
				logger.debug("Start B2B 기관정보  extract (extnlInstiIdnfiName=" + extnlInstiIdnfiName + ")");
			}

			HashMap<String, String> paramMap = new HashMap<String, String>();
			paramMap.put("extnlInstiIdnfiName", extnlInstiIdnfiName);
			List<HashMap> he03s = transformDao.selectHE03ForMigration(paramMap);

			if (he03s == null || he03s.size() == 0) {
				throw new BizException("B2B 기관정보(" + extnlInstiIdnfiName + ")가 없습니다");
			}
			if (eaiSystemCode.size() > 1) {
				throw new BizException("CM대상 자원의 EAI서버구분코드가 통일되지 않았습니다.");
			}
			// 플로어라우터 변경 - tobe에서는 필요없을꺼 같음
			// String suffix = eaiSvcName.substring(eaiSvcName.length()-2,
			// eaiSvcName.length());
			// String flowControlRoutName =
			// chgFlowControls[Arrays.asList(chgSvcNames).indexOf(suffix)];

		}

		DataSourceType dt = DataSourceContextHolder.getDataSourceType();
		String folderName = cmDate + cmTime + "_" + userId + "_" + serviceType + "_TXT";
		String path = localPath + folderName + File.separator + FileWriteUtil.B2B + File.separator;

		try {
			for (String extnlInstiIdnfiName : extnlInstiIdnfiNames) {
				loaderService.b2bDownLoading(dt, path, extnlInstiIdnfiName);
			}
			eaiMsgCmFtpService.ftpUploadForStage(folderName, FileWriteUtil.B2B, extnlInstiIdnfiNames);

			ret = true;
		} catch (Exception e) {
			logger.error("ERROR: " + e.toString());
			ret = false;
			// 스테이징에 복사가 안되었을 경우 after에 생성된 폴더 삭제
			eaiMsgCmFtpService.deleteFolder(folderName);
			throw e;
		}
		return ret;
	}
}
