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

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import javax.transaction.Transactional;

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

import com.eactive.eai.data.entity.onl.adapter.Adapter;
import com.eactive.eai.data.entity.onl.adapter.AdapterGroup;
import com.eactive.eai.data.entity.onl.adapter.QAdapter;
import com.eactive.eai.data.entity.onl.adapter.QAdapterGroup;
import com.eactive.eai.data.entity.onl.adapter.QAdapterProp;
import com.eactive.eai.data.entity.onl.adapter.QAdapterPropGroup;
import com.eactive.eai.data.jpa.AbstractDataService;
import com.eactive.eai.rms.data.entity.onl.bzwkdstcd.UserBusinessService;
import com.eactive.eai.rms.onl.manage.adapter.adapter.ui.AdapterGroupUISearch;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.impl.JPAQuery;

@Service
@Transactional
public class AdapterGroupService extends AbstractDataService<AdapterGroup, String, AdapterGroupEMSRepository> {

	@Autowired
	private UserBusinessService userBusinessService;

	public Page<AdapterGroup> findPage(Pageable pageable, AdapterGroupUISearch adapterGroupUISearch) {

		QAdapterGroup qAdapterGroup = QAdapterGroup.adapterGroup;

		List<String> userBusiness = userBusinessService.getCurrentUserBusinessCodes();
		BooleanExpression predicate = qAdapterGroup.eaibzwkdstcd.in(userBusiness);

		if (StringUtils.isNotBlank(adapterGroupUISearch.getSearchAdptrMsgPtrnCd())) {
			predicate = predicate.and(qAdapterGroup.adptrmsgptrncd.eq(adapterGroupUISearch.getSearchAdptrMsgPtrnCd()));
		}

		if (StringUtils.isNotBlank(adapterGroupUISearch.getSearchAdptrUseYn())) {
			predicate = predicate.and(qAdapterGroup.adptruseyn.eq(adapterGroupUISearch.getSearchAdptrUseYn()));
		}

		if (StringUtils.isNotBlank(adapterGroupUISearch.getSearchAdptrBzwkGroupName())) {
			predicate = predicate
					.and(qAdapterGroup.adptrbzwkgroupname
							.containsIgnoreCase(adapterGroupUISearch.getSearchAdptrBzwkGroupName()));
		}

		if (StringUtils.isNotBlank(adapterGroupUISearch.getSearchAdptrBzwkGroupDesc())) {
			predicate = predicate
					.and(qAdapterGroup.adptrbzwkgroupdesc
							.containsIgnoreCase(adapterGroupUISearch.getSearchAdptrBzwkGroupDesc()));
		}

		if (StringUtils.isNotBlank(adapterGroupUISearch.getSearchAdptrIoDstCd())) {
			predicate = predicate.and(qAdapterGroup.adptriodstcd.eq(adapterGroupUISearch.getSearchAdptrIoDstCd()));
		}

		if (StringUtils.isNotBlank(adapterGroupUISearch.getSearchEaiBzwkDstcd())) {
			predicate = predicate.and(qAdapterGroup.eaibzwkdstcd.eq(adapterGroupUISearch.getSearchEaiBzwkDstcd()));
		}

		if (StringUtils.isNotBlank(adapterGroupUISearch.getSearchAdptrMsgDstCd())) {
			predicate = predicate.and(qAdapterGroup.adptrmsgdstcd.eq(adapterGroupUISearch.getSearchAdptrMsgDstCd()));
		}

		return repository.findAll(predicate, pageable);
	}

	public Iterable<AdapterGroup> findByAdptrIoDstcd(String adptrIoDstcd) {
		QAdapterGroup ag = QAdapterGroup.adapterGroup;
		BooleanExpression ex1 = ag.adptrbzwkgroupname.contains("_IO_");
		BooleanExpression ex2 = ag.adptrbzwkgroupname.contains("_IO{");
		BooleanExpression ex3 = ag.adptrbzwkgroupname.contains("_" + adptrIoDstcd + "_");

		return repository.findAll(ex1.or(ex2).or(ex3));
	}

