package com.eactive.eai.rms.onl.manage.rule.header;

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

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.entity.onl.stdmessage.StandardMessageLayout;
import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageLayoutDeploy;
import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageLayoutHistory;
import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageLayoutItem;
import com.eactive.eai.rms.common.base.OnlBaseService;
import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.common.util.ModelMapperUtils;
import com.eactive.eai.rms.data.entity.onl.stdmessage.StandardMessageLayoutDeployService;
import com.eactive.eai.rms.data.entity.onl.stdmessage.StandardMessageLayoutHistoryService;
import com.eactive.eai.rms.data.entity.onl.stdmessage.StandardMessageLayoutItemService;
import com.eactive.eai.rms.data.entity.onl.stdmessage.StandardMessageLayoutService;
import com.eactive.eai.rms.onl.manage.rule.header.mapper.StandardMessageLayoutItemMapper;
import com.eactive.eai.rms.onl.manage.rule.header.mapper.StandardMessageLayoutMapper;
import com.eactive.eai.rms.onl.manage.rule.header.vo.StandardMessageLayoutDeployVo;
import com.eactive.eai.rms.onl.manage.rule.header.vo.StandardMessageLayoutHistoryVo;
import com.eactive.eai.rms.onl.manage.rule.header.vo.StandardMessageLayoutItemVo;
import com.eactive.eai.rms.onl.manage.rule.header.vo.StandardMessageLayoutVo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

@Service("standardLayoutService")
@Transactional
public class StandardLayoutService extends OnlBaseService {

	static final String OPERATION_HISTORY_NEW = "NEW";
	static final String OPERATION_HISTORY_MODIFY = "MODIFY";
	static final String OPERATION_HISTORY_DEPLOY = "DEPLOY";
	static final String OPERATION_HISTORY_DELETE = "DELETE";

	/** The monitoring context. */
	@Autowired
	@Qualifier("monitoringContext")
	private MonitoringContext monitoringContext;

	@Autowired
	private StandardMessageLayoutItemService standardMessageLayoutItemService;

	@Autowired
	private StandardMessageLayoutHistoryService standardMessageLayoutHistoryService;

	@Autowired
	private StandardMessageLayoutDeployService standardMessageLayoutDeployService;

	@Autowired
	private StandardMessageLayoutService standardMessageLayoutService;

	@Autowired
	private StandardMessageLayoutMapper standardMessageLayoutMapper;

	@Autowired
	private StandardMessageLayoutItemMapper standardMessageLayoutItemMapper;

	@Autowired
	private ObjectMapper objectMapper;

	public Page<StandardMessageLayoutVo> selectList(Pageable pageable, Map<String, Object> paramMap) {
		return standardMessageLayoutService.findAll(pageable).map(standardMessageLayoutMapper::toVo);
	}

	public StandardMessageLayoutDeployVo selectDeploy() {
		StandardMessageLayoutDeploy deploy = standardMessageLayoutDeployService.findFirst();

		if (deploy == null) {
			return new StandardMessageLayoutDeployVo();
		}

		StandardMessageLayout layout = standardMessageLayoutService.getById(deploy.getLayoutName());
		StandardMessageLayoutDeployVo vo = ModelMapperUtils.map(deploy, StandardMessageLayoutDeployVo.class);
		vo.setLayoutDesc(layout.getLayoutDesc());
		return vo;

	}

	public Page<StandardMessageLayoutHistoryVo> selectHistoryList(Pageable pageable) {
		return ModelMapperUtils
				.mapPage(standardMessageLayoutHistoryService.findAll(pageable), StandardMessageLayoutHistoryVo.class);
	}

	public Map<String, Object> selectDetail(String layoutName) {

		StandardMessageLayout standardMessageLayout = standardMessageLayoutService.getById(layoutName);
		StandardMessageLayoutVo layoutVo = standardMessageLayoutMapper.toVo(standardMessageLayout);

		HashMap<String, Object> result = new HashMap<>();
		result.put("detail", layoutVo);
		result.put("rows", layoutVo.getStandardMessageLayoutItems());
		return result;
	}

