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

import com.prolog.cs.biz.inbound.dao.rqc.RqcStMapper;
import com.prolog.cs.biz.inbound.dto.PageParam;
import com.prolog.cs.biz.inbound.dto.rqc.RqcStDTO;
import com.prolog.cs.biz.inbound.model.rqc.RqcSt;
import com.prolog.cs.biz.inbound.service.rqc.RqcStService;
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.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 RqcStServiceImpl implements RqcStService {

	@Resource
	private RqcStMapper mapper;

	@Resource
	private UserUtils userUtils;

	@Override
	public Object add(RqcStDTO rqcStDTO) {
		AssertUtils.isNotNull(rqcStDTO, "操作的对象不能为空!");
		UserDTO userDTO = userUtils.getUserDTO();
		Date now = new Date();
		this.vaildateModel(rqcStDTO, false, userDTO, now);
		RqcSt rqcSt = new RqcSt();
		BeanUtils.copyProperties(rqcStDTO, rqcSt);
		this.buildField(rqcSt, false, userDTO, now);
		this.mapper.save(rqcSt);
		return true;
	}

	@Override
	public Object edit(String pkId, RqcStDTO rqcStDTO) {
		AssertUtils.isTrue(canEdit(rqcStDTO.getRqcStId()), "该数据不可编辑!");
		UserDTO userDTO = userUtils.getUserDTO();
		Date now = new Date();
		this.vaildateModel(rqcStDTO, true, userDTO, now);
		RqcSt rqcSt = new RqcSt();
		BeanUtils.copyProperties(rqcStDTO, rqcSt);
		this.buildField(rqcSt, true, userDTO, now);
		this.mapper.updateWithValidate(rqcSt, 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, RqcSt.class));
		return true;
	}

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

	@Override
	public Page<RqcStDTO> findList(RqcStDTO rqcStDTO, PageParam pageParam) {
		Criteria criteria = Criteria.forClass(RqcSt.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();
			RqcStDTO condition = rqcStDTO;
			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<RqcSt> list = this.mapper.findByCriteria(criteria);
		List<RqcStDTO> collect = Optional.ofNullable(list).orElse(Collections.emptyList()).stream().map(p -> {
			RqcStDTO target = new RqcStDTO();
			BeanUtils.copyProperties(p, target);
			return target;
		}).collect(Collectors.toList());
		Page<RqcSt> page = PageUtils.getPage(list);
		Page<RqcStDTO> 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<RqcStDTO> rqcStDTOList) {
		AssertUtils.isNotEmpty(rqcStDTOList, "操作集合不可为空!");
		UserDTO userDTO = userUtils.getUserDTO();
		Date now = new Date();
		Integer row = 0;
		for (RqcStDTO rqcStDTO : rqcStDTOList) {
			row++;
			this.vaildateModel(rqcStDTO, false, userDTO, now, row);
			RqcSt rqcSt = new RqcSt();
			BeanUtils.copyProperties(rqcStDTO, rqcSt);
			this.buildField(rqcSt, false, userDTO, now);
			this.mapper.save(rqcSt);
		}
		return true;
	}

	@Override
	@Transactional
	public Object batchEdit(List<RqcStDTO> rqcStDTOList) {
		AssertUtils.isNotEmpty(rqcStDTOList, "操作集合不可为空!");
		UserDTO userDTO = userUtils.getUserDTO();
		Date now = new Date();
		Integer row = 0;
		for (RqcStDTO rqcStDTO : rqcStDTOList) {
			row++;
			this.vaildateModel(rqcStDTO, true, userDTO, now, row);
			AssertUtils.isTrue(canEdit(rqcStDTO.getRqcStId()), String.format("第[%d]行,该数据不可编辑!", row));
			RqcSt rqcSt = new RqcSt();
			BeanUtils.copyProperties(rqcStDTO, rqcSt);
			this.buildField(rqcSt, true, userDTO, now);
			this.mapper.updateWithValidate(rqcSt, p -> ObjectUtils.isNotNull(p) && ObjectUtils.isNotNull(p.getValue()));
		}
		return true;
	}

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

	@Override
	public RqcStDTO findByPkId(String pkId) {
		AssertUtils.isBlank(pkId, "主键id不可为空!");
		RqcSt rqcSt = this.findById(pkId);
		AssertUtils.notNull(rqcSt, "查询的数据为空!");
		RqcStDTO rqcStDTO = new RqcStDTO();
		BeanUtils.copyProperties(rqcSt, rqcStDTO);
		return rqcStDTO;
	}

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

	private void vaildateModel(RqcStDTO rqcStDTO, boolean b, UserDTO userDTO, Date now) {
		vaildateModel(rqcStDTO, b, userDTO, now, null);
	}

	private void vaildateModel(RqcStDTO rqcStDTO, Boolean editFlag, UserDTO userDTO, Date now, Integer row) {
		String format = "";
		if (row != null && row != 0) {
			format = String.format("第[%d]行,", row);
		}
		if (!editFlag) {
			String mtlOwnerId = rqcStDTO.getMtlOwnerId();
			String warehouseId = rqcStDTO.getWarehouseId();
			String stNum = rqcStDTO.getStNum();
			String stName = rqcStDTO.getStName();
			String stType = rqcStDTO.getStType();
			String billType = rqcStDTO.getBillType();
			AssertUtils.isNotBlank(mtlOwnerId, format + "新增策略货主id(mtlOwnerId)不可为空!");
			AssertUtils.isNotBlank(warehouseId, format + "新增策略仓库id(warehouseId)不可为空!");
			AssertUtils.isNotBlank(stNum, format + "新增策略编码(stNum)不可为空!");
			AssertUtils.isNotBlank(stName, format + "新增策略名称(stName)不可为空!");
			AssertUtils.isNotBlank(stType, format + "新增策略类型(stType)不可为空!");
			AssertUtils.isNotBlank(billType, format + "新增策略对应的单据类型(billType)不可为空!");
			if (stType.equals("1")) {
				String itemId = rqcStDTO.getItemId();
				String itemCategoryCode = rqcStDTO.getItemCategoryCode();
				if (StringUtils.isBlank(itemCategoryCode)) {
					throw new BizException("商品大类(itemCategoryCode)不可为空!");
				}
			}
		} else {
			String rqcStId = rqcStDTO.getRqcStId();
			AssertUtils.isNotBlank(rqcStId, "编辑的主键id(rqcStId)不可为空!");
		}
		vaildateModelRepeated(rqcStDTO, editFlag, userDTO, row);
	}

	private void buildField(RqcSt rqcSt, Boolean editFlag, UserDTO userDTO, Date now) {
		if (now == null) {
			now = new Date();
		}
		String enterpriseId = userDTO.getEnterpriseId();
		String id = userDTO.getId();
		String username = userDTO.getUsername();
		if (!editFlag) {
			rqcSt.setCreator(id);
			rqcSt.setCreatorName(username);
			rqcSt.setGmtCreate(now);
			rqcSt.setEnterpriseId(enterpriseId);
			if (ObjectUtils.isNull(rqcSt.getStatus()))
				rqcSt.setStatus("1");
		} else {
		}
		rqcSt.setModifier(id);
		rqcSt.setModifierName(username);
		rqcSt.setGmtModified(now);
	}

	private void vaildateModelRepeated(RqcStDTO rqcStDTO, Boolean editFlag, UserDTO userDTO, Integer row) {
		// 1. 同货主,同仓库,同单据类型,同通用类型,只有一种
		// 2. 同货主,同仓库,同单据类型,非通用类型,同商品(同商品大类)只能有一个
		// 3. 同货主,同仓库,策略编号唯一
		String format = "";
		if (row != null && row != 0) {
			format = String.format("第[%d]行,", row);
		}
		String stNum = rqcStDTO.getStNum();
		String warehouseId = rqcStDTO.getWarehouseId();
		String mtlOwnerId = rqcStDTO.getMtlOwnerId();
		String stType = rqcStDTO.getStType();
		String itemId = rqcStDTO.getItemId();
		String itemCategoryCode = rqcStDTO.getItemCategoryCode();
		String billType = rqcStDTO.getBillType();
		Restriction condition = null;
		if (!editFlag) {
			Restriction er1 = StringUtils.isBlank(stType) ? null : Restrictions.eq("stType", stType);
			if (stType.equals("1")) {
				Restriction r0 = StringUtils.isBlank(stNum) ? null : Restrictions.eq("stNum", stNum);
				Restriction er2 = StringUtils.isBlank(itemId) ? null : Restrictions.eq("itemId", itemId);
				Restriction er3 = StringUtils.isBlank(itemCategoryCode) ? null
						: Restrictions.eq("itemCategoryCode", itemCategoryCode);
				condition = Restrictions.and(r0, er1, er2, er3);
			} else {
				condition = er1;
			}
		} else {
			if (StringUtils.isBlank(stNum) && StringUtils.isBlank(itemId) && StringUtils.isBlank(itemCategoryCode)) {
				return;
			}
			String rqcStId = rqcStDTO.getRqcStId();
			RqcSt findById = this.findById(rqcStId);
			String stNum2 = findById.getStNum();
			String itemId2 = findById.getItemId();
			String itemCategoryCode2 = findById.getItemCategoryCode();
			String stType2 = findById.getStType();
			String mtlOwnerId2 = findById.getMtlOwnerId();
			String warehouseId2 = findById.getWarehouseId();
			String billType2 = findById.getBillType();
			if (!StringUtils.isBlank(warehouseId) && !warehouseId.equals(warehouseId2)
					&& !StringUtils.isBlank(mtlOwnerId) && !mtlOwnerId.equals(mtlOwnerId2)
					&& !StringUtils.isBlank(stType) && !stType.equals(stType2) && !StringUtils.isBlank(billType)
					&& !stType.equals(billType2)) {
				throw new BizException(format + "货主,仓库,策略类型,单据类型不可更改!");
			}
			warehouseId = warehouseId2;
			mtlOwnerId = mtlOwnerId2;
			billType = billType2;
			if (stType2.equals("1")) {
				// 非通用
				if (!StringUtils.isBlank(stNum) && stNum2.equals(stNum) && !StringUtils.isBlank(itemId)
						&& !StringUtils.isBlank(itemId2) && itemId2.equals(itemId)
						&& !StringUtils.isBlank(itemCategoryCode2) && !StringUtils.isBlank(itemCategoryCode)
						&& itemCategoryCode2.equals(itemCategoryCode)) {
					return;
				}
				if (!StringUtils.isBlank(stNum) && stNum2.equals(stNum) && !StringUtils.isBlank(itemCategoryCode)
						&& !StringUtils.isBlank(itemCategoryCode2) && itemCategoryCode2.equals(itemCategoryCode)
						&& (StringUtils.isBlank(itemId) || itemId.equals("all"))) {
					return;
				}
			} else {
				// 通用
				if (!StringUtils.isBlank(stNum) && stNum2.equals(stNum)) {
					return;
				}
			}

			Restriction er2 = StringUtils.isBlank(itemId) ? null : Restrictions.eq("itemId", itemId);
			Restriction er3 = StringUtils.isBlank(itemCategoryCode) ? null
					: Restrictions.eq("itemCategoryCode", itemCategoryCode);
			Restriction r0 = StringUtils.isBlank(stNum) ? null : Restrictions.eq("stNum", stNum);
			condition = Restrictions.and(r0, er2, er3);
		}
		Restriction er11 = StringUtils.isBlank(billType) ? null : Restrictions.eq("billType", billType);
		Restriction eq1 = Restrictions.eq("warehouseId", warehouseId);
		Restriction eq2 = Restrictions.eq("mtlOwnerId", mtlOwnerId);
		Restriction and = Restrictions.and(eq1, eq2, condition, er11);
		Criteria criteria = Criteria.forClass(RqcSt.class);
		criteria.setRestriction(and);
		long l = this.mapper.findCountByCriteria(criteria);
		if (l > 0) {
			throw new BizException(format + "重复校验失败!检查自己策略是否重复冲突.");
		}
	}

	private Restriction buildCondition(RqcStDTO rqcStDTO) {
		if (rqcStDTO == null) {
			return null;
		}
		String rqcStId = rqcStDTO.getRqcStId();
		String stType = rqcStDTO.getStType();
		String mtlOwnerId = rqcStDTO.getMtlOwnerId();
		String warehouseId = rqcStDTO.getWarehouseId();
		String status = rqcStDTO.getStatus();
		String stNum = rqcStDTO.getStNum();
		String stName = rqcStDTO.getStName();
		String itemId = rqcStDTO.getItemId();
		String itemCode = rqcStDTO.getItemCode();
		String itemName = rqcStDTO.getItemName();
		String itemCategoryCode = rqcStDTO.getItemCategoryCode();
		String itemCondition = rqcStDTO.getItemCondition();
		String billType = rqcStDTO.getBillType();

		Restriction r1 = StringUtils.isBlank(mtlOwnerId) ? null : Restrictions.eq("mtlOwnerId", mtlOwnerId);
		Restriction r2 = StringUtils.isBlank(warehouseId) ? null : Restrictions.eq("warehouseId", warehouseId);
		Restriction r3 = StringUtils.isBlank(stType) ? null : Restrictions.eq("stType", stType);
		Restriction r4 = StringUtils.isBlank(rqcStId) ? null : Restrictions.eq("rqcStId", rqcStId);
		Restriction r5 = StringUtils.isBlank(status) ? null : Restrictions.eq("status", status);
		Restriction r6 = StringUtils.isBlank(itemId) ? null : Restrictions.eq("itemId", itemId);
		Restriction r7 = StringUtils.isBlank(itemName) ? null : Restrictions.eq("itemName", itemName);
		Restriction r8 = StringUtils.isBlank(stNum) ? null : Restrictions.likeAllIgnoreCase("stNum", stNum);
		Restriction r9 = StringUtils.isBlank(stName) ? null : Restrictions.likeAllIgnoreCase("stName", stName);
		Restriction r10 = StringUtils.isBlank(itemCode) ? null : Restrictions.likeAllIgnoreCase("itemCode", itemCode);
		Restriction r11 = StringUtils.isBlank(itemCategoryCode) ? null
				: Restrictions.likeAllIgnoreCase("itemCategoryCode", itemCategoryCode);
		Restriction r12 = StringUtils.isBlank(itemCondition) ? null
				: Restrictions.or(Restrictions.likeAllIgnoreCase("itemName", itemCondition),
						Restrictions.likeAllIgnoreCase("itemCode", itemCode));
		Restriction r13 = StringUtils.isBlank(billType) ? null : Restrictions.eq("billType", billType);
		return Restrictions.and(r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13);
	}

	private boolean canEdit(String pkId) {
		AssertUtils.isNotBlank(pkId, "主键id(pkId)不可为空!");
		boolean flag = false;
		RqcSt rqcSt = this.findById(pkId);
		AssertUtils.notNull(rqcSt, "查询的抽检策略为空!");
		// TODO 可写无法编辑的判断
		if (true)
			flag = true;
		return flag;
	}
}
