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

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

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.transaction.annotation.Transactional;

import com.uas.platform.b2b.dao.EnterpriseDao;
import com.uas.platform.b2b.dao.PurchaseOrderAllDao;
import com.uas.platform.b2b.dao.PurchaseOrderAllItemDao;
import com.uas.platform.b2b.dao.PurchaseOrderDao;
import com.uas.platform.b2b.dao.PurchaseOrderDoneDao;
import com.uas.platform.b2b.dao.PurchaseOrderEndDao;
import com.uas.platform.b2b.dao.PurchaseOrderItemDao;
import com.uas.platform.b2b.dao.PurchaseOrderReplyDao;
import com.uas.platform.b2b.dao.PurchaseOrderTodoDao;
import com.uas.platform.b2b.model.PurchaseOrder;
import com.uas.platform.b2b.model.PurchaseOrderAll;
import com.uas.platform.b2b.model.PurchaseOrderAllItem;
import com.uas.platform.b2b.model.PurchaseOrderDone;
import com.uas.platform.b2b.model.PurchaseOrderEnd;
import com.uas.platform.b2b.model.PurchaseOrderItem;
import com.uas.platform.b2b.model.PurchaseOrderReply;
import com.uas.platform.b2b.model.PurchaseOrderTodo;
import com.uas.platform.b2b.service.PurchaseOrderService;
import com.uas.platform.b2b.support.SystemSession;
import com.uas.platform.b2b.support.XingePusher;
import com.uas.platform.core.exception.IllegalOperatorException;
import com.uas.platform.core.exception.NotFoundException;
import com.uas.platform.core.model.Constant;
import com.uas.platform.core.model.PageInfo;
import com.uas.platform.core.model.Status;

@Service
public class PurchaseOrderServiceImpl implements PurchaseOrderService {

	@Autowired
	private PurchaseOrderDao purchaseOrderDao;

	@Autowired
	private PurchaseOrderAllDao purchaseOrderAllDao;

	@Autowired
	private PurchaseOrderTodoDao purchaseOrderTodoDao;

	@Autowired
	private PurchaseOrderDoneDao purchaseOrderDoneDao;

	@Autowired
	private PurchaseOrderEndDao purchaseOrderEndDao;

	@Autowired
	private PurchaseOrderReplyDao purchaseOrderReplyDao;

	@Autowired
	private PurchaseOrderItemDao purchaseOrderItemDao;

	@Autowired
	private PurchaseOrderAllItemDao purchaseOrderAllItemDao;

	@Autowired
	private EnterpriseDao enterpriseDao;

	public void save(List<PurchaseOrderAllItem> orderItems) {
		List<PurchaseOrderAllItem> newOrderItems = purchaseOrderAllItemDao.save(orderItems);
		// 将采购单信息推送通知供应商联系人UU号
		Set<Long> orderId = new HashSet<Long>();
		for (PurchaseOrderAllItem orderItem : newOrderItems) {
			if (!orderId.contains(orderItem.getOrder().getId())) {
				if (orderItem.getOrder().getVendUserUU() != null) {
					// 如果采购单单据存在客户联系人UU且UU正确--->客户联系人UU
					// 如果不存在，但是平台中企业供应商资料存在供应商联系人UU--->平台中供应商资料中的联系人UU
					// 否则不推送
					// Android
					XingePusher.pushSingleAccountAndroid(orderItem.getOrder().getVendUserUU().toString(), "新增一条客户采购单", "单号:"
							+ orderItem.getOrder().getCode() + ",客户:" + orderItem.getOrder().getEnterprise().getEnName(),
							"com.sas.mobile.activity.PurchaseActivity");
					// IOS
					XingePusher.pushSingleAccountIOS(orderItem.getOrder().getVendUserUU().toString(), "新增一条客户采购单-" + "单号:"
							+ orderItem.getOrder().getCode() + ",客户:" + orderItem.getOrder().getEnterprise().getEnName());
				}
				orderId.add(orderItem.getOrder().getId());
			}
		}
	}

	public Page<PurchaseOrder> findAllByPageInfo(final PageInfo pageInfo) {
		return purchaseOrderDao.findAll(new Specification<PurchaseOrder>() {

			public Predicate toPredicate(Root<PurchaseOrder> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
				query.where(pageInfo.getPredicates(root, query, builder));
				return null;
			}
		}, pageInfo);
	}

