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

import com.prolog.cs.biz.inbound.dao.rqc.WmsInRqcStRuleMapper;
import com.prolog.cs.biz.inbound.dto.PageParam;
import com.prolog.cs.biz.inbound.dto.rqc.WmsInRqcStRuleDTO;
import com.prolog.cs.biz.inbound.model.rqc.WmsInRqcStRule;
import com.prolog.cs.biz.inbound.service.rqc.WmsInRqcStRuleService;
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.core.restriction.Restrictions;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.framework.utils.AssertUtils;
import com.prolog.framework.utils.MapUtils;
import com.prolog.framework.utils.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
public class WmsInRqcStRuleServiceImpl implements WmsInRqcStRuleService {

	@Resource
	private WmsInRqcStRuleMapper mapper;

	@Resource
	private UserUtils userUtils;

	@Override
	public Object add(WmsInRqcStRuleDTO wmsInRqcStRuleDTO) {
		UserDTO userDTO = userUtils.getUserDTO();
		Date now = new Date();
		this.vaildateModel(wmsInRqcStRuleDTO, false, userDTO, now);
		WmsInRqcStRule wmsInRqcStRule = new WmsInRqcStRule();
		BeanUtils.copyProperties(wmsInRqcStRuleDTO, wmsInRqcStRule);
		this.buildField(wmsInRqcStRule, false, userDTO, now);
		this.mapper.save(wmsInRqcStRule);
		return true;
	}

	@Override
	public Object edit(String pkId, WmsInRqcStRuleDTO wmsInRqcStRuleDTO) {
		UserDTO userDTO = userUtils.getUserDTO();
		Date now = new Date();
		this.vaildateModel(wmsInRqcStRuleDTO, true, userDTO, now);
		WmsInRqcStRule wmsInRqcStRule = new WmsInRqcStRule();
		BeanUtils.copyProperties(wmsInRqcStRuleDTO, wmsInRqcStRule);
		this.buildField(wmsInRqcStRule, true, userDTO, now);
		this.mapper.updateWithValidate(wmsInRqcStRule,
				p -> ObjectUtils.isNotNull(p) && ObjectUtils.isNotNull(p.getValue()));
		return true;
	}

	@Override
	@Transactional
	public Object delIds(List<String> pkIdList) {
		AssertUtils.isNotEmpty(pkIdList, "操作的集合不可为空!");
		pkIdList.stream().filter(p -> canEdit(p)).forEach(p -> this.mapper.deleteById(p, WmsInRqcStRule.class));
		return true;
	}

	@Override
	public Object deletePkId(String pkId) {
		AssertUtils.isTrue(canEdit(pkId), "改数据不可删除!");
		this.mapper.deleteById(pkId, WmsInRqcStRule.class);
		return true;
	}

	@Override
	public Object delByRelatedId(String relatedId) {
		// 根据关联id删除
		AssertUtils.isNotBlank(relatedId, "关联的策略id不可为空!");
		Criteria crt = Criteria.forClass(WmsInRqcStRule.class);
		crt.setRestriction(Restrictions.eq("rqcStId", relatedId));
		this.mapper.deleteByCriteria(crt);
		return true;
	}

	@Override
	public List<WmsInRqcStRuleDTO> findByRelatedId(String relatedId) {
		// 根据关联id删除
		AssertUtils.isNotBlank(relatedId, "关联的策略id不可为空!");
		Criteria crt = Criteria.forClass(WmsInRqcStRule.class);
		crt.setRestriction(Restrictions.eq("rqcStId", relatedId));
		Order order = Order.newInstance().asc("sortIndex").desc("gmtModified");
		crt.setOrder(order);
		List<WmsInRqcStRule> list = this.mapper.findByCriteria(crt);
		List<WmsInRqcStRuleDTO> collect = Optional.ofNullable(list).orElse(Collections.emptyList()).stream().map(p -> {
			WmsInRqcStRuleDTO target = new WmsInRqcStRuleDTO();
			BeanUtils.copyProperties(p, target);
			return target;
		}).collect(Collectors.toList());
		return collect;
	}

