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

import com.uas.platform.b2b.core.util.ContextUtils;
import com.uas.platform.b2b.dao.MakeAcceptDao;
import com.uas.platform.b2b.dao.MakeAcceptItemDao;
import com.uas.platform.b2b.dao.MakeOrderDao;
import com.uas.platform.b2b.erp.model.OrderDetailPrice;
import com.uas.platform.b2b.erp.model.ProdInOutRefreshPrice;
import com.uas.platform.b2b.erp.service.MakeService;
import com.uas.platform.b2b.event.MakeAcceptSaveReleaseEvent;
import com.uas.platform.b2b.model.MakeAccept;
import com.uas.platform.b2b.model.MakeAcceptItem;
import com.uas.platform.b2b.model.MakeOrder;
import com.uas.platform.b2b.model.OrderType;
import com.uas.platform.b2b.service.MakeAcceptService;
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 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 javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class MakeAcceptServiceImpl implements MakeAcceptService {

	@Autowired
	private MakeAcceptItemDao makeAcceptItemDao;

	@Autowired
	private MakeOrderDao makeOrderDao;

	@Autowired
	private MakeAcceptDao makeAcceptDao;

	@Autowired
    private MakeService makeService;

	@Override
	public void save(List<MakeAcceptItem> acceptItems) {
		acceptItems = makeAcceptItemDao.save(acceptItems);
		for (MakeAcceptItem acceptItem : acceptItems) {
			MakeOrder makeOrders = acceptItem.getOrder();
			List<MakeOrder> orders = makeOrderDao.findByEnUUAndCode(makeOrders.getEnUU(), makeOrders.getCode());
			if (orders.size() > 0) {
				MakeOrder order = orders.get(0);
				order.setAcceptQty(
						(order.getAcceptQty() == null ? 0 : orders.get(0).getAcceptQty()) + acceptItem.getQty());
				makeOrderDao.save(order);
			}
		}
		// 消息事件
		ContextUtils.publishEvent(new MakeAcceptSaveReleaseEvent(MakeAcceptItem.distinct(acceptItems)));
	}

	@Override
	public MakeAccept findById(Long id) {
		return makeAcceptDao.findOne(id);
	}

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

	@Override
	public Page<MakeAccept> findAllByPageInfo(final PageInfo pageInfo, final String keyword, final Long fromDate,
			final Long endDate) {
		if (fromDate != null) {
			pageInfo.expression(PredicateUtils.gte("date", new Date(fromDate), false));
		}
		if (endDate != null) {
			pageInfo.expression(PredicateUtils.lte("date", new Date(endDate), false));
		}
		return makeAcceptDao.findAll(new Specification<MakeAccept>() {
			@Override
            public Predicate toPredicate(Root<MakeAccept> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
				return query.where(pageInfo.getPredicates(root, query, builder)).getRestriction();
			}
		}, pageInfo);
	}

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

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

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

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

	@Override
	public List<MakeAcceptItem> convertPirceForProdIn(List<ProdInOutRefreshPrice> prodInOuts) {
		List<MakeAcceptItem> items = new ArrayList<MakeAcceptItem>();
		List<OrderDetailPrice> detailPriceList = new ArrayList<>();
		if (!CollectionUtils.isEmpty(prodInOuts)) {
			for (ProdInOutRefreshPrice prod : prodInOuts) {
				MakeAcceptItem returnItem = makeAcceptItemDao.findByEnUUAndCodeAndNumber(
						SystemSession.getUser().getEnterprise().getUu(), prod.getPbu_inoutno(), prod.getPbu_pdno());
				if (null != returnItem) {
					returnItem.setOrderPrice(prod.getPbu_orderprice());
					returnItem.setTaxrate(prod.getPbu_taxrate());
					items.add(returnItem);
					if (null != returnItem.getOrderId()) {
						detailPriceList.add(new OrderDetailPrice(returnItem.getOrderId(), returnItem.getOrderPrice(), returnItem.getTaxrate()));
					}
				}
			}
		}
		if (!CollectionUtils.isEmpty(detailPriceList)) {
            makeService.refreshPrice(detailPriceList, OrderType.makeaccpet.name());
        }
		return items;
	}
}
