package com.uas.platform.b2b.service.impl;

import com.uas.platform.b2b.core.util.ContextUtils;
import com.uas.platform.b2b.dao.PurchaseAcceptDao;
import com.uas.platform.b2b.dao.PurchaseAcceptItemDao;
import com.uas.platform.b2b.dao.PurchaseOrderItemDao;
import com.uas.platform.b2b.event.PurchaseAcceptSaveReleaseEvent;
import com.uas.platform.b2b.model.PurchaseAccept;
import com.uas.platform.b2b.model.PurchaseAcceptItem;
import com.uas.platform.b2b.model.PurchaseOrderItem;
import com.uas.platform.b2b.model.SearchFilter;
import com.uas.platform.b2b.search.SearchService;
import com.uas.platform.b2b.service.PurchaseAcceptService;
import com.uas.platform.b2b.support.SystemSession;
import com.uas.platform.core.model.Constant;
import com.uas.platform.core.model.PageInfo;
import com.uas.platform.core.model.Status;
import com.uas.platform.core.persistence.criteria.PredicateUtils;
import com.uas.search.b2b.model.PageParams;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.*;
import java.util.*;

@Service
public class PurchaseAcceptServiceImpl implements PurchaseAcceptService {

	@Autowired
	private PurchaseAcceptItemDao purchaseAcceptItemDao;

	@Autowired
	private PurchaseAcceptDao purchaseAcceptDao;

	@Autowired
	private PurchaseOrderItemDao purchaseOrderItemDao;

	@Autowired
	private SearchService searchService;

	@Override
	public void save(List<PurchaseAcceptItem> acceptItems) {
		acceptItems = purchaseAcceptItemDao.save(acceptItems);
		// 关联订单的验收数量
		for (PurchaseAcceptItem acceptItem : acceptItems) {
			if (acceptItem.getOrderItem() != null) {
				List<PurchaseOrderItem> orderItems = purchaseOrderItemDao.findByEnUUAndOrderCodeAndNumber(
						acceptItem.getOrderItem().getOrder().getEnUU(), acceptItem.getOrderItem().getOrder().getCode(),
						acceptItem.getOrderItem().getNumber());
				if (orderItems.size() > 0) {
					PurchaseOrderItem orderItem = orderItems.get(0);
					orderItem.setAcceptQty((orderItem.getAcceptQty() == null ? 0 : orderItems.get(0).getAcceptQty())
							+ acceptItem.getQty());
					if(Objects.equals(orderItem.getAcceptQty(), orderItem.getQty())) { //全部验收则将单据转成已回复
					    orderItem.setStatus((short) Status.REPLIED.value());
                    }
					purchaseOrderItemDao.save(orderItem);
				}
			}
		}
		// 产生消息
		ContextUtils.publishEvent(new PurchaseAcceptSaveReleaseEvent(PurchaseAcceptItem.distinct(acceptItems)));
	}

	@Override
	public void nonPosting(List<PurchaseAccept> accepts) {
		if (!CollectionUtils.isEmpty(accepts)) {
			for (PurchaseAccept accept : accepts) {
				if (accept.getSendStatus() == Status.DOWNLOADED.value()) {
					// 已传输到供应商ERP，修改单据反过账状态
					accept.setNonPosting(Constant.YES);
					purchaseAcceptDao.save(accept);
				} else {
					// 未传输到供应商ERP，直接删除平台上的单据
					purchaseAcceptDao.delete(accept);
				}
				// 关联订单的验收数量
				if (!CollectionUtils.isEmpty(accept.getAcceptItems())) {
					for (PurchaseAcceptItem acceptItem : accept.getAcceptItems()) {
						List<PurchaseOrderItem> orderItems = purchaseOrderItemDao.findByEnUUAndOrderCodeAndNumber(
								acceptItem.getOrderItem().getOrder().getEnUU(),
								acceptItem.getOrderItem().getOrder().getCode(), acceptItem.getOrderItem().getNumber());
						if (orderItems.size() > 0) {
							PurchaseOrderItem orderItem = orderItems.get(0);
							// 已接受数未空或小于本次验收单数目，设为0
							if (orderItem.getAcceptQty() == null || orderItem.getAcceptQty() < acceptItem.getQty()) {
								orderItem.setAcceptQty((double) 0);
							} else {// 否则减去本次的验收数量
								orderItem.setAcceptQty(orderItem.getAcceptQty() - acceptItem.getQty());
							}
							purchaseOrderItemDao.save(orderItem);
						}
					}
				}
			}
		}
	}

