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

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.eactive.eai.data.converter.LocalDateTimeFormatters;
import com.eactive.eai.data.entity.onl.unifbwk.QUnifBwkTp;
import com.eactive.eai.data.entity.onl.unifbwk.UnifBwkTp;
import com.eactive.eai.data.jpa.AbstractDataService;
import com.eactive.eai.rms.data.entity.onl.bzwkdstcd.QUserBusiness;
import com.eactive.eai.rms.onl.manage.comm.unifbwk.UnifbwkUISearch;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;

@Service
@Transactional
public class UnifBwkTpService extends AbstractDataService<UnifBwkTp, String, UnifBwkTpEMSRepository> {

	@Override
	public List<UnifBwkTp> findAll() {
		List<UnifBwkTp> list = new ArrayList<>();
		repository.findAll(QUnifBwkTp.unifBwkTp.eaibzwkdstcd.asc()).forEach(list::add);
		return list;
	}

	public List<Map<String, Object>> getRecordAuthListALL() {
		return repository.findAll().stream().map(e -> {
			Map<String, Object> map = new HashMap<>();
			map.put("BZCD", e.getEaibzwkdstcd());
			return map;
		}).collect(Collectors.toList());
	}

	public long selectListCount(String searchBzwkName) {
		BooleanExpression predicate = Optional
				.ofNullable(searchBzwkName)
				.filter(StringUtils::isNotBlank)
				.map(searchName -> QUnifBwkTp.unifBwkTp.eaibzwkdstcd.containsIgnoreCase(searchBzwkName))
				.orElse(null);

		return predicate != null ? repository.count(predicate) : repository.count();
	}

	public Iterable<UnifBwkTp> findAllwithSearch(String searchBzwkName) {
		QUnifBwkTp qUnifBwkTp = QUnifBwkTp.unifBwkTp;
		
		BooleanBuilder builder = new BooleanBuilder();
		
		if(StringUtils.isNotBlank(searchBzwkName)) {
			
			String[] keywords = searchBzwkName.split(",");
			
			for(String keyword : keywords) {
				
				String param = keyword.trim();
				
				BooleanExpression predicate = QUnifBwkTp.unifBwkTp.bzwkdsticname
						.containsIgnoreCase(param)
						.or(qUnifBwkTp.eaibzwkdstcd.containsIgnoreCase(param));
				
				builder.or(predicate);
			}
			
		}

		return repository.findAll(builder, qUnifBwkTp.eaibzwkdstcd.asc());
	}

	public Page<UnifBwkTp> findPageWithSearch(Pageable pageable, UnifbwkUISearch unifbwkUISearch) {
		QUnifBwkTp qUnifBwkTp = QUnifBwkTp.unifBwkTp;
		BooleanExpression predicate = qUnifBwkTp.eaibzwkdstcd
				.containsIgnoreCase(unifbwkUISearch.getSearchEaiBzwkDstcd())
				.and(qUnifBwkTp.applcd.containsIgnoreCase(unifbwkUISearch.getSearchApplCd()))
				.and(qUnifBwkTp.bzwkdsticname.containsIgnoreCase(unifbwkUISearch.getSearchBzwkDsticName()))
				.and(qUnifBwkTp.inputdstcd.contains(unifbwkUISearch.getSearchInputDstCd()));

		if (StringUtils.isNotBlank(unifbwkUISearch.getSearchDiscardYn())) {
			BooleanExpression discardPredicate = getDiscardPredicate(unifbwkUISearch, qUnifBwkTp);
			predicate = predicate.and(discardPredicate);
		}
		return repository.findAll(predicate, pageable);
	}

	private BooleanExpression getDiscardPredicate(UnifbwkUISearch unifbwkUISearch, QUnifBwkTp qUnifBwkTp) {
		String currentDate = LocalDate.now().format(LocalDateTimeFormatters.FORMATTER_YYYYMMDD_8);
		BooleanExpression discardPredicate;

		if ("N".equals(unifbwkUISearch.getSearchDiscardYn())) {
			discardPredicate = qUnifBwkTp.discarddate
					.isNull()
					.or(qUnifBwkTp.discarddate.trim().isEmpty())
					.or(qUnifBwkTp.discarddate.gt(currentDate));
		} else {
			discardPredicate = qUnifBwkTp.discarddate.isNotEmpty().and(qUnifBwkTp.discarddate.loe(currentDate));
		}
		return discardPredicate;
	}

	public long count(BooleanExpression predicate) {
		return repository.count(predicate);
	}

	public long selectCnt(Map<String, String> paramMap) {
		QUnifBwkTp qUnifBwkTp = QUnifBwkTp.unifBwkTp;
		BooleanExpression predicate = qUnifBwkTp.eaibzwkdstcd.eq(paramMap.get("eaiBzwkDstcd"));

		if (StringUtils.isNotBlank(paramMap.get("inputDstCd"))) {
			predicate = predicate.and(qUnifBwkTp.inputdstcd.eq(paramMap.get("inputDstCd")));
		}
		return repository.count(predicate);
	}

	public Iterable<UnifBwkTp> findByInputdstcd(String inputdstcd) {
		BooleanExpression predicate = QUnifBwkTp.unifBwkTp.inputdstcd.eq(inputdstcd);
		return repository.findAll(predicate, QUnifBwkTp.unifBwkTp.eaibzwkdstcd.asc());
	}

	public List<UnifBwkTp> findUserBizCodesByUserId(String userId) {
		JPAQueryFactory queryFactory = getJPAQueryFactory();
		QUnifBwkTp qUnifBwkTp = QUnifBwkTp.unifBwkTp;
		QUserBusiness qUserBusiness = QUserBusiness.userBusiness;

		return queryFactory
				.select(qUnifBwkTp)
				.from(qUnifBwkTp, qUserBusiness)
				.where(qUnifBwkTp.eaibzwkdstcd
						.eq(qUserBusiness.id.eaiBzwkDstcd)
						.and(qUserBusiness.id.userId.eq(userId)))
				.orderBy(qUnifBwkTp.eaibzwkdstcd.asc())
				.fetch();
	}

	public List<UnifBwkTp> findExtBusiness() {
		QUnifBwkTp qUnifBwkTp = QUnifBwkTp.unifBwkTp;
		return getJPAQueryFactory()
				.selectFrom(qUnifBwkTp)
				.where(qUnifBwkTp.inputdstcd.eq("EXT"))
				.orderBy(qUnifBwkTp.eaibzwkdstcd.asc())
				.fetch();
	}

}
