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

import java.util.List;
import java.util.stream.Collectors;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.eactive.eai.data.entity.onl.adapter.QAdapterGroup;
import com.eactive.eai.data.entity.onl.inflow.InflowControl;
import com.eactive.eai.data.entity.onl.inflow.InflowControlId;
import com.eactive.eai.data.entity.onl.inflow.QInflowControl;
import com.eactive.eai.data.entity.onl.message.QEAIMessageEntity;
import com.eactive.eai.data.jpa.AbstractDataService;
import com.eactive.eai.rms.onl.manage.inflow.inflow.InflowControlManMapper;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.Tuple;
import com.querydsl.jpa.impl.JPAQueryFactory;

@Service
public class InflowControlService extends AbstractDataService<InflowControl, InflowControlId, InflowControlRepository> {

	private static final String ADAPTER_TYPE_INFLOW = "01";

	@PersistenceContext
	EntityManager entityManager;

	@Autowired
	InflowControlManMapper mapper;

	public Page<InflowControlServiceDto> findAllForAdapter(Pageable pageable, String searchName) {
		JPAQueryFactory jpaQueryFactory = new JPAQueryFactory(entityManager);
		QAdapterGroup qAdapterGroup = QAdapterGroup.adapterGroup;
		QInflowControl qInflowControl = QInflowControl.inflowControl;

		BooleanBuilder boolBuilder = new BooleanBuilder();
		if (!StringUtils.isEmpty(searchName))
			boolBuilder.and(qAdapterGroup.adptrbzwkgroupname.contains(searchName));

		BooleanBuilder adapterWherePredicate = new BooleanBuilder(qAdapterGroup.adptriodstcd
				.eq("I")
				.and(qAdapterGroup.adptrcd
						.in("RST", "HTT", "HTC")
						.or(qAdapterGroup.adptrbzwkgroupname
								.like("%_AsS%")
								.or(qAdapterGroup.adptrbzwkgroupname.like("%_AsC%")))));
		boolBuilder.and(adapterWherePredicate);

		List<Tuple> tupleList = jpaQueryFactory
				.select(qAdapterGroup.adptrbzwkgroupname, qAdapterGroup.adptrbzwkgroupdesc, qInflowControl)
				.from(qAdapterGroup)
				.leftJoin(qInflowControl)
				.on(qAdapterGroup.adptrbzwkgroupname
						.eq(qInflowControl.id.name)
						.and(qInflowControl.id.type.eq(ADAPTER_TYPE_INFLOW)))
				.where(boolBuilder)
				.orderBy(qAdapterGroup.adptrbzwkgroupname.asc())
				.offset(pageable.getOffset())
				.limit(pageable.getPageSize())
				.fetch();
		List<InflowControlServiceDto> dtoList = tupleList
				.stream()
				.map(tuple -> toDto(qAdapterGroup, qInflowControl, tuple))
				.collect(Collectors.toList());

		long totalCount = jpaQueryFactory
				.select(qAdapterGroup.adptrbzwkgroupname.count())
				.from(qAdapterGroup)
				.where(boolBuilder)
				.fetchOne();

		return new PageImpl<>(dtoList, pageable, totalCount);
	}

	private InflowControlServiceDto toDto(QAdapterGroup qAdapterGroup, QInflowControl qInflowControl, Tuple tuple) {
		InflowControlServiceDto dto = null;
		if (tuple.get(qInflowControl) != null)
			dto = mapper.toDto(tuple.get(qInflowControl));
		else {
			dto = new InflowControlServiceDto();
			dto.setName(tuple.get(qAdapterGroup.adptrbzwkgroupname));
			dto.setType(ADAPTER_TYPE_INFLOW);
		}
		dto.setDesc(tuple.get(qAdapterGroup.adptrbzwkgroupdesc));
		return dto;
	}

