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

import com.uas.platform.b2b.core.util.ContextUtils;
import com.uas.platform.b2b.core.util.ThreadTask;
import com.uas.platform.b2b.dao.*;
import com.uas.platform.b2b.erp.model.SaleDownChangeReply;
import com.uas.platform.b2b.event.PurchaseOrderChangeSaveReleaseEvent;
import com.uas.platform.b2b.model.*;
import com.uas.platform.b2b.search.SearchService;
import com.uas.platform.b2b.service.PurchaseOrderChangeService;
import com.uas.platform.b2b.support.SystemSession;
import com.uas.platform.b2b.support.XingePusher;
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.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;
import java.util.*;

@Service
@Transactional
public class PurchaseOrderChangeServiceImpl implements PurchaseOrderChangeService {

	@Autowired
	private PurchaseOrderChangeDao purchaseOrderChangeDao;

	@Autowired
	private PurchaseOrderChangeItemDao purchaseOrderChangeItemDao;

	@Autowired
	private EnterpriseDao enterpriseDao;

	@Autowired
	private PurchaseOrderDao purchaseOrderDao;

	@Autowired
	private PurchaseOrderItemDao purchaseOrderItemDao;

	@Autowired
	private UserBaseInfoDao userBaseInfoDao;

	@Autowired
	private SearchService searchService;

	@Autowired
	private DistributeDao distributeDao;

	@Autowired
	private  RoleDao roleDao;

	@Autowired
	private  UserOrderDao userOrderDao;

	@Autowired
	private  UserDao userDao;

	@Autowired
	private VendorDao vendorDao;

	@Override
	public void save(List<PurchaseOrderChangeItem> changeItems) {
		changeItems = purchaseOrderChangeItemDao.save(changeItems);
		saveUserOrders(PurchaseOrderChangeItem.distinct(changeItems));
		ContextUtils.publishEvent(new PurchaseOrderChangeSaveReleaseEvent(PurchaseOrderChangeItem.distinct(changeItems)));
		// 将采购变更单信息推送通知供应商联系人UU号
		Set<Long> orderId = new HashSet<Long>();
		for (PurchaseOrderChangeItem orderItem : changeItems) {
			if (!orderId.contains(orderItem.getOrderChange().getId())) {
				orderId.add(orderItem.getOrderChange().getId());
				// 买家直接批准变更，无需卖家确认的情况下，直接变更平台的客户采购单
				if (orderItem.getOrderChange().isAgreed() || orderItem.getOrderChange().getUnNeedReply() == Constant.YES) {
                    changeOrder(orderItem.getOrderChange());
                }
			}
		}
	}

	private void saveUserOrders(final List<PurchaseOrderChange> changes) {

		ThreadTask.getInstance().execute(new Runnable() {
			@Override
			public void run() {
            	/* 添加供应商的阅读记录*/
				for(PurchaseOrderChange change : changes) {
					Set<Long> userUUs = new HashSet<>();
					// 添加管理员
					List<Role> roles = roleDao.findByEnUUAndIssys(change.getVendUU(), Constant.YES);
					if (!CollectionUtils.isEmpty(roles)) {
						List<User> admins = userDao.findByRole(roles.get(0).getId());
						for (User admin : admins) {
							if (!userUUs.contains(admin.getUserUU())) {
								userUUs.add(admin.getUserUU());
							}
						}
					}
					List<Vendor> vendors = vendorDao.findByMyEnUUAndVendUU(change.getEnUU(), change.getVendUU());
					// 查找有权限的用户
					if (!CollectionUtils.isEmpty(vendors)) {
						Long vendorId = vendors.get(0).getId();
						List<Distribute> distributes = distributeDao.findByVendorId(vendorId);
						if (!CollectionUtils.isEmpty(distributes)) {
							for (Distribute distribute : distributes) {
								if (!userUUs.contains(distribute.getUserUU())) {
									userUUs.add(distribute.getUserUU());
								}
							}
						}
					}
					UserOrders userOrders;
					List<UserOrders> list = new ArrayList<>();
					for (Long userUU : userUUs) {
						if (userUU == null) {
							continue;
						}
						userOrders = new UserOrders(userUU, change.getVendUU(), change.getId(), "sale", "purc$changes");
						list.add(userOrders);
					}

                	/* 添加采购员的阅读记录*/
                	if (change.getUserUU() != null) {
						userOrders = new UserOrders(change.getUserUU(), change.getEnUU(), change.getId(), "purc", "purc$changes");
                        userOrders.setReadStatus((short) Status.READ.value());
                        list.add(userOrders);
					}
					userOrderDao.save(list);
				}
			}
		});
	}

