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.event.MakeOrderChangeSaveReleaseEvent;
import com.uas.platform.b2b.model.*;
import com.uas.platform.b2b.service.MakeOrderChangeService;
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 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.util.CollectionUtils;
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 java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class MakeOrderChangeServiceImpl implements MakeOrderChangeService {

	@Autowired
	private MakeOrderChangeItemDao makeOrderChangeItemDao;

	@Autowired
	private MakeOrderDao makeOrderDao;

	@Autowired
	private UserBaseInfoDao userBaseInfoDao;

	@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<MakeOrderChangeItem> changeItems) {
		List<MakeOrderChangeItem> newItems = makeOrderChangeItemDao.save(changeItems);
		saveUserOrders(newItems);
		// 委外变更单无需供应商确认，直接修改委外加工单的数据
		for (MakeOrderChangeItem item : newItems) {
			changeMakeOrder(item, true);
		}
		// 消息
		ContextUtils.publishEvent(new MakeOrderChangeSaveReleaseEvent(newItems));
	}

	private void saveUserOrders(final List<MakeOrderChangeItem> newItems) {

		ThreadTask.getInstance().execute(new Runnable() {
			@Override
			public void run() {
				/* 添加供应商的阅读记录*/
				for(MakeOrderChangeItem item : newItems) {
					Set<Long> userUUs = new HashSet<>();
					// 添加管理员
					List<Role> roles = roleDao.findByEnUUAndIssys(item.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(item.getOrderChange().getEnUU(), item.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, item.getVendUU(), item.getId(), "sale", "make$changeitems");
						list.add(userOrders);
					}

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

	}

	@Override
	public Page<MakeOrderChangeItem> findAllByPageInfo(final PageInfo pageInfo, String keyword) {
		return makeOrderChangeItemDao.findAll(new Specification<MakeOrderChangeItem>() {
			@Override
            public Predicate toPredicate(Root<MakeOrderChangeItem> root, CriteriaQuery<?> query,
                                         CriteriaBuilder builder) {
				return query.where(pageInfo.getPredicates(root, query, builder)).getRestriction();
			}
		}, pageInfo);
	}

	@Override
	public MakeOrderChangeItem reply(MakeOrderChangeItem item) {
		item.setReplyDate(new Date());// 回复时间为服务器当前时间
		return reply(item, true);
	}

	/**
	 * @param item
	 * @param isB2b
	 *            是否在平台操作
	 */
	private MakeOrderChangeItem reply(MakeOrderChangeItem item, boolean isB2b) {
		MakeOrderChangeItem changeItem = makeOrderChangeItemDao.findOne(item.getId());
		changeItem.setStatus((short) Status.REPLIED.value());
		changeItem.setAgreed(item.getAgreed());
		changeItem.setReplyRemark(item.getReplyRemark());
		changeItem.setReplySendStatus((short) Status.NOT_UPLOAD.value());
		if (isB2b) {
			changeItem.setReplyBackStatus((short) Status.NOT_UPLOAD.value());
		} else {
			changeItem.setReplyBackStatus((short) Status.DOWNLOADED.value());
		}
		changeItem = makeOrderChangeItemDao.save(changeItem);
		// 将回复信息推送给采购企业采购员（或管理员）
		if (changeItem.getOrderChange().getUserUU() != null) {
			Long userUU = changeItem.getOrderChange().getUserUU();
			UserBaseInfo user = userBaseInfoDao.findOne(userUU);
			XingePusher.pushByUser(user, (changeItem.isAgreed() ? "同意了" : "不同意") + "您的委外变更",
					"供应商:" + changeItem.getOrderChange().getEnterprise().getEnName(), "", "");
		}
		return changeItem;
	}

	@Override
	public List<MakeOrderChangeItem> findNotUploadReply() {
		Long enUU = SystemSession.getUser().getEnterprise().getUu();
		return makeOrderChangeItemDao.findByOrderChangeEnUUAndStatusAndReplySendStatus(enUU,
				(short) Status.REPLIED.value(), (short) Status.NOT_UPLOAD.value());
	}

	@Override
	public void onReplyUploadSuccess(String[] idArray) {
		for (String id : idArray) {
			MakeOrderChangeItem item = makeOrderChangeItemDao.findOne(Long.parseLong(id));
			item.setReplySendStatus((short) Status.DOWNLOADED.value());
			makeOrderChangeItemDao.save(item);
			// 变更委外加工单，修改加工单
			changeMakeOrder(item, false);
		}
	}

	/**
	 * 将委外变更信息反映在委外加工单上
	 * 
	 * @param item
	 * @param noNeedAgree
	 *            不需要确认
	 */
	private void changeMakeOrder(MakeOrderChangeItem item, boolean noNeedAgree) {
		if (noNeedAgree || item.isAgreed()) {
			MakeOrder order = makeOrderDao.findOne(item.getOrderId());
			if (order != null) {
				if (item.getNewCommence() != null) {
					order.setCommence(item.getNewCommence());
				}
				if (item.getNewComplete() != null) {
					order.setComplete(item.getNewComplete());
				}
				if (item.getNewPrice() != null) {
					order.setPrice(item.getNewPrice());
				}
				if (item.getNewQty() != null) {
					order.setQty(item.getNewQty());
				}
				if (item.getNewtaxrate() != null) {
					order.setTaxrate(item.getNewtaxrate());
				}
				String remark;
				if (StringUtils.isEmpty(order.getRemark())) {
					remark = "";
				} else {
					remark = order.getRemark() + ";";
				}
				DateFormat format = new SimpleDateFormat("MM-dd HH:mm");
				order.setRemark(
						remark + format.format(new Date()) + " 经委外变更单：" + item.getOrderChange().getCode() + "变更数据;");
				makeOrderDao.save(order);
				saveUserOrders(order);
			}
		}
	}

	private void saveUserOrders(final MakeOrder 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", "make$orders");
					list.add(userOrders);
				}

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

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

	@Override
	public void onUploadChangeSuccess(String[] idArray) {
		for (String id : idArray) {
			MakeOrderChangeItem item = makeOrderChangeItemDao.findOne(Long.parseLong(id));
			if (item != null) {
				item.setSendStatus((short) Status.DOWNLOADED.value());
				makeOrderChangeItemDao.save(item);
			}
		}
	}

	@Override
	public Page<MakeOrderChangeItem> findByPageInfo(final PageInfo pageInfo, SearchFilter filter) {
		if (filter != null) {
			if (filter.getFromDate() != null) {
                pageInfo.expression(PredicateUtils.gte("orderChange.date", new Date(filter.getFromDate()), false));
            }
			if (filter.getEndDate() != null) {
                pageInfo.expression(PredicateUtils.lte("orderChange.date", new Date(filter.getEndDate()), false));
            }
			if (!CollectionUtils.isEmpty(filter.getDistribute())) {
                pageInfo.expression(PredicateUtils.in("orderChange.enUU", filter.getDistribute(), false));
            }
		}
		Page<MakeOrderChangeItem> pageOrders = makeOrderChangeItemDao.findAll(new Specification<MakeOrderChangeItem>() {
			@Override
            public Predicate toPredicate(Root<MakeOrderChangeItem> root, CriteriaQuery<?> query,
                                         CriteriaBuilder builder) {
				return query.where(pageInfo.getPredicates(root, query, builder)).getRestriction();
			}
		}, pageInfo);
		return pageOrders;
	}

	@Override
	public MakeOrderChangeItem findById(Long id) {
		return makeOrderChangeItemDao.findOne(id);
	}

}