	public Map<String, Object> selectHistoryDetail(String operationSeq) throws JsonProcessingException {
		int seq = Integer.parseInt(operationSeq);
		StandardMessageLayoutHistory history = standardMessageLayoutHistoryService.getById(seq);
		StandardMessageLayoutHistoryVo historyVo = ModelMapperUtils.map(history, StandardMessageLayoutHistoryVo.class);

		Map<String, Object> result = new HashMap<>();
		result.put("detail", historyVo);

		String itemListData = history.getItemListData();
		List<Map<String, Object>> list = StringUtils.isBlank(itemListData) ? new ArrayList<>()
				: toItemArray(itemListData);

		result.put("rows", list);
		return result;
	}

	private List<Map<String, Object>> toItemArray(String gridData) throws JsonProcessingException {
		return objectMapper.readValue(gridData, new TypeReference<List<Map<String, Object>>>() {
		});
	}

	public void update(Map<String, Object> paramMap, String sessionUserId, String gridData,
			StandardMessageLayoutVo standardMessageLayoutVo,
			List<StandardMessageLayoutItemVo> standardMessageLayoutItemVos) {

		StandardMessageLayout standardMessageLayout = standardMessageLayoutService
				.getById(standardMessageLayoutVo.getLayoutName());

		standardMessageLayout.getStandardMessageLayoutItems().clear();

		standardMessageLayoutMapper.updateEntity(standardMessageLayoutVo, standardMessageLayout);

		standardMessageLayoutItemVos.forEach(standardMessageLayoutItemVo -> {
			// vo to entity
			StandardMessageLayoutItem standardMessageLayoutItem = standardMessageLayoutItemMapper
					.toEntity(standardMessageLayoutItemVo);
			// set layout
			standardMessageLayoutItem.setStandardMessageLayout(standardMessageLayout);

			// set item
			standardMessageLayout.getStandardMessageLayoutItems().add(standardMessageLayoutItem);
		});

		save(standardMessageLayout, sessionUserId);
		insertHistory(paramMap, OPERATION_HISTORY_MODIFY, gridData);
	}

	public void insert(Map<String, Object> paramMap, String sessionUserId, String gridData,
			StandardMessageLayoutVo standardMessageLayoutVo) {
		StandardMessageLayout standardMessageLayout = standardMessageLayoutMapper.toEntity(standardMessageLayoutVo);

		// item에 layoutName 설정
		standardMessageLayout
				.getStandardMessageLayoutItems()
				.forEach(i -> i.getId().setLayoutName(standardMessageLayout.getLayoutName()));

		standardMessageLayoutService.save(standardMessageLayout);
		save(standardMessageLayout, sessionUserId);
		insertHistory(paramMap, OPERATION_HISTORY_NEW, gridData);
	}

	private void save(StandardMessageLayout standardMessageLayout, String sessionUserId) {
		standardMessageLayout.setWriterName(sessionUserId);
		standardMessageLayoutService.save(standardMessageLayout);
	}

	public void insertHistory(Map<String, Object> paramMap, String operationType, String gridData) {
		StandardMessageLayoutHistory history = objectMapper.convertValue(paramMap, StandardMessageLayoutHistory.class);
		history.setOperationType(operationType);
		history.setItemListData(gridData);
		standardMessageLayoutHistoryService.save(history);
	}

	public void delete(Map<String, Object> paramMap) {
		String layoutName = (String) paramMap.get("layoutName");
		standardMessageLayoutService.deleteById(layoutName);
		standardMessageLayoutItemService.deleteAllByIdLayoutName(layoutName);

		insertHistory(paramMap, OPERATION_HISTORY_DELETE, "");
	}

	public void deploy(Map<String, Object> paramMap, String layoutName) throws JsonProcessingException {
		List<StandardMessageLayoutItem> list = standardMessageLayoutItemService.findByIdLayoutName(layoutName);

		List<StandardMessageLayoutItemVo> voList = list
				.stream()
				.map(standardMessageLayoutItemMapper::toVo)
				.collect(Collectors.toList());

		String gridData = objectMapper.writeValueAsString(voList);

		standardMessageLayoutDeployService.deleteAll(standardMessageLayoutDeployService.findAll());
		StandardMessageLayoutDeploy deploy = new StandardMessageLayoutDeploy();
		deploy.setLayoutName(layoutName);
		standardMessageLayoutDeployService.save(deploy);

		insertHistory(paramMap, OPERATION_HISTORY_DEPLOY, gridData);
	}

}