	@Override
	public List<PurchaseOrderChange> findNotUploadReply() {
		return purchaseOrderChangeDao.findByEnUUAndStatusAndBackStatus(SystemSession.getUser().getEnterprise().getUu(),
				(short) Status.REPLIED.value(), (short) Status.NOT_UPLOAD.value());
	}

	@Override
	public void onReplyUploadSuccess(String[] idArray) {
		for (String id : idArray) {
			PurchaseOrderChange change = purchaseOrderChangeDao.findOne(Long.parseLong(id));
			if (change != null) {
				change.setBackStatus((short) Status.DOWNLOADED.value());
				purchaseOrderChangeDao.save(change);
				// 变更信息反馈到客户采购单
				changeOrder(change);
			}
		}
	}

	/**
	 * 变更信息反馈到客户采购单
	 * 
	 * @param change
	 */
	private void changeOrder(PurchaseOrderChange change) {
		if (change.isAgreed() || change.getUnNeedReply() == Constant.YES) { // 同意或无需确认
			purchaseOrderDao.save(convertOrder(change));
			if (!CollectionUtils.isEmpty(change.getOrderChangeItems())) {
				for (PurchaseOrderChangeItem changeItem : change.getOrderChangeItems()) {
                    if (null != changeItem.getOrderItemId()) {
                        purchaseOrderItemDao.save(convertOrderItem(changeItem));
                    }
                }
			}
			// 将数量变更为0的情况，需要修改单据的回复状态
			int notReply = purchaseOrderItemDao.getCountByStatus(change.getOrderId(), (short) Status.NOT_REPLY.value());
			PurchaseOrder order = purchaseOrderDao.findOne(change.getOrderId());
			order.setStatus((short) (notReply > 0 ? Status.NOT_REPLY.value() : Status.REPLIED.value()));
			purchaseOrderDao.save(order);
			saveUserOrders(order);
//			if (order.getStatus() == Status.REPLIED.value()) {
//			}
		}
	}

	/**
	 * 保存至用户单据表
	 *
	 * @param order 采购订单
	 * @return
	 */
	private void saveUserOrders(final PurchaseOrder order){
		ThreadTask.getInstance().execute(new Runnable() {
			@Override
			public void run() {
				/* 添加供应商的阅读记录*/
				Set<Long> userUUs = new HashSet<>();
				// 添加管理员
				List<Role> roles = roleDao.findByEnUUAndIssys(order.getVendUU(), Constant.YES);
				if (!CollectionUtils.isEmpty(roles)) {
					List<User> admins = userDao.findByRole(roles.get(0).getId());
					for (User admin : admins) {
						if (!userUUs.contains(admin.getUserUU())) {
							userUUs.add(admin.getUserUU());
						}
					}
				}
				List<Vendor> vendors = vendorDao.findByMyEnUUAndVendUU(order.getEnUU(), order.getVendUU());
				// 查找有权限的用户
				if (!CollectionUtils.isEmpty(vendors)) {
					Long vendorId = vendors.get(0).getId();
					List<Distribute> distributes = distributeDao.findByVendorId(vendorId);
					if (!CollectionUtils.isEmpty(distributes)) {
						for (Distribute distribute : distributes) {
							if (!userUUs.contains(distribute.getUserUU())) {
								userUUs.add(distribute.getUserUU());
							}
						}
					}
				}
				UserOrders userOrders;
				List<UserOrders> list = new ArrayList<>();
				for (Long userUU : userUUs){
					if(userUU == null){
						continue;
					}
					userOrders = new UserOrders(userUU, order.getVendUU(), order.getId(), "sale", "purc$orders");
					list.add(userOrders);
				}

				/* 添加采购员的阅读记录*/
				if (order.getUserUU() != null) {
					userOrders = new UserOrders(order.getUserUU(), order.getEnUU(), order.getId(), "purc", "purc$orders");
                    userOrders.setReadStatus((short) Status.READ.value());
                    list.add(userOrders);
				}
				userOrderDao.save(list);
			}
		});
	}