	@Override
	public Page<PurchaseOrderAll> findAllDetailByPageInfo(final PageInfo pageInfo) {
		return purchaseOrderAllDao.findAll(new Specification<PurchaseOrderAll>() {

			public Predicate toPredicate(Root<PurchaseOrderAll> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
				query.where(pageInfo.getPredicates(root, query, builder));
				return null;
			}
		}, pageInfo);
	}

	@Override
	public void reply(PurchaseOrderReply reply) {
		reply(reply, true);
	}

	/**
	 * @param reply
	 * @param isB2b
	 *            是否b2b新增
	 */
	@Transactional
	private void reply(PurchaseOrderReply reply, boolean isB2b) {
		if (isB2b) {
			reply.setDate(new Date());
			// 作为B2B->买家ERP数据是否已传输的标志--为传输
			reply.setStatus((short) Status.NOT_UPLOAD.value());
			// 作为B2B->卖家ERP数据是否已传输的标志--为传输
			reply.setSendStatus((short) Status.NOT_UPLOAD.value());
			reply.setRecorder(SystemSession.getUser().getUserName());
			reply.setType("供应商平台回复");
		}
		PurchaseOrderItem item = purchaseOrderItemDao.findOne(reply.getOrderItem().getId());
		Double replyQty = item.getReplyQty();
		replyQty = replyQty == null ? 0 : replyQty;
		item.setReplyQty(replyQty + reply.getQty());
		if (item.getReplyQty() > item.getQty())
			throw new IllegalOperatorException("回复的数量合计超过了订单数量");
		purchaseOrderReplyDao.save(reply);
		purchaseOrderItemDao.updateByReply(reply.getDelivery(), reply.getRemark(), item.getId());
		PurchaseOrder order = item.getOrder();
		// 订单主记录状态
		order = updateOrderStatus(order.getId());
		// 将回复信息推送给采购企业采购员（或管理员）
		if (order.getUserUU() != null) {
			// Android
			XingePusher.pushSingleAccountAndroid(order.getUserUU().toString(), "新增采购单回复", "单号:" + order.getCode() + ",供应商:"
					+ enterpriseDao.findOne(order.getVendUU()).getEnName(), "");
			// IOS
			XingePusher.pushSingleAccountIOS(order.getUserUU().toString(), "新增采购单回复" + "单号:" + order.getCode() + ",供应商:"
					+ enterpriseDao.findOne(order.getVendUU()).getEnName());
		}
	}

	/**
	 * 修改客户采购单的状态
	 */
	private PurchaseOrder updateOrderStatus(long orderId) {
		int notReply = purchaseOrderItemDao.getCountByStatus(orderId, (short) Status.NOT_REPLY.value());
		PurchaseOrder order = purchaseOrderDao.findOne(orderId);
		order.setStatus((short) (notReply > 0 ? Status.NOT_REPLY.value() : Status.REPLIED.value()));
		if (purchaseOrderItemDao.getCountByReply(orderId) > 0)
			order.setReply(Constant.YES);
		if (purchaseOrderItemDao.getCountByEnd(orderId, Constant.YES) > 0)
			order.setEnd(Constant.YES);
		else
			order.setEnd(Constant.NO);// 反结案之后
		return purchaseOrderDao.save(order);
	}

	@Override
	public PurchaseOrderAll findByCode(String code) {
		List<PurchaseOrderAll> purchaseOrderAlls = purchaseOrderAllDao.findByVendUUAndCode(SystemSession.getUser().getEnterprise().getUu(),
				code);
		if (purchaseOrderAlls.size() == 0)
			throw new NotFoundException(code);
		return purchaseOrderAlls.get(0);
	}

	@Override
	public PurchaseOrderAll findById(Long id) {
		List<PurchaseOrderAll> purchaseOrderAlls = purchaseOrderAllDao.findById(id);
		if (purchaseOrderAlls.size() == 0)
			throw new NotFoundException();
		return purchaseOrderAlls.get(0);
	}

	@Override
	public void reply(String[] orderItemIdString) {
		for (String orderItemId : orderItemIdString) {
			PurchaseOrderItem orderItem = purchaseOrderItemDao.findOne(Long.parseLong(orderItemId));
			PurchaseOrderReply reply = new PurchaseOrderReply();
			reply.setOrderItem(orderItem);
			reply.setDelivery(orderItem.getDelivery());
			reply.setRemark("批量回复");
			if (orderItem.getReplyQty() == null)
				orderItem.setReplyQty((double) 0);
			reply.setQty(orderItem.getQty() - orderItem.getReplyQty());
			reply(reply, true);
		}

	}

	@Override
	public List<PurchaseOrderReply> findReplyByOrderItem(long orderItemId) {
		return purchaseOrderReplyDao.findByOrderItemId(orderItemId);
	}