	@Override
	public Page<WmsInRqcStRuleDTO> findList(WmsInRqcStRuleDTO wmsInRqcStRuleDTO, PageParam pageParam) {
		Criteria criteria = Criteria.forClass(WmsInRqcStRule.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();
			WmsInRqcStRuleDTO condition = wmsInRqcStRuleDTO;
			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().asc("sortIndex").desc("gmtModified");
		criteria.setOrder(order);
		PageUtils.startPage(pageNum, pageSize);
		List<WmsInRqcStRule> list = this.mapper.findByCriteria(criteria);
		List<WmsInRqcStRuleDTO> collect = Optional.ofNullable(list).orElse(Collections.emptyList()).stream().map(p -> {
			WmsInRqcStRuleDTO target = new WmsInRqcStRuleDTO();
			BeanUtils.copyProperties(p, target);
			return target;
		}).collect(Collectors.toList());
		Page<WmsInRqcStRule> page = PageUtils.getPage(list);
		Page<WmsInRqcStRuleDTO> 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<WmsInRqcStRuleDTO> wmsInRqcStRuleDTOList) {
		batchVaildate(wmsInRqcStRuleDTOList);
		UserDTO userDTO = userUtils.getUserDTO();
		Integer row = 0;
		Date now = new Date();
		for (WmsInRqcStRuleDTO wmsInRqcStRuleDTO : wmsInRqcStRuleDTOList) {
			row++;
			this.vaildateModel(wmsInRqcStRuleDTO, false, userDTO, now, row);
			WmsInRqcStRule wmsInRqcStRule = new WmsInRqcStRule();
			BeanUtils.copyProperties(wmsInRqcStRuleDTO, wmsInRqcStRule);
			this.buildField(wmsInRqcStRule, false, userDTO, now, row);
			this.mapper.save(wmsInRqcStRule);
		}
		return true;
	}

	@Override
	@Transactional
	public Object batchEdit(List<WmsInRqcStRuleDTO> wmsInRqcStRuleDTOList) {
		batchVaildate(wmsInRqcStRuleDTOList);
		UserDTO userDTO = userUtils.getUserDTO();
		Date now = new Date();
		Integer row = 0;
		for (WmsInRqcStRuleDTO wmsInRqcStRuleDTO : wmsInRqcStRuleDTOList) {
			row++;
			this.vaildateModel(wmsInRqcStRuleDTO, true, userDTO, now, row);
			WmsInRqcStRule wmsInRqcStRule = new WmsInRqcStRule();
			BeanUtils.copyProperties(wmsInRqcStRuleDTO, wmsInRqcStRule);
			this.buildField(wmsInRqcStRule, true, userDTO, now, row);
			this.mapper.updateWithValidate(wmsInRqcStRule,
					p -> ObjectUtils.isNotNull(p) && ObjectUtils.isNotNull(p.getValue()));
		}
		return true;
	}

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

	@Override
	public WmsInRqcStRuleDTO findByPkId(String pkId) {
		AssertUtils.isBlank(pkId, "主键id不可为空!");
		WmsInRqcStRule wmsInRqcStRule = this.findById(pkId);
		AssertUtils.notNull(wmsInRqcStRule, "查询对象为空!");
		WmsInRqcStRuleDTO wmsInRqcStRuleDTO = new WmsInRqcStRuleDTO();
		BeanUtils.copyProperties(wmsInRqcStRule, wmsInRqcStRuleDTO);
		return wmsInRqcStRuleDTO;
	}

	@Override
	public Object move(String pkId, String moveType) {
		// 数值越小,优先级越大
		AssertUtils.isNotBlank(moveType, "规则移动的类型为空!");
		AssertUtils.isNotBlank(pkId, "规则主键id为空!");
		WmsInRqcStRule findById = this.findById(pkId);
		String rqcStId = findById.getRqcStId();
		Integer sortIndex = findById.getSortIndex();
		Criteria criteria = Criteria.forClass(WmsInRqcStRule.class);
		Restriction eq = Restrictions.eq("rqcStId", rqcStId);
		Restriction and = null;
		Order order = null;
		if (moveType.equals("up")) {
			// 升序
			Restriction lt = Restrictions.lt("sortIndex", sortIndex);
			and = Restrictions.and(eq, lt);
			order = Order.newInstance().desc("sortIndex").desc("gmtModified");
		}
		if (moveType.equals("down")) {
			// 降序
			Restriction gt = Restrictions.gt("sortIndex", sortIndex);
			and = Restrictions.and(eq, gt);
			order = Order.newInstance().asc("sortIndex").desc("gmtModified");
		}
		criteria.setRestriction(and);
		criteria.setOrder(order);
		List<WmsInRqcStRule> findByCriteria = this.mapper.findByCriteria(criteria);
		AssertUtils.isNotEmpty(findByCriteria, "无法移动该数据,最顶或者最底");
		WmsInRqcStRule rule2 = findByCriteria.get(0);
		Integer sortIndex2 = rule2.getSortIndex();
		String ruleId2 = rule2.getRuleId();
		// 排序互换
		this.mapper.updateMapById(pkId, MapUtils.put("sortIndex", sortIndex2).getMap(), WmsInRqcStRule.class);
		this.mapper.updateMapById(ruleId2, MapUtils.put("sortIndex", sortIndex).getMap(), WmsInRqcStRule.class);
		return true;
	}

	private void batchVaildate(List<WmsInRqcStRuleDTO> wmsInRqcStRuleDTOList) {
		AssertUtils.isNotEmpty(wmsInRqcStRuleDTOList, "操作的集合不可为空!");
	}

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

	private void vaildateModel(WmsInRqcStRuleDTO wmsInRqcStRuleDTO, Boolean editFlag, UserDTO userDTO, Date now) {
		vaildateModel(wmsInRqcStRuleDTO, editFlag, userDTO, now, null);
	}

	private void vaildateModel(WmsInRqcStRuleDTO wmsInRqcStRuleDTO, Boolean editFlag, UserDTO userDTO, Date now,
			Integer row) {
		String format = "";
		if (row != null && row != 0) {
			format = String.format("第[%d]行,", row);
		}
		AssertUtils.isNotNull(wmsInRqcStRuleDTO, format + "操作的对象不能为空!");
		if (!editFlag) {
			String rqcStId = wmsInRqcStRuleDTO.getRqcStId();
			String searchRegexp = wmsInRqcStRuleDTO.getSearchRegexp();
			String matchRegexp = wmsInRqcStRuleDTO.getMatchRegexp();
			String ruleName = wmsInRqcStRuleDTO.getRuleName();
			AssertUtils.isNotBlank(rqcStId, format + "抽检策略id(rqcStId)不可为空!");
			AssertUtils.isNotBlank(searchRegexp, format + "查询表达式(searchRegexp)不可为空!");
			AssertUtils.isNotBlank(matchRegexp, format + "匹配表达式(matchRegexp)不可为空!");
			AssertUtils.isNotBlank(ruleName, format + "规则名称(ruleName)不可为空!");
		} else {
			AssertUtils.isTrue(canEdit(wmsInRqcStRuleDTO.getRuleId()), format + "该数据不可编辑!");
		}
		vaildateModelRepeated(wmsInRqcStRuleDTO, editFlag, userDTO, now, row);
	}

	private void vaildateModelRepeated(WmsInRqcStRuleDTO wmsInRqcStRuleDTO, Boolean editFlag, UserDTO userDTO, Date now,
			Integer row) {
		// 策略id+规则名称不可重复+查询表达式 不可重复
		String format = "";
		if (row != null && row != 0) {
			format = String.format("第[%d]行,", row);
		}
		String rqcStId = wmsInRqcStRuleDTO.getRqcStId();
		String ruleName = wmsInRqcStRuleDTO.getRuleName();
		String matchRegexp = wmsInRqcStRuleDTO.getMatchRegexp();
		Restriction condition = null;
		if (!editFlag) {
		} else {
			if (StringUtils.isBlank(ruleName) && StringUtils.isBlank(ruleName)) {
				return;
			}
			WmsInRqcStRule findById = this.findById(wmsInRqcStRuleDTO.getRuleId());
			String ruleName2 = findById.getRuleName();
			String matchRegexp2 = findById.getMatchRegexp();
			String rqcStId2 = findById.getRqcStId();
			if (!StringUtils.isBlank(rqcStId) && !rqcStId.equals(rqcStId2)) {
				throw new BizException(format + "编辑的策略id和查询的规则id对应的策略id不一致,请检查!");
			}
			if (!StringUtils.isBlank(ruleName) && ruleName.equals(ruleName2) && !StringUtils.isBlank(matchRegexp)
					&& matchRegexp.equals(matchRegexp2)) {
				return;
			}
			rqcStId = rqcStId2;
		}
		Restriction er2 = StringUtils.isBlank(ruleName) ? null : Restrictions.eq("ruleName", ruleName);
		Restriction er3 = StringUtils.isBlank(matchRegexp) ? null : Restrictions.eq("matchRegexp", matchRegexp);
		Restriction er1 = StringUtils.isBlank(rqcStId) ? null : Restrictions.eq("rqcStId", rqcStId);
		condition = Restrictions.and(er1, er2, er3);
		Criteria criteria = Criteria.forClass(WmsInRqcStRule.class);
		criteria.setRestriction(condition);
		long l = this.mapper.findCountByCriteria(criteria);
		if (l > 0) {
			throw new BizException(format + "重复校验失败!检查自己规则是否重复.");
		}
	}

	private void buildField(WmsInRqcStRule wmsInRqcStRule, Boolean editFlag, UserDTO userDTO, Date now) {
		buildField(wmsInRqcStRule, editFlag, userDTO, now, null);
	}

	private void buildField(WmsInRqcStRule wmsInRqcStRule, Boolean editFlag, UserDTO userDTO, Date now, Integer row) {
		String enterpriseId = userDTO.getEnterpriseId();
		String id = userDTO.getId();
		String username = userDTO.getUsername();
		if (!editFlag) {
			String rqcStId = wmsInRqcStRule.getRqcStId();
			// 加入排序
			Integer sort = this.mapper.getMaxSortRule(rqcStId);
			if (row != null && row != 0) {
				sort = sort + row;
			} else {
				sort = sort + 1;
			}
			wmsInRqcStRule.setSortIndex(sort);
			String status = wmsInRqcStRule.getStatus();
			if (StringUtils.isBlank(status)) {
				wmsInRqcStRule.setStatus("1");
			}
			wmsInRqcStRule.setEnterpriseId(enterpriseId);
			wmsInRqcStRule.setCreator(id);
			wmsInRqcStRule.setCreatorName(username);
			wmsInRqcStRule.setGmtCreate(now);
		} else {
		}
		wmsInRqcStRule.setModifier(id);
		wmsInRqcStRule.setModifierName(username);
		wmsInRqcStRule.setGmtModified(now);
	}

	private boolean canEdit(String pkId) {
		AssertUtils.isNotBlank(pkId, "主键id(pkId)不可为空!");
		boolean flag = false;
		WmsInRqcStRule wmsInRqcStRule = this.findById(pkId);
		AssertUtils.notNull(wmsInRqcStRule, "查询的抽检策略规则为空!");
		// TODO 可定义不可编辑的规则
		if (true)
			flag = true;
		return flag;
	}

	private Restriction buildCondition(WmsInRqcStRuleDTO wmsInRqcStRuleDTO) {
		if (wmsInRqcStRuleDTO == null) {
			return null;
		}
		String ruleName = wmsInRqcStRuleDTO.getRuleName();
		String ruleId = wmsInRqcStRuleDTO.getRuleId();
		String status = wmsInRqcStRuleDTO.getStatus();
		String rqcStId = wmsInRqcStRuleDTO.getRqcStId();
		Restriction r1 = StringUtils.isBlank(ruleName) ? null : Restrictions.likeAllIgnoreCase("ruleName", ruleName);
		Restriction r2 = StringUtils.isBlank(ruleId) ? null : Restrictions.eq("ruleId", ruleId);
		Restriction r3 = StringUtils.isBlank(rqcStId) ? null : Restrictions.eq("rqcStId", rqcStId);
		Restriction r4 = StringUtils.isBlank(status) ? null : Restrictions.eq("status", status);
		return Restrictions.and(r1, r2, r3, r4);
	}

}