	/**
	 * 已同意的变更单反应到采购订单中
	 * 
	 * @param change
	 * @return
	 */
	private PurchaseOrder convertOrder(PurchaseOrderChange change) {
		PurchaseOrder order = purchaseOrderDao.findOne(change.getOrderId());
		if (order != null) {
			if (StringUtils.hasText(change.getNewPayments())) {
                order.setPayments(change.getNewPayments());
            }
			if (StringUtils.hasText(change.getNewCurrency())) {
				order.setCurrency(change.getNewCurrency());
				order.setRate(change.getNewRate());
			}
		}
		return order;
	}

	private PurchaseOrderItem convertOrderItem(PurchaseOrderChangeItem changItem) {
		PurchaseOrderItem orderItem = purchaseOrderItemDao.findOne(changItem.getOrderItemId());
		if (changItem.getNewDelivery() != null) {
            orderItem.setDelivery(changItem.getNewDelivery());
        }
		if (changItem.getNewPrice() != null) {
            orderItem.setPrice(changItem.getNewPrice());
        }
		if (changItem.getNewQty() != null) {
            orderItem.setQty(changItem.getNewQty());
        }
		if (changItem.getNewTaxrate() != null) {
            orderItem.setTaxrate(changItem.getNewTaxrate());
        }
		if (changItem.getNewProduct() != null) {
			orderItem.setProductId(changItem.getNewProduct().getId());
		}
		if (changItem.getNewQty() != null) {
			if (changItem.getNewQty() == 0) {
				orderItem.setReplyQty((double) 0);
				orderItem.setReplyRemark("需求数量变更为0，无需回复");
			}
		}

		return orderItem;
	}

	@Override
	public List<PurchaseOrderChange> findNotUploadOrderChange() {
		return purchaseOrderChangeDao.findByVendUUAndSendStatus(SystemSession.getUser().getEnterprise().getUu(),
				(short) Status.NOT_UPLOAD.value());
	}

	@Override
	public List<PurchaseOrderChange> findNotUploadOrderChangeB2b() {
		return purchaseOrderChangeDao.findByVendUUAndSendStatusAndErpId(SystemSession.getUser().getEnterprise().getUu(),
				(short) Status.NOT_UPLOAD.value());
	}

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

	@Override
	public void reply(List<SaleDownChangeReply> replies) {
		for (SaleDownChangeReply reply : replies) {
			PurchaseOrderChange orderChange = purchaseOrderChangeDao.findOne(reply.getB2b_pc_id());
			if (orderChange != null) {
				orderChange.setAgreed(reply.getSc_agreed());
				orderChange.setReplyRemark(reply.getSc_replyremark());
				orderChange.setReplySendStatus((short) Status.DOWNLOADED.value());
				reply(orderChange, false);
			}
			//更改采购单
			if (reply.getSc_agreed() == Constant.YES) {
				PurchaseOrder purchaseOrder = convertOrder(orderChange);
				if (!StringUtils.isEmpty(purchaseOrder)) {
					purchaseOrderDao.save(purchaseOrder);
					Set<PurchaseOrderChangeItem> changeItems = orderChange.getOrderChangeItems();
					Iterator<PurchaseOrderChangeItem> itemIterator = changeItems.iterator();
					while (itemIterator.hasNext()) {
						PurchaseOrderItem purchaseOrderItem = convertOrderItem(itemIterator.next());
						purchaseOrderItemDao.save(purchaseOrderItem);
					}
				}
			}
		}
	}

