package com.prolog.cs.biz.inbound.service.impl.failure;

import com.prolog.cs.biz.inbound.constant.OperationConstant;
import com.prolog.cs.biz.inbound.dao.failure.ExceptionLogMapper;
import com.prolog.cs.biz.inbound.dto.PageParam;
import com.prolog.cs.biz.inbound.dto.failure.ExceptionLinesDTO;
import com.prolog.cs.biz.inbound.dto.failure.ExceptionLogDTO;
import com.prolog.cs.biz.inbound.dto.failure.ExceptionLogQueryDTO;
import com.prolog.cs.biz.inbound.dto.failure.ExceptionLogQueryVO;
import com.prolog.cs.biz.inbound.model.failure.ExceptionLog;
import com.prolog.cs.biz.inbound.service.failure.ExceptionLogService;
import com.prolog.cs.biz.inbound.service.impl.BaseServiceImpl;
import com.prolog.cs.biz.inbound.utils.ObjectUtils;
import com.prolog.cs.biz.inbound.utils.UserUtils;
import com.prolog.framework.authority.core.dto.UserDTO;
import com.prolog.framework.beans.BeanUtils;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.framework.utils.AssertUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.Validator;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class ExceptionLogServiceImpl extends BaseServiceImpl<ExceptionLog> implements ExceptionLogService {

	@Resource
	private ExceptionLogMapper mapper;

	@Resource
	private UserUtils userUtils;

	@Resource
	private Validator validator;

	private static final String SERVICE_MSG = "异常日志业务";
	private static Logger log = LoggerFactory.getLogger(ExceptionLogServiceImpl.class);

	@Override
	public ExceptionLogQueryDTO infoByPkId(String pkId) {
		// 详情查询
		AssertUtils.isNotBlank(pkId,
				SERVICE_MSG + OperationConstant.INFO_QUERY_OPERATION + OperationConstant.PK_NULL_MSG);
		return this.mapper.findByPkId(pkId);
	}

	@Override
	public Page<ExceptionLogQueryDTO> findList(ExceptionLogQueryVO queryVO) {
		// 条件分页
		AssertUtils.notNull(queryVO,
				SERVICE_MSG + OperationConstant.PAGE_QUERY_OPERATION + OperationConstant.QUERY_OBJ_NULL_MSG);
		this.startPage(queryVO);
		List<ExceptionLogQueryDTO> list = this.mapper.findList(queryVO);
		return PageUtils.getPage(list);
	}

	@Transactional
	@Override
	public Object saveList(List<ExceptionLinesDTO> exceptionLineDTOList, UserDTO userDTO, Date now) {
		AssertUtils.notNull(exceptionLineDTOList, "批量保存日志失败!异常的数据集合为空!");
		if (ObjectUtils.isNull(userDTO))
			userDTO = userUtils.getUserDTO();
		if (ObjectUtils.isNull(now))
			now = new Date();
		boolean editFlag = false;
		for (ExceptionLinesDTO exceptionLinesDTO : exceptionLineDTOList) {
			ExceptionLog model = new ExceptionLog();
			BeanUtils.copyProperties(exceptionLinesDTO, model);
//			String nodeTaskId = exceptionLinesDTO.getNodeTaskId();
			this.buildDefaultField(model, editFlag, userDTO, now);
			this.setBaseSysField(model, editFlag, userDTO, now);
			this.mapper.save(model);
		}
		return true;
	}

	private void buildDefaultField(ExceptionLog model, boolean editFlag, UserDTO userDTO, Date now) {
		// 保存默认值
		String executorUser = model.getExecutorUser();
		Date executorDate = model.getExecutorDate();
		if (ObjectUtils.isNull(executorUser))
			model.setExecutorUser(userDTO.getUsername());
		if (ObjectUtils.isNull(executorDate))
			model.setExecutorDate(now);

	}

	@Override
	public Object add(ExceptionLogDTO exceptionLogDTO) {
		// TODO vaildate
		UserDTO userDTO = userUtils.getUserDTO();
		ExceptionLog exceptionLog = new ExceptionLog();
		BeanUtils.copyProperties(exceptionLogDTO, exceptionLog);
		this.vaildateModel(exceptionLog, false, userDTO);
		this.buildField(exceptionLog, false, userDTO);
		this.mapper.save(exceptionLog);
		return "";
	}

	@Override
	public Object edit(String pkId, ExceptionLogDTO exceptionLogDTO) {
		// TODO
		UserDTO userDTO = userUtils.getUserDTO();
		ExceptionLog exceptionLog = new ExceptionLog();
		BeanUtils.copyProperties(exceptionLogDTO, exceptionLog);
		this.vaildateModel(exceptionLog, true, userDTO);
		this.buildField(exceptionLog, true, userDTO);
		this.mapper.updateWithValidate(exceptionLog,
				p -> ObjectUtils.isNotNull(p) && ObjectUtils.isNotNull(p.getValue()));
		return "";
	}

	@Override
	@Transactional
	public Object delIds(List<String> pkIdList) {
		// TODO
		pkIdList.stream().filter(p -> canEdit(p)).forEach(p -> this.mapper.deleteById(p, ExceptionLog.class));
		return "";
	}

	@Override
	public Object deletePkId(String pkId) {
		// TODO
		if (canEdit(pkId))
			throw new BizException("can not del");
		this.mapper.deleteById(pkId, ExceptionLog.class);
		return "";
	}

	@Override
	public Page<ExceptionLogDTO> findList(ExceptionLogDTO exceptionLogDTO, PageParam pageParam) {
		Criteria criteria = Criteria.forClass(ExceptionLog.class);
		Integer pageNum = null;
		Integer pageSize = null;
		Restriction r = null;
		if (pageParam == null) {
			pageNum = PageParam.DEFAULT_PAGE_NUM;
			pageSize = PageParam.DEFAULT_PAGE_SIZE;
		} else {
			pageNum = pageParam.getPageNum();
			pageSize = pageParam.getPageSize();
			ExceptionLogDTO condition = exceptionLogDTO;
			r = buildCondition(condition);
		}
		if (pageNum == null || pageNum == 0) {
			pageNum = PageParam.DEFAULT_PAGE_NUM;
		}
		if (pageSize == null || pageSize == 0) {
			pageSize = PageParam.DEFAULT_PAGE_SIZE;
		}
		criteria.setRestriction(r);
		Order order = Order.newInstance().desc("gmtModified");
		criteria.setOrder(order);
		PageUtils.startPage(pageNum, pageSize);
		List<ExceptionLog> list = this.mapper.findByCriteria(criteria);
		List<ExceptionLogDTO> collect = Optional.ofNullable(list).orElse(Collections.emptyList()).stream().map(p -> {
			ExceptionLogDTO target = new ExceptionLogDTO();
			BeanUtils.copyProperties(p, target);
			return target;
		}).collect(Collectors.toList());
		Page<ExceptionLog> page = PageUtils.getPage(list);
		Page<ExceptionLogDTO> page2 = new Page<>();
		page2.setStartRow(page.getStartRow());
		page2.setEndRow(page.getEndRow());
		page2.setPageCount(page.getPageCount());
		page2.setPageNum(page.getPageNum());
		page2.setPageSize(page.getPageSize());
		page2.setTotalCount(page.getTotalCount());
		page2.setList(collect);
		return page2;
	}

	@Override
	@Transactional
	public Object batchAdd(List<ExceptionLogDTO> exceptionLogDTOList) {
		// TODO
		UserDTO userDTO = userUtils.getUserDTO();
		for (ExceptionLogDTO exceptionLogDTO : exceptionLogDTOList) {
			ExceptionLog exceptionLog = new ExceptionLog();
			BeanUtils.copyProperties(exceptionLogDTO, exceptionLog);
			this.vaildateModel(exceptionLog, false, userDTO);
			this.buildField(exceptionLog, false, userDTO);
			this.mapper.save(exceptionLog);
		}
		return "";
	}

	@Override
	@Transactional
	public Object batchEdit(List<ExceptionLogDTO> exceptionLogDTOList) {
		// TODO
		UserDTO userDTO = userUtils.getUserDTO();
		for (ExceptionLogDTO exceptionLogDTO : exceptionLogDTOList) {
			ExceptionLog exceptionLog = new ExceptionLog();
			BeanUtils.copyProperties(exceptionLogDTO, exceptionLog);
			this.vaildateModel(exceptionLog, true, userDTO);
			this.buildField(exceptionLog, true, userDTO);
			this.mapper.updateWithValidate(exceptionLog,
					p -> ObjectUtils.isNotNull(p) && ObjectUtils.isNotNull(p.getValue()));
		}
		return "";
	}

	@Override
	public List<ExceptionLogDTO> findAll(ExceptionLogDTO exceptionLogDTO) {
		// TODO
		Criteria criteria = Criteria.forClass(ExceptionLog.class);
		ExceptionLogDTO condition = exceptionLogDTO;
		Restriction r = buildCondition(condition);
		criteria.setRestriction(r);
		Order order = Order.newInstance().desc("gmtModified");
		criteria.setOrder(order);
		List<ExceptionLog> list = this.mapper.findByCriteria(criteria);
		List<ExceptionLogDTO> collect = Optional.ofNullable(list).orElse(Collections.emptyList()).stream().map(p -> {
			ExceptionLogDTO target = new ExceptionLogDTO();
			BeanUtils.copyProperties(p, target);
			return target;
		}).collect(Collectors.toList());
		return collect;
	}

	@Override
	public ExceptionLogDTO findByPkId(String pkId) {
		// TODO
		ExceptionLog exceptionLog = this.findById(pkId);
		AssertUtils.notNull(exceptionLog, "model empty!");
		ExceptionLogDTO exceptionLogDTO = new ExceptionLogDTO();
		BeanUtils.copyProperties(exceptionLog, exceptionLogDTO);
		return exceptionLogDTO;
	}

	private ExceptionLog findById(String id) {
		return this.mapper.findById(id, ExceptionLog.class);
	}

	private void vaildateModel(ExceptionLog exceptionLog, Boolean editFlag, UserDTO userDTO) {
		if (!editFlag) {
			// TODO add
		} else {
			// TODO
		}
	}

	private void buildField(ExceptionLog exceptionLog, Boolean editFlag, UserDTO userDTO) {
		if (!editFlag) {
			// TODO add
		} else {
			// TODO edit
		}
		vaildateModelRepeated(exceptionLog, editFlag, userDTO);
	}

	private void vaildateModelRepeated(ExceptionLog exceptionLog, Boolean editFlag, UserDTO userDTO) {
		if (!editFlag) {
			// TODO add
		} else {
			// TODO
		}
	}

	private boolean canEdit(String pkId) {
		boolean flag = true;
		ExceptionLog exceptionLog = this.findById(pkId);
		AssertUtils.notNull(exceptionLog, "model empty!");
		// TODO
		if (true)
			flag = false;
		return flag;
	}

	private Restriction buildCondition(ExceptionLogDTO exceptionLogDTO) {
		// TODO
		return null;
	}

}