	public InflowControlServiceDto findByIdForAdapter(String adptrbzwkgroupname) {
		JPAQueryFactory jpaQueryFactory = new JPAQueryFactory(entityManager);
		QAdapterGroup qAdapterGroup = QAdapterGroup.adapterGroup;
		QInflowControl qInflowControl = QInflowControl.inflowControl;

		Tuple tuple = jpaQueryFactory
				.select(qAdapterGroup.adptrbzwkgroupname, qAdapterGroup.adptrbzwkgroupdesc, qInflowControl)
				.from(qAdapterGroup)
				.leftJoin(qInflowControl)
				.on(qAdapterGroup.adptrbzwkgroupname
						.eq(qInflowControl.id.name)
						.and(qInflowControl.id.type.eq(ADAPTER_TYPE_INFLOW)))
				.where(qAdapterGroup.adptrbzwkgroupname.eq(adptrbzwkgroupname))
				.fetchOne();

		return toDto(qAdapterGroup, qInflowControl, tuple);
	}

	public Page<InflowControlServiceDto> findAllForInterface(Pageable pageable, String searchName) {
		JPAQueryFactory jpaQueryFactory = new JPAQueryFactory(entityManager);
		QInflowControl qInflowControl = QInflowControl.inflowControl;
		QEAIMessageEntity qEAIMessageEntity = QEAIMessageEntity.eAIMessageEntity;

		List<Tuple> tupleList = jpaQueryFactory
				.select(qInflowControl, qEAIMessageEntity.eaisvcname, qEAIMessageEntity.eaisvcdesc)
				.from(qEAIMessageEntity)
				.leftJoin(qInflowControl)
				.on(qInflowControl.id.type.eq("02").and(qInflowControl.id.name.eq(qEAIMessageEntity.eaisvcname)))
				.where(qEAIMessageEntity.eaisvcname.contains(searchName))
				.orderBy(qEAIMessageEntity.eaisvcname.asc())
				.offset(pageable.getOffset())
				.limit(pageable.getPageSize())
				.fetch();

		List<InflowControlServiceDto> dtoList = tupleList
				.stream()
				.map(tuple -> toDto(qEAIMessageEntity, qInflowControl, tuple))
				.collect(Collectors.toList());

		long totalCount = jpaQueryFactory
				.select(qEAIMessageEntity.eaisvcname.count())
				.from(qEAIMessageEntity)
				.where(qEAIMessageEntity.eaisvcname.contains(searchName))
				.fetchOne();
		return new PageImpl<>(dtoList, pageable, totalCount);
	}

	private InflowControlServiceDto toDto(QEAIMessageEntity qEAIMessageEntity, QInflowControl qInflowControl,
			Tuple tuple) {
		InflowControlServiceDto dto = null;
		if (tuple.get(qInflowControl) != null)
			dto = mapper.toDto(tuple.get(qInflowControl));
		else {
			dto = new InflowControlServiceDto();
			dto.setName(tuple.get(qEAIMessageEntity.eaisvcname));
			dto.setType(ADAPTER_TYPE_INFLOW);
		}
		dto.setDesc(tuple.get(qEAIMessageEntity.eaisvcdesc));
		return dto;
	}

	public InflowControlServiceDto findByIdForInterface(String eaisvcname) {
		JPAQueryFactory jpaQueryFactory = new JPAQueryFactory(entityManager);
		QInflowControl qInflowControl = QInflowControl.inflowControl;
		QEAIMessageEntity qEAIMessageEntity = QEAIMessageEntity.eAIMessageEntity;

		Tuple tuple = jpaQueryFactory
				.select(qInflowControl, qEAIMessageEntity.eaisvcname, qEAIMessageEntity.eaisvcdesc)
				.from(qEAIMessageEntity)
				.leftJoin(qInflowControl)
				.on(qInflowControl.id.type.eq("02").and(qInflowControl.id.name.eq(qEAIMessageEntity.eaisvcname)))
				.where(qEAIMessageEntity.eaisvcname.eq(eaisvcname))
				.fetchOne();

		return toDto(qEAIMessageEntity, qInflowControl, tuple);
	}

}