	public List<Adapter> updateSingleNode(String node) {
		QAdapterGroup qAdapterGroup = QAdapterGroup.adapterGroup;
		QAdapter qAdapter = QAdapter.adapter;

		List<AdapterGroup> adpaterGroups = getJPAQueryFactory()
				.select(qAdapterGroup)
				.from(qAdapterGroup)
				.join(qAdapter)
				.where(qAdapterGroup.adptrbzwkgroupname
						.contains("NET_AsC")
						.or(qAdapterGroup.adptrbzwkgroupname.contains("NET_SyC")))
				.where(qAdapterGroup.adptruseyn.eq("1"))
				.where(qAdapter.eaisevrinstncname.ne("ALL"))
				.fetch();

		List<Adapter> adpaters = new ArrayList<>();

		adpaterGroups.stream().flatMap(adpaterGroup -> adpaterGroup.getAdapters().stream()).forEach(adapter -> {
			String eaisevrinstncname = adapter.getEaisevrinstncname();
			eaisevrinstncname = StringUtils.substring(eaisevrinstncname, 0, 9) + node
					+ StringUtils.substring(eaisevrinstncname, 10, 11);
			adapter.setEaisevrinstncname(eaisevrinstncname);

			adpaters.add(adapter);
		});

		return adpaters;
	}

	public List<AdapterGroup> findByAdptrcd(String adptrcd) {
		return repository.findByAdptrcd(adptrcd, Sort.by("adptrbzwkgroupname"));
	}

	public Optional<String> getSocketMonitorPort(String eaisevrinstncname) {

		QAdapterGroup qAdapterGroup = QAdapterGroup.adapterGroup;
		QAdapter qAdapter = QAdapter.adapter;
		QAdapterPropGroup qAdapterPropGroup = QAdapterPropGroup.adapterPropGroup;
		QAdapterProp qAdapterProp = QAdapterProp.adapterProp;

		JPAQuery<String> query = getJPAQueryFactory()
				.select(qAdapterProp.prpty2val)
				.from(qAdapterGroup)
				.innerJoin(qAdapterGroup.adapters, qAdapter)
				.innerJoin(qAdapter.adapterPropGroup, qAdapterPropGroup)
				.innerJoin(qAdapterPropGroup.adapterProps, qAdapterProp);

		query.where(qAdapter.eaisevrinstncname.eq(eaisevrinstncname));
		query.where(qAdapterProp.id.prptyname.eq("port.number"));
		query.where(qAdapterGroup.adptrbzwkgroupname.contains("SOCKET_MONITOR"));

		return Optional.ofNullable(query.fetchFirst());

//		
//
//		AdapterGroup socketMonitorAdapterGroup = repository.getReferenceById("SOCKET_MONITOR");
//
//		Optional<Adapter> adapterOptional = socketMonitorAdapterGroup
//				.getAdapters()
//				.stream()
//				.filter(adapter -> StringUtils.equals(adapter.getEaisevrinstncname(), eaisevrinstncname))
//				.findAny();
//
//		if (!adapterOptional.isPresent()) {
//			return Optional.ofNullable(null);
//		}
//
//		// socket port number set
//		return adapterOptional
//				.get()
//				.getAdapterPropGroup()
//				.getAdapterProps()
//				.stream()
//				.filter(prop -> "port.number".equals(prop.getId().getPrptyname()))
//				.findAny()
//				.map(AdapterProp::getPrpty2val);

	}

