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

import com.prolog.cs.biz.inbound.constant.InboundBizConstant;
import com.prolog.cs.biz.inbound.dao.rqc.RqcReHeadersMapper;
import com.prolog.cs.biz.inbound.dto.PageParam;
import com.prolog.cs.biz.inbound.dto.rcv.RcvHAndPDTO;
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.rcv.RcvLinesProfilesDTO;
import com.prolog.cs.biz.inbound.dto.rqc.RqcReDTO;
import com.prolog.cs.biz.inbound.dto.rqc.RqcReHeadersDTO;
import com.prolog.cs.biz.inbound.dto.rqc.RqcReLinesDTO;
import com.prolog.cs.biz.inbound.dto.task.TaskQcRecheckDetailDTO;
import com.prolog.cs.biz.inbound.model.rqc.RqcReHeaders;
import com.prolog.cs.biz.inbound.service.impl.BaseServiceImpl;
import com.prolog.cs.biz.inbound.service.rcv.RcvHeadersService;
import com.prolog.cs.biz.inbound.service.rcv.RcvLinesProfilesService;
import com.prolog.cs.biz.inbound.service.rcv.RcvLinesService;
import com.prolog.cs.biz.inbound.service.rqc.RqcReHeadersService;
import com.prolog.cs.biz.inbound.service.rqc.RqcReLinesService;
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.RqcHQueryVO;
import com.prolog.cs.biz.inbound.vo.TaskQcDQueryVO;
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.dao.util.PageUtils;
import com.prolog.framework.utils.AssertUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.Validator;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;

@Service
public class RqcReHeadersServiceImpl extends BaseServiceImpl<RqcReHeaders> implements RqcReHeadersService {

	@Resource
	private RqcReHeadersMapper mapper;

	@Resource
	private UserUtils userUtils;

	@Resource
	private TaskQcRecheckDetailService taskQcRecheckDetailService;

	@Resource
	private Validator validator;

	@Resource
	private RqcReLinesService rqcReLinesService;

	@Resource
	private RcvLinesProfilesService rcvLinesProfilesService;

	@Resource
	private RcvLinesService rcvLinesService;

	@Resource
	private RcvHeadersService rcvHeadersService;

	private final static String addMsg = "复检头保存操作";
//	private final static String batchAddMsg = "复检头批量保存操作";

	/**
	 * 原生sql实现任务
	 */
	@Override
	public Page<TaskQcRecheckDetailDTO> extractRqcReTask(TaskQcDetailQueryVO taskQcDetailQueryVO) {
		// 提取质检任务池中数据
		return taskQcRecheckDetailService.extractTaskWithNativeSql(taskQcDetailQueryVO);
	}

	/**
	 * 原生sql实现查询头
	 */
	@Override
	public Page<RcvHDTO> extractRcvHAndPro(RcvQueryVO rcvQueryVO, PageParam pageParam) {
		Integer times = rcvQueryVO.getTimes();
		if (ObjectUtils.isNull(times)) {
			times = InboundBizConstant.DEFAULT_RECHECK_TIMES;
		}
		return taskQcRecheckDetailService.extractRcvHWithNativeSql(rcvQueryVO, pageParam);
	}

