package com.eactive.eai.rms.common.combo;

import com.eactive.apim.portal.approval.entity.ApprovalType;
import com.eactive.apim.portal.monitoringcode.entity.MonitoringCode;
import com.eactive.apim.portal.portalorg.entity.PortalOrgEnums;
import com.eactive.eai.rms.common.datasource.DataSourceType;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.eai.rms.common.util.CommonConstants;
import com.eactive.eai.rms.data.entity.man.monitoringCode.service.MonitoringCodeService;
import com.eactive.eai.rms.data.entity.onl.adapter.AdapterGroupService;
import com.eactive.eai.rms.data.entity.onl.adapter.CommonDomainService;
import com.eactive.eai.rms.data.entity.onl.adaptertype.AdapterTypeService;
import com.eactive.eai.rms.data.entity.onl.apim.portalorg.PortalOrgService;
import com.eactive.eai.rms.data.entity.onl.authserver.ClientEntityService;
import com.eactive.eai.rms.data.entity.onl.b2bservice.B2bServiceService;
import com.eactive.eai.rms.data.entity.onl.bzwkdstcd.UserBusinessService;
import com.eactive.eai.rms.data.entity.onl.code.Code;
import com.eactive.eai.rms.data.entity.onl.code.CodeId;
import com.eactive.eai.rms.data.entity.onl.code.CodeService;
import com.eactive.eai.rms.data.entity.onl.eaimsg.ServiceMessageService;
import com.eactive.eai.rms.data.entity.onl.layout.LayoutTypeService;
import com.eactive.eai.rms.data.entity.onl.routing.RoutingService;
import com.eactive.eai.rms.data.entity.onl.server.EAIServerService;
import com.eactive.eai.rms.data.entity.onl.transform.FunctionService;
import com.eactive.eai.rms.data.entity.onl.unifbwk.UnifBwkTpService;
import com.eactive.eai.transformer.util.TransformKeys;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

@Service("comboService")
@RequiredArgsConstructor
class ComboServiceImpl implements ComboService {

	private final ComboMapper comboMapper;
	private final CodeService codeService;
	private final MonitoringCodeService monitoringCodeService;
	private final UnifBwkTpService unifBwkService;
	private final UserBusinessService userBusinessService;
	private final EAIServerService eaiServerService;
	private final AdapterTypeService adapterTypeEntityService;
	private final RoutingService routingService;
	private final B2bServiceService b2bServiceService;
	private final ServiceMessageService serviceMessageService;
	private final AdapterGroupService adapterGroupService;
	private final CommonDomainService commonDomainService;
	private final FunctionService functionService;
	private final LayoutTypeService layoutTypeService;
	private final PortalOrgService portalOrgService;
	private final ClientEntityService clientEntityService;