	public List<String> findAdptrBzwkGroupNamesByPort(String searchAdptrBzwkGroupName, String searchPortNum) {
		QAdapterGroup qAdapterGroup = QAdapterGroup.adapterGroup;
		QAdapter qAdapter = QAdapter.adapter;
		QAdapterPropGroup qAdapterPropGroup = QAdapterPropGroup.adapterPropGroup;
		QAdapterProp qAdapterProp = QAdapterProp.adapterProp;

		JPAQuery<String> query = getJPAQueryFactory()
				.selectDistinct(qAdapterGroup.adptrbzwkgroupname)
				.from(qAdapterGroup)
				.innerJoin(qAdapterGroup.adapters, qAdapter)
				.innerJoin(qAdapter.adapterPropGroup, qAdapterPropGroup)
				.innerJoin(qAdapterPropGroup.adapterProps, qAdapterProp);

		query.where(qAdapterProp.id.prptyname.eq("port.number"));

		if (StringUtils.isNotBlank(searchAdptrBzwkGroupName)) {
			query.where(qAdapterGroup.adptrbzwkgroupname.containsIgnoreCase(searchAdptrBzwkGroupName));
		}

		if (StringUtils.isNotBlank(searchPortNum)) {
			query.where(qAdapterProp.prpty2val.contains(searchPortNum));
		}

		return query.fetch();
	}

	public List<AdapterGroup> findByAdptruseyn(boolean useYn) {
		QAdapterGroup qAdapterGroup = QAdapterGroup.adapterGroup;
		JPAQuery<AdapterGroup> query = getJPAQueryFactory().selectFrom(qAdapterGroup);

		if (useYn) {
			query.where(qAdapterGroup.adptruseyn.eq("1"));
		} else {
			query.where(qAdapterGroup.adptruseyn.ne("1"));
		}

		query.orderBy(qAdapterGroup.adptrbzwkgroupname.asc());

		return query.fetch();
	}

	public List<String> findAdptrNode() {
		QAdapterGroup qAdapterGroup = QAdapterGroup.adapterGroup;

		JPAQuery<String> query = getJPAQueryFactory().selectDistinct(qAdapterGroup.adptrbzwkgroupname.substring(1, 4))
				.from(qAdapterGroup)
				.where(qAdapterGroup.adptrmsgptrncd.eq("N")
						.and(qAdapterGroup.adptrbzwkgroupname.ne("SOCKET_MONITOR")
								.or(qAdapterGroup.adptrbzwkgroupname.like("_SIM%"))))
				.orderBy(qAdapterGroup.adptrbzwkgroupname.substring(1, 4).asc());

		return query.fetch();
	}

	public List<String> findAdptrNodeChnl(String chnnl) {
		QAdapterGroup qAdapterGroup = QAdapterGroup.adapterGroup;

		JPAQuery<String> query = getJPAQueryFactory()
				// .selectDistinct(qAdapterGroup.adptrbzwkgroupname.substring(qAdapterGroup.adptrbzwkgroupname.indexOf("_").add(1),
				// qAdapterGroup.adptrbzwkgroupname.indexOf("_").add(4)))
				.selectDistinct(qAdapterGroup.adptrbzwkgroupname.substring(1, 4)).from(qAdapterGroup)
				.where(qAdapterGroup.adptrmsgptrncd.eq("N")
						.and(qAdapterGroup.adptrbzwkgroupname.ne("SOCKET_MONITOR")
								.or(qAdapterGroup.adptrbzwkgroupname.like("_SIM%"))))
				.where(Expressions.stringTemplate("UPPER({0})", qAdapterGroup.adptrbzwkgroupname.substring(2, 4))
						.likeIgnoreCase("%" + chnnl + "%"))
				.orderBy(qAdapterGroup.adptrbzwkgroupname.substring(1, 4).asc());

		return query.fetch();
	}

	public List<AdapterGroup> findByAdptrinsticodeNotEmpty() {
		QAdapterGroup qAdapterGroup = QAdapterGroup.adapterGroup;

		JPAQuery<AdapterGroup> query = getJPAQueryFactory()
				.selectFrom(qAdapterGroup)
				.where(qAdapterGroup.adptrinsticode.isNotNull()
						.and(qAdapterGroup.adptrinsticode.ne("")))
				.orderBy(qAdapterGroup.adptrbzwkgroupname.asc());

		return query.fetch();
	}
	
	public AdapterGroup saveAndFlush(AdapterGroup adapterGroup) {
        return repository.saveAndFlush(adapterGroup);
    }
}