	@Override
	public List<PurchaseOrderReply> findNotUploadReply() {
		return purchaseOrderReplyDao
				.findByEnUUAndStatus(SystemSession.getUser().getEnterprise().getUu(), (short) Status.NOT_UPLOAD.value());
	}

	@Override
	public List<PurchaseOrderReply> findNotSendReply() {
		return purchaseOrderReplyDao.findByVendUUAndSendStatus(SystemSession.getUser().getEnterprise().getUu(),
				(short) Status.NOT_UPLOAD.value());
	}

	@Override
	public void onReplyUploadSuccess(String[] idArray) {
		for (String id : idArray) {
			PurchaseOrderReply reply = purchaseOrderReplyDao.findOne(Long.parseLong(id));
			if (reply != null) {
				reply.setStatus((short) Status.DOWNLOADED.value());
				purchaseOrderReplyDao.save(reply);
			}
		}
	}

	@Override
	public void onReplyDownSuccess(String[] idArray) {
		for (String id : idArray) {
			PurchaseOrderReply reply = purchaseOrderReplyDao.findOne(Long.parseLong(id));
			if (reply != null) {
				reply.setSendStatus((short) Status.DOWNLOADED.value());
				purchaseOrderReplyDao.save(reply);
			}
		}
	}

	@Override
	public void reply(List<PurchaseOrderReply> replies) {
		for (PurchaseOrderReply reply : replies)
			reply(reply, false);
	}

	@Override
	public List<PurchaseOrderAll> findNotUploadOrder() {
		return purchaseOrderAllDao.findByVendUUAndSendStatus(SystemSession.getUser().getEnterprise().getUu(),
				(short) Status.NOT_UPLOAD.value());
	}

	@Override
	public void onSaleDownSuccess(String[] idArray) {
		for (String id : idArray) {
			PurchaseOrder order = purchaseOrderDao.findOne(Long.parseLong(id));
			if (order != null) {
				order.setSendStatus((short) Status.DOWNLOADED.value());
				purchaseOrderDao.save(order);
			}
		}
	}

	@Override
	public List<PurchaseOrderItem> findNotSendEnd() {
		return purchaseOrderItemDao.findByVendUUAndEndStatus(SystemSession.getUser().getEnterprise().getUu(),
				(short) Status.NOT_UPLOAD.value());
	}

	@Override
	public void onEndDownSuccess(String[] idArray) {
		for (String id : idArray) {
			PurchaseOrderItem orderItem = purchaseOrderItemDao.findOne(Long.parseLong(id));
			if (orderItem != null) {
				orderItem.setEndStatus((short) Status.DOWNLOADED.value());
				purchaseOrderItemDao.save(orderItem);
			}
		}
	}

	@Override
	public void saveItems(List<PurchaseOrderItem> items) {
		purchaseOrderItemDao.save(items);
		for (PurchaseOrderItem item : items)
			// 明细结案情况下，明细状态为已回复（即不再处理），此时同时修改主记录状态
			updateOrderStatus(item.getOrder().getId());
	}

	@Override
	public int getOnhandCount() {
		return purchaseOrderDao
				.getCountByVendUUAndStatus(SystemSession.getUser().getEnterprise().getUu(), (short) Status.NOT_REPLY.value());
	}

	@Override
	public Page<PurchaseOrderTodo> findTodoByPageInfo(final PageInfo pageInfo) {
		return purchaseOrderTodoDao.findAll(new Specification<PurchaseOrderTodo>() {

			public Predicate toPredicate(Root<PurchaseOrderTodo> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
				query.where(pageInfo.getPredicates(root, query, builder));
				return null;
			}
		}, pageInfo);
	}

	@Override
	public Page<PurchaseOrderDone> findDoneByPageInfo(final PageInfo pageInfo) {
		return purchaseOrderDoneDao.findAll(new Specification<PurchaseOrderDone>() {

			public Predicate toPredicate(Root<PurchaseOrderDone> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
				query.where(pageInfo.getPredicates(root, query, builder));
				return null;
			}
		}, pageInfo);
	}

	@Override
	public Page<PurchaseOrderEnd> findEndByPageInfo(final PageInfo pageInfo) {
		return purchaseOrderEndDao.findAll(new Specification<PurchaseOrderEnd>() {

			public Predicate toPredicate(Root<PurchaseOrderEnd> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
				query.where(pageInfo.getPredicates(root, query, builder));
				return null;
			}
		}, pageInfo);
	}

}