	/**
	 * 代码实现查询任务
	 */
	@Override
	public Page<TaskQcRecheckDetailDTO> extractRqcReTask(TaskQcDQueryVO taskQcDQueryVO, PageParam pageParam) {
		// 提取质检任务池中数据
		TaskQcRecheckDetailDTO rd = new TaskQcRecheckDetailDTO();
		BeanUtils.copyProperties(taskQcDQueryVO, rd);
		Page<TaskQcRecheckDetailDTO> page = taskQcRecheckDetailService.findList(rd, pageParam);
		List<TaskQcRecheckDetailDTO> list = page.getList();

		List<String> rcvLineIdList = Optional.ofNullable(list).orElse(Collections.emptyList()).stream().distinct()
				.map(p -> p.getRcvLineId()).collect(Collectors.toList());
		if (ObjectUtils.isNotNull(rcvLineIdList)) {
			List<RcvLinesProfilesDTO> rcvPList = rcvLinesProfilesService.searchByIdList(rcvLineIdList);
			List<RcvLinesDTO> rcvLList = rcvLinesService.searchByIdList(rcvLineIdList);
			// 1. 根据行id分组
			Map<String, List<TaskQcRecheckDetailDTO>> collect = Optional.ofNullable(list)
					.orElse(Collections.emptyList()).stream().distinct()
					.collect(Collectors.groupingBy(TaskQcRecheckDetailDTO::getRcvLineId));
			Map<String, List<RcvLinesProfilesDTO>> collect2 = Optional.ofNullable(rcvPList)
					.orElse(Collections.emptyList()).stream().distinct()
					.collect(Collectors.groupingBy(RcvLinesProfilesDTO::getRcvLineId));
			Map<String, List<RcvLinesDTO>> collect3 = Optional.ofNullable(rcvLList).orElse(Collections.emptyList())
					.stream().distinct().collect(Collectors.groupingBy(RcvLinesDTO::getRcvLineId));
			Set<Entry<String, List<TaskQcRecheckDetailDTO>>> entrySet = collect.entrySet();
			// 2. set进对应的拓展信息
			for (Entry<String, List<TaskQcRecheckDetailDTO>> entry : entrySet) {
				List<TaskQcRecheckDetailDTO> value = entry.getValue();
				String key = entry.getKey();
				List<RcvLinesProfilesDTO> list2 = collect2.get(key);
				List<RcvLinesDTO> list3 = collect3.get(key);
				if (ObjectUtils.isNotNull(value) && ObjectUtils.isNotNull(list2)) {
					value.get(0).setRcvLinesProfilesDTO(list2.get(0));
					value.get(0).setRcvLinesDTO(list3.get(0));
				}
			}
		}
		return page;
	}

	/**
	 * 代码实现查询头
	 */
	@Override
	public Page<RcvHAndPDTO> extractRcvH(RcvQueryVO rcvQueryVO, PageParam pageParam) {
		// 提取收货头表信息
		// 首先获取所有质检池中待质检的任务
		List<TaskQcRecheckDetailDTO> findAll = taskQcRecheckDetailService.findAll(null);
		if (ObjectUtils.isNull(findAll))
			return null;
		// 获取头表id列表
		List<String> rcvHeaderId = findAll.stream().distinct()
				.collect(Collectors.groupingBy(TaskQcRecheckDetailDTO::getRcvHeaderId)).entrySet().stream()
				.map(p -> p.getKey()).collect(Collectors.toList());
		rcvQueryVO.setIncludeHids(rcvHeaderId);

		return rcvHeadersService.findListWithPro(rcvQueryVO, pageParam);
	}

	@Transactional
	@Override
	public Object addWithRelated(RqcReDTO rqcReDTO) {
		// 极联保存
		RqcReHeadersDTO rqcReHeadersDTO = rqcReDTO.getRqcReHeadersDTO();
		AssertUtils.notNull(rqcReHeadersDTO, "新增复检单对象不可为空!");
		List<RqcReLinesDTO> rqcReLinesDTOList = rqcReDTO.getRqcReLinesDTOList();
		AssertUtils.notNull(rqcReLinesDTOList, "新增的复检明细行数据为空!");
		UserDTO userDTO = userUtils.getUserDTO();
		Date now = new Date();
		String masterId = (String) this.add(rqcReHeadersDTO, true, userDTO, now);

		//校验头单与明细行是否一致
		long count = rqcReLinesDTOList.stream().filter(x -> x.getRqcHeaderId().equals(rqcReHeadersDTO.getRqcHeaderId())).count();
		if(count==0){
			throw new BizException("验收单主表与明细不一致，请检查！");
		}

		rqcReLinesService.batchAdd(rqcReLinesDTOList, masterId, userDTO, now);
		return true;
	}

	@Override
	public Page<RqcReHeadersDTO> findList(RqcReHeadersDTO rqcReHeadersDTO, PageParam pageParam) {
		Criteria criteria = buildPageParam(pageParam, true, null, RqcReHeaders.class);
		Restriction r = buildCondition(rqcReHeadersDTO);
		criteria.setRestriction(r);
		this.startPage(pageParam);
		List<RqcReHeaders> list = this.mapper.findByCriteria(criteria);
		Page<RqcReHeaders> page = PageUtils.getPage(list);
		Page<RqcReHeadersDTO> page2 = this.buildPage(page, (p) -> {
			RqcReHeadersDTO target = new RqcReHeadersDTO();
			BeanUtils.copyProperties(p, target);
			return target;
		});
		return page2;
	}