	@Override
	public List<ComboVo> getFromAdapterType() {
		return adapterTypeEntityService
				.findAll(Sort.by("adptrcd"))
				.stream()
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromEAIServer() {
		return eaiServerService
				.findAll(Sort.by("eaisevrinstncname"))
				.stream()
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromEAIServerWithoutAll() {
		return eaiServerService
				.findAll(Sort.by("eaisevrinstncname"))
				.stream()
				.map(comboMapper::toCombo)
				.filter(vo -> !vo.getCode().equals("ALL"))
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromBusinessType() {
		return unifBwkService
				.findAll(Sort.by("eaibzwkdstcd"))
				.stream()
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromRouting(String layerdstcd) {
		return StreamSupport
				.stream(routingService.findByLayerdstcd(layerdstcd).spliterator(), false)
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromRouting() {
		return routingService
				.findAll(Sort.by("routname"))
				.stream()
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromLayoutType() {
		return layoutTypeService.findAll().stream().map(comboMapper::toCombo).collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromFunction() {
		return functionService
				.findAll(Sort.by("cnvsnfuntnname"))
				.stream()
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromB2BService() {
		return b2bServiceService
				.findAll(Sort.by("id.extnlinstiidnfiname"))
				.stream()
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromCode(String codeGroup) {
		List<Code> codes = codeService.findByIdCodegroup(codeGroup);
		return codes.stream().map(comboMapper::toCombo).collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromBizCode(String inputdstcd) {
		return StreamSupport
				.stream(unifBwkService.findByInputdstcd(inputdstcd).spliterator(), false)
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromBizCodeAppl(String inputdstcd) {
		return StreamSupport
				.stream(unifBwkService.findByInputdstcd(inputdstcd).spliterator(), false)
				.map(comboMapper::toComboAppl)
				.collect(Collectors.toList());
	}

	@Override
	public List<Map<String, Object>> getFromCodeByGroups(List<String> codeGroups) {
		List<Map<String, Object>> result = new ArrayList<>();
		if (codeGroups == null) {
			return result;
		}

		Map<String, Object> groupedCodesMap = new HashMap<>();
		for (String codeGroup : codeGroups) {

			List<ComboVo> codesForGroup = getFromCode(codeGroup);
			groupedCodesMap.put(codeGroup, codesForGroup);
		}

		result.add(groupedCodesMap);
		return result;
	}

	@Override
	public String getName(String codeGroup, String code) {
		return codeService.findById(new CodeId(codeGroup, code)).map(Code::getCodename).orElse("");
	}

	@Override
	public List<ComboVo> selectTransform(String type) {
		Map<String, String> data = null;

		if ("CNVSNRETUNID".equals(type)) {
			data = TransformKeys.getCnvsnRetunID();
		} else if ("CNVSNTYPEID".equals(type)) {
			data = TransformKeys.getCnvsnTypeID();
		} else if ("CNVSNPARMTYPEID".equals(type)) {
			data = TransformKeys.getCnvsnParmTypeID();
		} else if ("LOUTITEMNODEPTRNID".equals(type)) {
			data = TransformKeys.getLoutItemNodePtrnID();
		}
		if (data == null) {
			return new ArrayList<>();
		}
		List<ComboVo> result = new ArrayList<>();

		for (Entry<String, String> entry : data.entrySet()) {
			ComboVo h = new ComboVo();
			h.setCode(entry.getValue());
			h.setCodename(entry.getKey());
			result.add(h);
		}
		return result;

	}

	@Override
	public List<ComboVo> getFromUserBusiness() {
		List<String> surrentUserBusinessCodes = userBusinessService.getCurrentUserBusinessCodes();
		return unifBwkService
				.findAllById(surrentUserBusinessCodes)
				.stream()
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromTransform(String eaiSvcName, String cnvsnName) {
		return serviceMessageService
				.findTransform(eaiSvcName, 1, cnvsnName)
				.stream()
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromMonitoringCode(String groupName, String useYn) {
		return StreamSupport
				.stream(monitoringCodeService.findByIdCodegroup(groupName).spliterator(), false)
				.filter(code -> StringUtils.equalsIgnoreCase(code.getUseYn(), useYn))
				.sorted(Comparator.comparing(MonitoringCode::getSeq))
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getMonitoringCodeSortedByIdCode(String groupName) {
		return getMonitoringCode(groupName, Comparator.comparing(code -> code.getId().getCode()));
	}

	@Override
	public List<ComboVo> getMonitoringCodeSortedByCodeName(String groupName) {
		return getMonitoringCode(groupName, Comparator.comparing(MonitoringCode::getCodeName));
	}

	@Override
	public List<ComboVo> getMonitoringCodeSortedBySeq(String groupName) {
		return getMonitoringCode(groupName, Comparator.comparing(MonitoringCode::getSeq));
	}

	private List<ComboVo> getMonitoringCode(String groupName, Comparator<MonitoringCode> comparator) {
		return StreamSupport
				.stream(monitoringCodeService.findByIdCodegroup(groupName).spliterator(), false)
				.sorted(comparator)
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromAdapterGroup() {
		return adapterGroupService
				.findAll(Sort.by("adptrbzwkgroupname"))
				.stream()
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromAdapterGroup(boolean useYn) {
		return adapterGroupService
				.findByAdptruseyn(useYn)
				.stream()
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromEAIServerForFailOver(String svrInstName) {
		return eaiServerService
				.findAllFailOverServer(svrInstName)
				.stream()
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromDomainNm() {
		return commonDomainService
				.findAll(Sort.by("domainNm"))
				.stream()
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromExtBusiness() {
		List<ComboVo> extBusiness = unifBwkService
				.findExtBusiness()
				.stream()
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
		extBusiness.forEach(c -> c.setCode(StringUtils.substring(c.getCode(), 1, 4)));
		return extBusiness;
	}

	@Override
	public List<ComboVo> getFromPortalOrgName() {
		return portalOrgService
				.findAll(Sort.by("orgName", "orgCode"))
				.stream()
				.filter(org -> org.getOrgStatus() != PortalOrgEnums.OrgStatus.REMOVED)
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromApprovalType() {
		return Arrays.stream(ApprovalType.values())
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}

	@Override
	public List<ComboVo> getFromServiceType(String useServiceType) {
		List<ComboVo> serviceTypeCombos = new ArrayList<>();
		if (StringUtils.equals(useServiceType, CommonConstants.USER_SERVICETYPE_NO_CHECK)) {
			for (DataSourceType dataSourceType : DataSourceTypeManager.getDynamicDataSourceTypes()){
				ComboVo comboVo = new ComboVo();
				comboVo.setCode(dataSourceType.getName());
				comboVo.setCodename(dataSourceType.getText());
				serviceTypeCombos.add(comboVo);
			}
		} else {
			String[] serviceTypes = useServiceType.split(",");
			for (String serviceType : serviceTypes) {
				DataSourceType dataSourceType = DataSourceTypeManager.getDataSourceType(serviceType);
				ComboVo comboVo = new ComboVo();
				comboVo.setCode(dataSourceType.getName());
				comboVo.setCodename(dataSourceType.getText());
				serviceTypeCombos.add(comboVo);
			}
		}

		return serviceTypeCombos;
	}

	@Override
	public List<ComboVo> getFromClientId() {
		return clientEntityService
				.findAll()
				.stream()
				.map(comboMapper::toCombo)
				.collect(Collectors.toList());
	}
}