	@Override
	public void saveb2b(List<SaleDownChangeReply> replies ) {
		for (SaleDownChangeReply reply : replies) {
			PurchaseOrderChange orderChange = purchaseOrderChangeDao.findOne(reply.getB2b_pc_id());
			if (orderChange != null) {
				orderChange.setAgreed(reply.getSc_agreed());
				orderChange.setReplyRemark(reply.getSc_replyremark());
				orderChange.setReplySendStatus((short) Status.DOWNLOADED.value());
				reply(orderChange,false);
			}
			//更改采购单
			if (reply.getSc_agreed() == Constant.YES) {
				PurchaseOrder purchaseOrder = convertOrder(orderChange);
				purchaseOrderDao.save(purchaseOrder);
				Set<PurchaseOrderChangeItem> changeItems = orderChange.getOrderChangeItems();
				Iterator<PurchaseOrderChangeItem> itemIterator = changeItems.iterator();
				while (itemIterator.hasNext()) {
					PurchaseOrderItem purchaseOrderItem = convertOrderItem(itemIterator.next());
					purchaseOrderItemDao.save(purchaseOrderItem);
				}
			}
		}
	}

	@Override
	public List<PurchaseOrderChange> findNotSendReply() {
		return purchaseOrderChangeDao.findByVendUUAndStatusAndReplySendStatus(
				SystemSession.getUser().getEnterprise().getUu(), (short) Status.REPLIED.value(),
				(short) Status.NOT_UPLOAD.value());
	}

	@Override
	public void onSaleDownChangeReplySuccess(String[] idArray) {
		for (String id : idArray) {
			PurchaseOrderChange change = purchaseOrderChangeDao.findOne(Long.parseLong(id));
			if (change != null) {
				change.setReplySendStatus((short) Status.DOWNLOADED.value());
				purchaseOrderChangeDao.save(change);
			}
		}
	}

	@Override
	public Page<PurchaseOrderChange> findAllByPageInfo(final PageInfo pageInfo, final String keyword,
			final SearchFilter filter) {
		if (filter != null) {
			if (!CollectionUtils.isEmpty(filter.getDistribute()))
				pageInfo.expression(PredicateUtils.in("enUU", filter.getDistribute(), 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 (StringUtils.hasText(keyword)) {
			List<Object> lists = new ArrayList<>();
			PageParams pageParams = new PageParams();
			ModelMap map = new ModelMap();
			map.put("pc_venduu", SystemSession.getUser().getEnterprise().getUu());
			pageParams.setFilters(map);
			for (PurchaseOrderChange list : searchService.searchPurchaseOrderChangeIds(keyword, pageParams)
					.getContent()) {
				lists.add(list.getId());
			}
			pageInfo.expression(PredicateUtils.in("id", lists, false));
		}

		return purchaseOrderChangeDao.findAll(new Specification<PurchaseOrderChange>() {
			public Predicate toPredicate(Root<PurchaseOrderChange> root, CriteriaQuery<?> query,
					CriteriaBuilder builder) {
				return query.where(pageInfo.getPredicates(root, query, builder)).getRestriction();
			}
		}, pageInfo);
	}

	@Override
	public PurchaseOrderChange reply(PurchaseOrderChange change) {
		return reply(change, true);
	}

	/**
	 * @param change
	 * @param isB2b
	 *            是否在平台操作
	 */
	private PurchaseOrderChange reply(PurchaseOrderChange change, boolean isB2b) {
		PurchaseOrderChange orderChange = purchaseOrderChangeDao.findOne(change.getId());
		orderChange.setStatus((short) Status.REPLIED.value());
		orderChange.setAgreed(change.getAgreed());
		orderChange.setReplyRemark(change.getReplyRemark());
		orderChange.setReplySendStatus(change.getReplySendStatus());
		if (isB2b)
			orderChange.setReplySendStatus((short) Status.NOT_UPLOAD.value());
		orderChange = purchaseOrderChangeDao.save(orderChange);
		// 将回复信息推送给采购企业采购员（或管理员）
		if (orderChange.getUserUU() != null) {
			UserBaseInfo user = userBaseInfoDao.findOne(orderChange.getUserUU());
			Enterprise vendor = enterpriseDao.findOne(orderChange.getVendUU());
			if (vendor != null) {
				XingePusher.pushByUser(user, (orderChange.isAgreed() ? "同意了" : "不同意") + "您的采购变更",
						"供应商:" + vendor.getEnName(), "", "");
			}
		}
		return orderChange;
	}

	@Override
	public PurchaseOrderChange findById(Long id) {
		return purchaseOrderChangeDao.findOne(id);
	}

}