package com.eactive.eai.rms.data.entity.onl.eaimsg;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.eactive.eai.data.entity.onl.message.QServiceMessageEntity;
import com.eactive.eai.data.entity.onl.message.ServiceMessageEntity;
import com.eactive.eai.data.entity.onl.message.ServiceMessageEntityId;
import com.eactive.eai.data.entity.onl.transformer.transform.TransformEntity;
import com.eactive.eai.data.jpa.AbstractDataService;
import com.eactive.eai.rms.data.entity.onl.layout.LayoutService;
import com.eactive.eai.rms.data.entity.onl.transform.TransformService;
import com.eactive.eai.rms.onl.common.exception.EMSRuntimeException;
import com.querydsl.core.types.dsl.BooleanExpression;

@Service
@Transactional
public class ServiceMessageService
		extends AbstractDataService<ServiceMessageEntity, ServiceMessageEntityId, ServiceMessageEMSRepository> {

	@Autowired
	private LayoutService layoutService;

	@Autowired
	private TransformService transformService;

	@Override
	public <S extends ServiceMessageEntity> S save(S entity) {
		entity.getEaiReferenceMessages().forEach(e -> {
			if (layoutService.countByLayoutNameAndCurrentUserBusiness(e.getRefmsgidname()) < 1) {
				throw new EMSRuntimeException("Reference Message ID information does not exist. Reference Message ID : "
						+ e.getRefmsgidname());
			}
		});

		return repository.save(entity);
	}

	public Set<ServiceMessageEntity> findByCnvsnname(Set<String> cnvsnNames) {

		QServiceMessageEntity qServiceMessageEntity = QServiceMessageEntity.serviceMessageEntity;

		BooleanExpression predicate = qServiceMessageEntity.chngmsgidname
				.in(cnvsnNames)
				.or(qServiceMessageEntity.bascrspnschngmsgidname.in(cnvsnNames))
				.or(qServiceMessageEntity.errrspnschngmsgidname.in(cnvsnNames));

		return StreamSupport.stream(repository.findAll(predicate).spliterator(), false).collect(Collectors.toSet());
	}

	public List<TransformEntity> findTransform(String eaiSvcName, int svcprcssno, String cnvsnName) {
		Optional<ServiceMessageEntity> serviceMessageEntity = repository.findById(new ServiceMessageEntityId(eaiSvcName, svcprcssno));
		List<TransformEntity> transformEntities = new ArrayList<>();

		if( serviceMessageEntity.isPresent() ){
			addTransformEntity(transformEntities, serviceMessageEntity.get().getChngmsgidname());
			addTransformEntity(transformEntities, serviceMessageEntity.get().getBascrspnschngmsgidname());
			addTransformEntity(transformEntities, serviceMessageEntity.get().getErrrspnschngmsgidname());

			return transformEntities
					.stream()
					.sorted(Comparator.comparing(TransformEntity::getCnvsnname))
					.collect(Collectors.toList());
		} else {
			Optional<TransformEntity> transformEntity = transformService.findById(cnvsnName);
            transformEntity.ifPresent(transformEntities::add);
			return transformEntities;
		}
	}

	private void addTransformEntity(List<TransformEntity> transformEntities, String transformEntityId) {
		if (StringUtils.isBlank(transformEntityId)) {
			return;
		}

		transformService.findById(transformEntityId).ifPresent(transformEntities::add);
	}

}
