package com.eactive.eai.rms.common.acl.monitoringCode;

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

import lombok.RequiredArgsConstructor;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.eactive.apim.portal.monitoringcode.entity.MonitoringCode;
import com.eactive.apim.portal.monitoringcode.entity.MonitoringCodeGroup;
import com.eactive.eai.rms.common.acl.monitoringCode.UI.MonitoringCodeGroupUI;
import com.eactive.eai.rms.common.acl.monitoringCode.UI.MonitoringCodeGroupUISearch;
import com.eactive.eai.rms.common.acl.monitoringCode.UI.MonitoringCodeSearchPOPUI;
import com.eactive.eai.rms.common.acl.monitoringCode.UI.MonitoringCodeUI;
import com.eactive.eai.rms.common.base.BaseService;
import com.eactive.eai.rms.common.spring.LocaleMessage;
import com.eactive.eai.rms.data.entity.man.monitoringCode.service.MonitoringCodeGroupService;
import com.eactive.eai.rms.data.entity.man.monitoringCode.service.MonitoringCodeService;
import com.eactive.eai.rms.onl.common.exception.BizException;

@Service
@Transactional(transactionManager = "transactionManagerForEMS")
@RequiredArgsConstructor
public class MonitoringCodeManService extends BaseService {

	private final MonitoringCodeService monitoringCodeService;
	private final MonitoringCodeGroupService monitoringCodeGroupService;
	private final MonitoringCodeMapper monitoringCodeMapper;
	private final MonitoringCodeGroupMapper monitoringCodeGroupMapper;
	private final LocaleMessage localeMessage;

	public List<MonitoringCodeGroupUI> selectCodeGroupList(MonitoringCodeGroupUISearch monitoringCodeGroupUISearch) {
		return monitoringCodeGroupService.selectCodeGroupList(monitoringCodeGroupUISearch).stream()
				.map(monitoringCodeGroupMapper::toVo).collect(Collectors.toList());
	}

	public List<MonitoringCodeUI> selectCodeTreeList(MonitoringCodeGroupUISearch search) {
		List<MonitoringCodeGroup> groupList = monitoringCodeGroupService.selectCodeGroupList(search.getSearchCodeGroup());
		List<MonitoringCodeUI> codeTreeList = new ArrayList<>();

		for (MonitoringCodeGroup group : groupList) {
			if (group.getCodeGroup().equals(search.getSearchCodeGroup())) {
				codeTreeList.add(createRootCodeUI(group));
			}
			List<MonitoringCode> codeList = monitoringCodeService.findByIdCodegroup(group.getCodeGroup(), "id.code");
			codeTreeList.addAll(codeList.stream()
					.filter(code -> isCodeMatched(code, search))
					.map(code -> createCodeUI(code, 1)).collect(Collectors.toList()));
		}
		return codeTreeList;
	}

	/* rootCode */
	public MonitoringCodeUI createRootCodeUI(MonitoringCodeGroup group) {
		MonitoringCodeUI rootCodeUI = new MonitoringCodeUI();
		rootCodeUI.setCode(group.getCodeGroup());
		rootCodeUI.setLevel(0);
		rootCodeUI.setUseYn("N");
		rootCodeUI.setUseYnName("");
		rootCodeUI.setCodeGroup(group.getCodeGroup());
		rootCodeUI.setId(group.getCodeGroup());
		rootCodeUI.setCodeName("");
		rootCodeUI.setSeq(0);
		return rootCodeUI;
	}

	/* findByIdCodegroup level=1 */
	private MonitoringCodeUI createCodeUI(MonitoringCode code, int level) {
		MonitoringCodeUI codeUI = new MonitoringCodeUI(code, level);

		if ("Y".equals(code.getUseYn())) {
			codeUI.setUseYnName(localeMessage.getString("combo.usey"));
		} else if ("N".equals(code.getUseYn())) {
			codeUI.setUseYnName(localeMessage.getString("combo.usen"));
		}
		return codeUI;
	}

	private boolean isCodeMatched(MonitoringCode code, MonitoringCodeGroupUISearch search) {
		return (StringUtils.isBlank(search.getSearchCode())
				|| StringUtils.containsIgnoreCase(code.getId().getCode(), search.getSearchCode()))
				&& (StringUtils.isBlank(search.getSearchCodeName())
				|| StringUtils.containsIgnoreCase(code.getCodeName(), search.getSearchCodeName()));
	}

	/* Start CODEGROUP 입력,수정,삭제 */
	public void insertGroup(MonitoringCodeGroupUI monitoringCodeGroupUI) {
		if (monitoringCodeGroupService.existsById(monitoringCodeGroupUI.getCdGroup())) {
			throw new BizException(localeMessage.getString("monitoringCode.codeGroupExists"));
		}
		MonitoringCodeGroup monitoringCodeGroup = monitoringCodeGroupMapper.toEntity(monitoringCodeGroupUI);
		monitoringCodeGroupService.save(monitoringCodeGroup);
	}

	public void updateGroup(MonitoringCodeGroupUI monitoringCodeGroupUI) {
		MonitoringCodeGroup monitoringCodeGroup = monitoringCodeGroupService.getById(monitoringCodeGroupUI.getCdGroup());
		monitoringCodeGroupMapper.updateToEntity(monitoringCodeGroupUI, monitoringCodeGroup);
		monitoringCodeGroupService.save(monitoringCodeGroup);
	}

	public void deleteGroup(String cdGroup) {
		monitoringCodeGroupService.deleteById(cdGroup);
	}

	/* Start CODE 입력,수정,삭제 */
	public void insert(MonitoringCodeUI monitoringCodeUI) {
		if (monitoringCodeService.existsById(monitoringCodeMapper.toId(monitoringCodeUI))) {
			throw new BizException(localeMessage.getString("monitoringCode.codeExists"));
		}
		MonitoringCode monitoringCode = monitoringCodeMapper.toEntity(monitoringCodeUI);
		monitoringCodeService.save(monitoringCode);
	}

	public void update(MonitoringCodeUI monitoringCodeUI) {
		MonitoringCode monitoringCode = monitoringCodeService.getById(monitoringCodeMapper.toId(monitoringCodeUI));
		monitoringCodeMapper.updateToEntity(monitoringCodeUI, monitoringCode);
		monitoringCodeService.save(monitoringCode);
	}

	public void delete(MonitoringCodeUI monitoringCodeUI) {
		MonitoringCode monitoringCode = monitoringCodeService.getById(monitoringCodeMapper.toId(monitoringCodeUI));
		MonitoringCodeGroup monitoringCodeGroup = monitoringCode.getMonitoringCodeGroup();

		if (monitoringCodeGroup != null) {
			monitoringCodeGroup.getMonitoringCodes().remove(monitoringCode);
			monitoringCodeService.deleteById(monitoringCode.getId());
		}
	}

	public Page<MonitoringCodeSearchPOPUI> selectPopList(Pageable pageable,
														 MonitoringCodeSearchPOPUI monitoringCodePOPUI) {
		Page<MonitoringCode> page = monitoringCodeService.findAll(pageable, monitoringCodePOPUI.getCodeGroup(),
				monitoringCodePOPUI.getSearchCodeName());
		return page.map(code -> {
			MonitoringCodeSearchPOPUI ui = new MonitoringCodeSearchPOPUI();
			ui.setCode(code.getId().getCode());
			ui.setCodeName(code.getCodeName());
			return ui;
		});
	}

}
