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

import com.prolog.common.util.DateUtils;
import com.prolog.cs.biz.inbound.constant.BizConstant;
import com.prolog.cs.biz.inbound.dao.task.TaskQcRecheckDetailMapper;
import com.prolog.cs.biz.inbound.dto.PageParam;
import com.prolog.cs.biz.inbound.dto.rcv.RcvHDTO;
import com.prolog.cs.biz.inbound.dto.rcv.RcvLinesDTO;
import com.prolog.cs.biz.inbound.dto.rqc.RqcLinesDTO;
import com.prolog.cs.biz.inbound.dto.rqc.RqcReLinesDTO;
import com.prolog.cs.biz.inbound.dto.rqc.RqcRechekLinesDTO;
import com.prolog.cs.biz.inbound.dto.task.TaskQcRecheckDetailDTO;
import com.prolog.cs.biz.inbound.model.task.TaskQcRecheckDetail;
import com.prolog.cs.biz.inbound.service.impl.BaseServiceImpl;
import com.prolog.cs.biz.inbound.service.impl.processor.Helper.HostedHelper;
import com.prolog.cs.biz.inbound.service.task.TaskInstockDetailService;
import com.prolog.cs.biz.inbound.service.task.TaskQcRecheckDetailService;
import com.prolog.cs.biz.inbound.utils.ObjectUtils;
import com.prolog.cs.biz.inbound.utils.UserUtils;
import com.prolog.cs.biz.inbound.vo.RcvQueryVO;
import com.prolog.cs.biz.inbound.vo.task.TaskQcDetailQueryVO;
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.math.BigDecimal;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class TaskQcRecheckDetailServiceImpl extends BaseServiceImpl<TaskQcRecheckDetail>
		implements TaskQcRecheckDetailService {

	@Resource
	private TaskQcRecheckDetailMapper mapper;

	@Resource
	private TaskInstockDetailService taskInstockDetailService;

	@Resource
	private UserUtils userUtils;

    @Resource
    private HostedHelper hostedHelper;

	private Restriction buildCondition(TaskQcRecheckDetailDTO taskQcRecheckDetailDTO) {
		Restriction r0 = Restrictions.eq("enterpriseId", userUtils.getEnterpriseId());
		if (ObjectUtils.isNull(taskQcRecheckDetailDTO))
			return r0;
		// 构建查询条件
		String batchNum = taskQcRecheckDetailDTO.getBatchNum();
		String mtlOwnerId = taskQcRecheckDetailDTO.getMtlOwnerId();
		String warehouseId = taskQcRecheckDetailDTO.getWarehouseId();
		String rcvHeaderId = taskQcRecheckDetailDTO.getRcvHeaderId();
		String rcvLineId = taskQcRecheckDetailDTO.getRcvLineId();
		String itemId = taskQcRecheckDetailDTO.getItemId();

		Restriction r1 = StringUtils.isBlank(mtlOwnerId) ? null : Restrictions.eq("mtlOwnerId", mtlOwnerId);
		Restriction r2 = StringUtils.isBlank(warehouseId) ? null : Restrictions.eq("warehouseId", warehouseId);
		Restriction r3 = StringUtils.isBlank(rcvHeaderId) ? null : Restrictions.eq("rcvHeaderId", rcvHeaderId);
		Restriction r4 = StringUtils.isBlank(rcvLineId) ? null : Restrictions.eq("rcvLineId", rcvLineId);
		Restriction r5 = StringUtils.isBlank(itemId) ? null : Restrictions.eq("itemId", itemId);
		Restriction r6 = StringUtils.isBlank(batchNum) ? null : Restrictions.like("batchNum", "%" + batchNum + "%");

		return Restrictions.and(r0, r1, r2, r3, r4, r5, r6);
	}

	@Override
	public Object excuteTask(List<RqcLinesDTO> rqcLinesList,boolean isAuto, String regValue, String warehouserId) {
		// TODO 创建复检任务
		UserDTO userDTO = userUtils.getUserDTO();
		Date now = new Date();

		boolean editFlag = Boolean.FALSE;
		// 此处需要判断是否是双人质检(pass)
		// 只有双人都检查结论为待处理才会入复检任务池(pass)
		List<RqcLinesDTO> rqcInstockLinesList = new ArrayList<>();
		List<RqcLinesDTO> hostedList = new ArrayList<>();
		for (RqcLinesDTO rqcLinesDTO : rqcLinesList) {

			// 执行是否需要跳过复检的操作(是否需要生成新的上架任务)
			if (excuteSkip(rqcLinesDTO, now)) {
				rqcInstockLinesList.add(rqcLinesDTO);
				continue;
			}

			excuteAdd(rqcLinesDTO, userDTO, now, editFlag, regValue);
			hostedList.add(rqcLinesDTO);
		}

		// 业务参数为1则进入代管子流程
		if (ObjectUtils.isNotNull(regValue) && "1".equals(regValue)) {
			String inType = "1";    // 入库类型-正常
			String status = "5";    // 库存状态-代管
			hostedHelper.rqcLinesInHosted(hostedList, inType, status, userDTO, now, warehouserId);
		}

		if (ObjectUtils.isNotNull(rqcInstockLinesList)) {
			taskInstockDetailService.excuteTask(rqcLinesList, "1", isAuto); // 不合格
		}
		return true;
	}

	private boolean excuteSkip(RqcLinesDTO rqcLinesDTO, Date now) {
		String rcvType = rqcLinesDTO.getRcvType();
		Date batchExpiredDate = rqcLinesDTO.getBatchExpiredDate();
		Long subtract = DateUtils.subtract(now, batchExpiredDate, ChronoUnit.DAYS);
		boolean flag = false;
		// 退货入库效期处理
		if (rcvType.equals(BizConstant.SALE_RETURN_IN) && subtract <= 0) {
			// 过期处理
			flag = true;
		}
		// 其他类型的入库效期处理

		return flag;
	}

	private void excuteAdd(RqcLinesDTO rqcLinesDTO, UserDTO userDTO, Date now, boolean editFlag, String regValue) {
		TaskQcRecheckDetail detail = new TaskQcRecheckDetail();
		BeanUtils.copyProperties(rqcLinesDTO, detail);
		// 看是否需要补数据
		this.buildDefaultField(detail, editFlag, userDTO, now);
		this.buildField(detail, editFlag, userDTO, now);

		BigDecimal conversionRate = rqcLinesDTO.getConversionRate();
		BigDecimal pieceQty = rqcLinesDTO.getPieceQty();

		if (null == conversionRate || conversionRate.compareTo(BigDecimal.ZERO) == 0) {
			detail.setQty(pieceQty);
		} else {
			detail.setQty(pieceQty.divide(conversionRate, 2, BigDecimal.ROUND_DOWN));
		}

		// 加入来源信息数据
		detail.setRefLineId(rqcLinesDTO.getRqcLineId());
		detail.setRefBillId(rqcLinesDTO.getRqcHeaderId());
		detail.setRefBillNo(rqcLinesDTO.getRqcHeaderNo());
		detail.setRefType(1);

		// 业务参数为1则进入代管子流程
		if (ObjectUtils.isNotNull(regValue) && "1".equals(regValue)) {
			// 操作来源是:质检待处理
			detail.setAttribute1("2");
		}

		this.mapper.save(detail);
		rqcLinesDTO.setTaskRecheckId(detail.getTaskRecheckId());
	}

	private void buildField(TaskQcRecheckDetail detail, boolean editFlag, UserDTO userDTO, Date now) {
		// 构建系统基础字段
		this.setBaseSysField(detail, editFlag, userDTO, now);

		vaildateModelRepeated(detail, editFlag, userDTO);
	}

	@Override
	public Object excuteTask22(List<RqcRechekLinesDTO> rqcRechekLinesList, int times) {
		// TODO 创建二次复检任务
		UserDTO userDTO = userUtils.getUserDTO();
		Date now = new Date();
		for (RqcRechekLinesDTO rqcRechekLinesDTO : rqcRechekLinesList) {
			TaskQcRecheckDetail detail = new TaskQcRecheckDetail();
			BeanUtils.copyProperties(rqcRechekLinesDTO, detail);
			// 看是否需要补数据
			this.buildDefaultField(detail, false, userDTO, now);
			this.buildField(detail, false, userDTO, now);
			this.mapper.save(detail);
		}
		return true;
	}

	@Override
	public Object excuteTask2(List<RqcReLinesDTO> rqcReLinesList, int times) {
		// TODO 创建二次复检任务
		UserDTO userDTO = userUtils.getUserDTO();
		Date now = new Date();
		for (RqcReLinesDTO rqcReLinesDTO : rqcReLinesList) {
			TaskQcRecheckDetail detail = new TaskQcRecheckDetail();
			BeanUtils.copyProperties(rqcReLinesDTO, detail);
			// 看是否需要补数据
			this.buildDefaultField(detail, false, userDTO, now);
			this.buildField(detail, false, userDTO, now);

			BigDecimal conversionRate = rqcReLinesDTO.getConversionRate();
			BigDecimal pieceQty = rqcReLinesDTO.getPieceQty();

			if (null == conversionRate || conversionRate.compareTo(BigDecimal.ZERO) == 0) {
				detail.setQty(pieceQty);
			} else {
				detail.setQty(pieceQty.divide(conversionRate, 2, BigDecimal.ROUND_DOWN));
			}
			this.mapper.save(detail);
		}
		return true;
	}

	@Override
	public Page<TaskQcRecheckDetailDTO> findList(TaskQcRecheckDetailDTO taskQcRecheckDetailDTO, PageParam pageParam) {
		Criteria criteria = this.buildPageParam(pageParam, true, null, TaskQcRecheckDetail.class);

		Restriction r = buildCondition(taskQcRecheckDetailDTO);
		Restriction or = Restrictions.eq("status", "1");
		Restriction and = Restrictions.and(r, or);
		criteria.setRestriction(and);
		this.startPage(pageParam);
		List<TaskQcRecheckDetail> list = this.mapper.findByCriteria(criteria);
		Page<TaskQcRecheckDetail> page = PageUtils.getPage(list);
		Page<TaskQcRecheckDetailDTO> page2 = this.buildPage(page, (p) -> {
			TaskQcRecheckDetailDTO target = new TaskQcRecheckDetailDTO();
			BeanUtils.copyProperties(p, target);
			return target;
		});
		return page2;
	}

	private void buildDefaultField(TaskQcRecheckDetail taskQcRecheckDetail, boolean editFlag, UserDTO userDTO,
			Date now) {
		String activeFlag = taskQcRecheckDetail.getActiveFlag();
		if (!editFlag && ObjectUtils.isNull(activeFlag)) {
			taskQcRecheckDetail.setActiveFlag("1"); // 默认作业标识可用
		}
		String status = taskQcRecheckDetail.getStatus();
		if (!editFlag && ObjectUtils.isNull(status)) {
			taskQcRecheckDetail.setStatus("1"); // 默认待质检
		}
		if (!editFlag) {
			taskQcRecheckDetail.setDataVersion(0);
		}
		taskQcRecheckDetail.setTimes(0); // 复检次数默认为0

	}

	private void buildField(TaskQcRecheckDetail taskQcRecheckDetail, Boolean editFlag, UserDTO userDTO) {
		this.buildField(taskQcRecheckDetail, editFlag, userDTO, new Date());
	}

	@Override
	public Object add(TaskQcRecheckDetailDTO taskQcRecheckDetailDTO) {
		// TODO vaildate
		UserDTO userDTO = userUtils.getUserDTO();
		TaskQcRecheckDetail taskQcRecheckDetail = new TaskQcRecheckDetail();
		BeanUtils.copyProperties(taskQcRecheckDetailDTO, taskQcRecheckDetail);
		this.vaildateModel(taskQcRecheckDetail, false, userDTO);
		this.buildField(taskQcRecheckDetail, false, userDTO);
		this.mapper.save(taskQcRecheckDetail);
		return "";
	}

	@Override
	public Object edit(String pkId, TaskQcRecheckDetailDTO taskQcRecheckDetailDTO) {
		// TODO
		UserDTO userDTO = userUtils.getUserDTO();
		TaskQcRecheckDetail taskQcRecheckDetail = new TaskQcRecheckDetail();
		BeanUtils.copyProperties(taskQcRecheckDetailDTO, taskQcRecheckDetail);
		this.vaildateModel(taskQcRecheckDetail, true, userDTO);
		this.buildField(taskQcRecheckDetail, true, userDTO);
		this.mapper.updateWithValidate(taskQcRecheckDetail,
				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, TaskQcRecheckDetail.class));
		return "";
	}

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

	@Override
	@Transactional
	public Object batchAdd(List<TaskQcRecheckDetailDTO> taskQcRecheckDetailDTOList) {
		// TODO
		UserDTO userDTO = userUtils.getUserDTO();
		for (TaskQcRecheckDetailDTO taskQcRecheckDetailDTO : taskQcRecheckDetailDTOList) {
			TaskQcRecheckDetail taskQcRecheckDetail = new TaskQcRecheckDetail();
			BeanUtils.copyProperties(taskQcRecheckDetailDTO, taskQcRecheckDetail);
			this.vaildateModel(taskQcRecheckDetail, false, userDTO);
			this.buildField(taskQcRecheckDetail, false, userDTO);
			this.mapper.save(taskQcRecheckDetail);
		}
		return "";
	}

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

	@Override
	public List<TaskQcRecheckDetailDTO> findAll(TaskQcRecheckDetailDTO taskQcRecheckDetailDTO) {
		// TODO
		Criteria criteria = Criteria.forClass(TaskQcRecheckDetail.class);
		TaskQcRecheckDetailDTO condition = taskQcRecheckDetailDTO;
		Restriction r = buildCondition(condition);
		Restriction or = Restrictions.eq("status", "1");
		Restriction and = Restrictions.and(r, or);

		criteria.setRestriction(and);
		Order order = Order.newInstance().desc("gmtModified");
		criteria.setOrder(order);
		List<TaskQcRecheckDetail> list = this.mapper.findByCriteria(criteria);
		List<TaskQcRecheckDetailDTO> collect = Optional.ofNullable(list).orElse(Collections.emptyList()).stream()
				.map(p -> {
					TaskQcRecheckDetailDTO target = new TaskQcRecheckDetailDTO();
					BeanUtils.copyProperties(p, target);
					return target;
				}).collect(Collectors.toList());
		return collect;
	}

	@Override
	public TaskQcRecheckDetailDTO findByPkId(String pkId) {
		// TODO
		TaskQcRecheckDetail taskQcRecheckDetail = this.findById(pkId);
		AssertUtils.notNull(taskQcRecheckDetail, "taskQcRecheckDetail model empty!");
		TaskQcRecheckDetailDTO taskQcRecheckDetailDTO = new TaskQcRecheckDetailDTO();
		BeanUtils.copyProperties(taskQcRecheckDetail, taskQcRecheckDetailDTO);
		return taskQcRecheckDetailDTO;
	}

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

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

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

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

	/**
	 * 本地sql实现提取任务头
	 */
	@Override
	public Page<RcvHDTO> extractRcvHWithNativeSql(RcvQueryVO rcvQueryVO, PageParam pageParam) {
		this.startPage(pageParam);
		rcvQueryVO.setEnterpriseId(userUtils.getEnterpriseId());
		List<RcvHDTO> list = this.mapper.extractRcvHWithNativeSql(rcvQueryVO);
		return PageUtils.getPage(list);
	}

	/**
	 * 本地sql实现提取复检任务
	 */
	@Override
	public Page<TaskQcRecheckDetailDTO> extractTaskWithNativeSql(TaskQcDetailQueryVO taskQcDetailQueryVO) {
		String rcvHeaderId = taskQcDetailQueryVO.getRcvHeaderId();
//		AssertUtils.isNotBlank(rcvHeaderId, "头表id(rcvHeaderId)不可为空!");
		String rqcHeaderId = taskQcDetailQueryVO.getRqcHeaderId();
//		TaskQcDetailDTO taskQcDetailDTO = new TaskQcDetailDTO();
//		BeanUtils.copyProperties(taskQcDetailQueryVO, taskQcDetailDTO);
		String userId = userUtils.getUserId();
		String enterpriseId = userUtils.getEnterpriseId();
		taskQcDetailQueryVO.setExecutor(userId);
		taskQcDetailQueryVO.setEnterpriseId(enterpriseId);
		taskQcDetailQueryVO.setStatus("1"); // 查询状态为0的
		taskQcDetailQueryVO.setPageSize(500);
		taskQcDetailQueryVO.setPageNum(1);
		this.startPage(taskQcDetailQueryVO);
		List<TaskQcRecheckDetailDTO> list = this.mapper.findList(taskQcDetailQueryVO);
		return PageUtils.getPage(list);
	}

	/**
	 * 收货待处理生成复检任务
	 */
	@Override
	public Object excuteTask(List<RcvLinesDTO> list, String mtlOwnerId, String warehouseId, boolean isAuto) {
		UserDTO userDTO = userUtils.getUserDTO();
		Date now = new Date();

		// 收货明细转换复检任务
		List<RcvLinesDTO> hostedList = new ArrayList<>();
		boolean editFlag = Boolean.FALSE;
		for (RcvLinesDTO rcvLinesDTO : list) {
			this.rcvLinesToTask(rcvLinesDTO, userDTO, now, editFlag);
			hostedList.add(rcvLinesDTO);
		}

		// 生成代管库存(根据业务参数 BizConstant.INBOUND_PEND_RERQC_HOSTIN)
		// 默认走复检必须代管入库，如有变动，在此加判断条件即可控制代管
		// ObjectUtils.isNotNull(regValue) && "1".equals(regValue)
		if (true) {
			String inType = "1";    // 入库类型-正常
			String status = "5";    // 库存状态-代管
			// 代管入库
			hostedHelper.rcvLinesInHosted(hostedList, inType, status, userDTO, now, warehouseId);
		}
		return true;
	}

	/**
	 * 收货单转复检任务单
	 *
	 * @param rcvLinesDTO
	 * @param userDTO
	 * @param now
	 * @param editFlag
	 */
	private void rcvLinesToTask(RcvLinesDTO rcvLinesDTO, UserDTO userDTO, Date now, boolean editFlag) {
		TaskQcRecheckDetail detail = new TaskQcRecheckDetail();
		BeanUtils.copyProperties(rcvLinesDTO, detail);
		// 看是否需要补数据
		this.buildDefaultField(detail, editFlag, userDTO, now);
		this.buildField(detail, editFlag, userDTO, now);

		detail.setRefBillId(rcvLinesDTO.getRcvHeaderId());
		detail.setRefLineId(rcvLinesDTO.getRcvLineId());
		detail.setRefType(2);
		// 操作来源是:收货待处理
		detail.setAttribute1("1");

		this.mapper.save(detail);
		rcvLinesDTO.setTaskRecheckId(detail.getTaskRecheckId());
	}

	@Override
	public List<TaskQcRecheckDetail> findByIds(List<String> ids) {
		String[] idsArray = ids.toArray(new String[ids.size()]);
		return this.mapper.findByIds(TaskQcRecheckDetail.class, idsArray, null);
	}
}
