package com.eactive.eai.rms.onl.manage.control.log.instigroup;

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

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

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.restrict.QRestrictInfoLog;
import com.eactive.eai.rms.data.entity.onl.restrict.RestrictInfoLogService;
import com.eactive.eai.rms.onl.manage.control.log.ControlLogManUISearch;
import com.eactive.eai.rms.onl.manage.control.log.ControlLogService;
import com.eactive.eai.rms.onl.manage.control.log.ControlLogServiceDto;
import com.querydsl.core.Tuple;
import com.querydsl.jpa.impl.JPAQueryFactory;

@Service
public class InstiGroupControlLogService extends RestrictInfoLogService implements ControlLogService {

	@PersistenceContext
	private EntityManager entityManager;

	public Page<ControlLogServiceDto> findALLGroupBy(Pageable pageable, ControlLogManUISearch uiSearch) {
		JPAQueryFactory jpaQueuryFactory = new JPAQueryFactory(entityManager);
		QRestrictInfoLog qLog = QRestrictInfoLog.restrictInfoLog;
		List<Tuple> groupByCount = jpaQueuryFactory
				.select(qLog.id.eaibzwkdstcd, qLog.eaiosidinsticd, qLog.eaiosidinsticd.count())
				.from(qLog)
				.where(qLog.id.msgdpstyms
						.between(uiSearch.getSearchStartDate() + BETWEEN_START_HHmmssSSS,
								uiSearch.getSearchEndDate() + BETWEEN_END_HHmmssSSS)
						.and(qLog.eaiosidinsticd.trim().isNotEmpty()))
				.groupBy(qLog.id.eaibzwkdstcd, qLog.eaiosidinsticd)
				.orderBy(qLog.id.eaibzwkdstcd.asc(), qLog.eaiosidinsticd.asc())
				.offset(pageable.getOffset())
				.limit(pageable.getPageSize())
				.fetch();

		List<ControlLogServiceDto> dtoList = instiTupleToDtoList(qLog, groupByCount);
		Map<String, String> adapterBizDesc = this.findAdapterOsidInstiNoOfLog(dtoList);
		for (ControlLogServiceDto dto : dtoList)
			dto.setInstiname(adapterBizDesc.get(dto.getEaiosidinsticd()));

		long totalCount = jpaQueuryFactory
				.select(qLog.count())
				.from(qLog)
				.where(qLog.id.msgdpstyms
						.between(uiSearch.getSearchStartDate() + BETWEEN_START_HHmmssSSS,
								uiSearch.getSearchEndDate() + BETWEEN_END_HHmmssSSS)
						.and(qLog.eaiosidinsticd.trim().isNotEmpty()))
				.groupBy(qLog.id.eaibzwkdstcd, qLog.eaiosidinsticd)
				.fetch()
				.size();

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

	public List<ControlLogServiceDto> findALLGroupBy(ControlLogManUISearch uiSearch) {
		JPAQueryFactory jpaQueuryFactory = new JPAQueryFactory(entityManager);
		QRestrictInfoLog qLog = QRestrictInfoLog.restrictInfoLog;
		List<Tuple> groupByCount = jpaQueuryFactory
				.select(qLog.id.eaibzwkdstcd, qLog.eaiosidinsticd, qLog.eaiosidinsticd.count())
				.from(qLog)
				.where(qLog.id.msgdpstyms
						.between(uiSearch.getSearchStartDate() + BETWEEN_START_HHmmssSSS,
								uiSearch.getSearchEndDate() + BETWEEN_END_HHmmssSSS)
						.and(qLog.eaiosidinsticd.trim().isNotEmpty()))
				.groupBy(qLog.id.eaibzwkdstcd, qLog.eaiosidinsticd)
				.orderBy(qLog.id.eaibzwkdstcd.asc(), qLog.eaiosidinsticd.asc())
				.fetch();

		List<ControlLogServiceDto> dtoList = instiTupleToDtoList(qLog, groupByCount);
		Map<String, String> adapterBizDesc = this.findAdapterOsidInstiNoOfLog(dtoList);
		for (ControlLogServiceDto dto : dtoList)
			dto.setInstiname(adapterBizDesc.get(dto.getEaiosidinsticd()));

		return dtoList;
	}

	private List<ControlLogServiceDto> instiTupleToDtoList(QRestrictInfoLog qLog, List<Tuple> groupByCount) {
		return groupByCount.stream().map(tuple -> {
			ControlLogServiceDto dto = new ControlLogServiceDto();
			dto.setEaibzwkdstcd(tuple.get(qLog.id.eaibzwkdstcd));
			dto.setEaiosidinsticd(tuple.get(qLog.eaiosidinsticd));
			dto.setCnt(tuple.get(qLog.eaiosidinsticd.count()).toString());
			return dto;
		}).collect(Collectors.toList());
	}

	private Map<String, String> findAdapterOsidInstiNoOfLog(List<ControlLogServiceDto> foundDtoList) {
		if (foundDtoList.isEmpty())
			return new HashMap<>();

		List<String> foundOsidInstiNoList = foundDtoList
				.stream()
				.map(dto -> dto.getEaiosidinsticd())
				.distinct()
				.collect(Collectors.toList());
		QAdapterGroup qAdapterGroup = QAdapterGroup.adapterGroup;
		JPAQueryFactory jpaQueuryFactory = new JPAQueryFactory(entityManager);
		List<Tuple> tupleList = jpaQueuryFactory
				.selectDistinct(qAdapterGroup.osidinstino, qAdapterGroup.adptrbzwkgroupdesc)
				.from(qAdapterGroup)
				.where(qAdapterGroup.osidinstino.in(foundOsidInstiNoList))
				.fetch();

		return tupleList
				.stream()
				.collect(Collectors
						.toMap(tuple -> tuple.get(qAdapterGroup.osidinstino),
								tuple -> tuple.get(qAdapterGroup.adptrbzwkgroupdesc),
								(osidinstino1, osidinstino2) -> osidinstino1));
	}

}