	@Override
	public List<PurchaseAccept> findNotUpload() {
		return purchaseAcceptDao.findByVendUUAndSendStatus(SystemSession.getUser().getEnterprise().getUu(),
				(short) Status.NOT_UPLOAD.value());
	}

	@Override
	public void onUploadSuccess(String[] idArray) {
		for (String id : idArray) {
			PurchaseAccept accept = purchaseAcceptDao.findOne(Long.parseLong(id));
			if (accept != null) {
				accept.setSendStatus((short) Status.DOWNLOADED.value());
				purchaseAcceptDao.save(accept);
			}
		}
	}

	@Override
	public Page<PurchaseAccept> findAllByPageInfo(final PageInfo pageInfo, final SearchFilter filter) {
		if (filter != null) {
			if (StringUtils.hasText(filter.getKeyword())) {
				List<Object> lists = new ArrayList<>();
				PageParams pageParams = new PageParams();
				ModelMap map = new ModelMap();
				map.put("pa_venduu", SystemSession.getUser().getEnterprise().getUu());
				pageParams.setFilters(map);
				for (PurchaseAccept list : searchService.searchPurchaseAcceptIds(filter.getKeyword(), pageParams)
						.getContent()) {
					lists.add(list.getId());
				}
				pageInfo.expression(PredicateUtils.in("id", lists, false));
			}
			if (filter.getFromDate() != null) {
                pageInfo.expression(PredicateUtils.gte("date", new Date(filter.getFromDate()), false));
            }
			if (filter.getEndDate() != null) {
                pageInfo.expression(PredicateUtils.lte("date", new Date(filter.getEndDate()), false));
            }
			if (!CollectionUtils.isEmpty(filter.getDistribute())) {
                pageInfo.expression(PredicateUtils.in("enUU", filter.getDistribute(), false));
            }
		}
		Page<PurchaseAccept> pageAccept = purchaseAcceptDao.findAll(new Specification<PurchaseAccept>() {
			@Override
			public Predicate toPredicate(Root<PurchaseAccept> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
				Predicate[] predicates = pageInfo.getPredicates(root, query, builder);
				if (filter != null && filter.getFromDelivery() != null) {
					predicates = Arrays.copyOf(predicates, predicates.length + 1);
					SetJoin<PurchaseAccept, PurchaseAcceptItem> join = root
							.join(root.getModel().getSet("acceprItems", PurchaseAcceptItem.class), JoinType.INNER);
					Predicate p = builder.greaterThanOrEqualTo(join.get("delivery").as(Date.class),
							new Date(filter.getFromDelivery()));
					predicates[predicates.length - 1] = p;
				}
				return query.where(predicates).getRestriction();
			}
		}, pageInfo);
		return pageAccept;
	}

	@Override
	public PurchaseAccept findById(Long id) {
		return purchaseAcceptDao.findOne(id);
	}

	@Override
	public List<PurchaseAccept> getNonPosting() {
		return purchaseAcceptDao.findByVendUUAndNonPosting(SystemSession.getUser().getEnterprise().getUu(),
				Constant.YES);
	}

	@Override
	public void onNonPostingUploadSuccess(String[] idArray) {
		for (String id : idArray) {
			PurchaseAccept accept = purchaseAcceptDao.findOne(Long.parseLong(id));
			if (accept != null) {
				purchaseAcceptDao.delete(accept);
			}
		}
	}

}