	private Object add(RqcReHeadersDTO rqcReHeadersDTO, boolean vaildateFlag, UserDTO userDTO, Date now) {
		if (ObjectUtils.isNull(userDTO))
			userDTO = userUtils.getUserDTO();
		if (ObjectUtils.isNull(userDTO))
			now = new Date();
		boolean editFlag = Boolean.FALSE;
		this.buildDefaultField(rqcReHeadersDTO, editFlag, userDTO, now);
		if (vaildateFlag) {
			int row = 0;
			this.vaildateModel(rqcReHeadersDTO, editFlag, userDTO, row, validator, addMsg);
		}
		RqcReHeaders rqcReHeaders = new RqcReHeaders();
		BeanUtils.copyProperties(rqcReHeadersDTO, rqcReHeaders);
		this.buildField(rqcReHeaders, editFlag, userDTO, now);
		rqcReHeaders.setRcvHeaderId(rqcReHeadersDTO.getRqcHeaderId());
		this.mapper.save(rqcReHeaders);
		return rqcReHeaders.getRqcReHeaderId(); // 复检主键id
	}

	private void buildDefaultField(RqcReHeadersDTO rqcReHeadersDTO, boolean editFlag, UserDTO userDTO, Date now) {
		// 构建默认值字段
		String status = rqcReHeadersDTO.getStatus();
		Date billDate = rqcReHeadersDTO.getBillDate();
		if (!editFlag && ObjectUtils.isNull(status))
			rqcReHeadersDTO.setStatus("1"); // 默认状态为可用

		if (!editFlag && ObjectUtils.isNull(billDate))
			rqcReHeadersDTO.setBillDate(now);
	}

	@Override
	public Object add(RqcReHeadersDTO rqcReHeadersDTO) {
		// TODO vaildate
		UserDTO userDTO = userUtils.getUserDTO();
		RqcReHeaders rqcReHeaders = new RqcReHeaders();
		BeanUtils.copyProperties(rqcReHeadersDTO, rqcReHeaders);
		this.vaildateModel(rqcReHeaders, false, userDTO);
		this.buildField(rqcReHeaders, false, userDTO);
		this.mapper.save(rqcReHeaders);
		return "";
	}

	private void buildField(RqcReHeaders rqcReHeaders, boolean editFlag, UserDTO userDTO, Date now) {
		this.setBaseSysField(rqcReHeaders, editFlag, userDTO, now);
		vaildateModelRepeated(rqcReHeaders, editFlag, userDTO);

	}

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

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

	@Override
	@Transactional
	public Object batchAdd(List<RqcReHeadersDTO> rqcReHeadersDTOList) {
		// TODO
		UserDTO userDTO = userUtils.getUserDTO();
		for (RqcReHeadersDTO rqcReHeadersDTO : rqcReHeadersDTOList) {
			RqcReHeaders rqcReHeaders = new RqcReHeaders();
			BeanUtils.copyProperties(rqcReHeadersDTO, rqcReHeaders);
			this.vaildateModel(rqcReHeaders, false, userDTO);
			this.buildField(rqcReHeaders, false, userDTO);
			this.mapper.save(rqcReHeaders);
		}
		return "";
	}

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

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

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

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

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

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

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

	private Restriction buildCondition(RqcReHeadersDTO rqcReHeadersDTO) {
		// TODO
		return null;
	}

	@Override
	public Page<RqcReHeadersDTO> findList(RqcHQueryVO rqcHQueryVO, PageParam pageParam) {
		rqcHQueryVO.setEnterpriseId(userUtils.getEnterpriseId());
		String status = rqcHQueryVO.getStatus();
		if (ObjectUtils.isNull(status))
			rqcHQueryVO.setStatus("1"); // 默认可用的
		this.startPage(pageParam);
		List<RqcReHeadersDTO> list = this.mapper.findList(rqcHQueryVO);
		return PageUtils.getPage(list);
	}

	@Override
	public RqcReHeadersDTO findByPkId(String pkId) {
		// TODO
		AssertUtils.isNotBlank(pkId, "主键id为空!");
		RqcReHeadersDTO dto = this.mapper.findByPkId(pkId);
		AssertUtils.notNull(dto, "查询对象为空!");
		return dto;
	}
//	@Override
//	public RqcReHeadersDTO findByPkId(String pkId) {
//		// TODO
//		RqcReHeaders rqcReHeaders = this.findById(pkId);
//		AssertUtils.notNull(rqcReHeaders, "model empty!");
//		RqcReHeadersDTO rqcReHeadersDTO = new RqcReHeadersDTO();
//		BeanUtils.copyProperties(rqcReHeaders, rqcReHeadersDTO);
//		return rqcReHeadersDTO;
//	}

}
