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.InquiryMould;
import com.uas.platform.b2b.erp.model.QuotationDown;
import com.uas.platform.b2b.event.PurchaseInquiryMouldInvalidReleaseEvent;
import com.uas.platform.b2b.event.PurchaseInquiryMouldSaveReleaseEvent;
import com.uas.platform.b2b.model.*;
import com.uas.platform.b2b.search.SearchService;
import com.uas.platform.b2b.service.PurchaseInquiryMouldService;
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.IllegalStatusException;
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 com.uas.search.b2b.model.SPage;
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.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.util.*;

@Service
public class PurchaseInquiryMouldServiceImpl implements PurchaseInquiryMouldService {

	@Autowired
	private PurchaseInquiryMouldDao purchaseInquiryMouldDao;

	@Autowired
	private PurchaseInquiryMouldInfoDao purchaseInquiryMouldInfoDao;

	@Autowired
	private PurchaseInquiryMouldItemDao purchaseInquiryMouldItemDao;
	
	@Autowired
	private PurchaseInquiryMouldDetailDao purchaseInquiryMouldDetailDao;

	@Autowired
	private AttachDao attachDao;

	@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 PurchaseInquiryMould save(PurchaseInquiryMould inquiryMould) {
		return purchaseInquiryMouldDao.save(inquiryMould);
	}

	@Override
	public List<PurchaseInquiryMould> findNotUploadReply() {
		List<PurchaseInquiryMould> moulds = purchaseInquiryMouldDao.findByEnuuAndBackStatus(
				SystemSession.getUser().getEnterprise().getUu(), (short) Status.NOT_UPLOAD.value());
		List<PurchaseInquiryMould> purchaseInquiryMoulds = new ArrayList<PurchaseInquiryMould>();
		for (PurchaseInquiryMould mould : moulds) {
			if (mould.getAdoptStatus() == null && mould.getStatus() == Status.REPLIED.value()) {
				purchaseInquiryMoulds.add(mould);
			}
		}
		return purchaseInquiryMoulds;
	}

	@Override
	public void onReplyUploadSuccess(String[] idArray) {
		if (idArray != null && idArray.length > 1) {
			List<PurchaseInquiryMould> moulds = new ArrayList<>();
			for (String id : idArray) {
				PurchaseInquiryMould mould = purchaseInquiryMouldDao.findOne(Long.parseLong(id));
				if (mould != null) {
					mould.setBackStatus((short) Status.DOWNLOADED.value());
					moulds.add(mould);
				}
			}
			purchaseInquiryMouldDao.save(moulds);
		}
	}

	@Override
	public void reply(List<QuotationDown> downs) {
		for (QuotationDown down : downs) {
			PurchaseInquiryMould mould = purchaseInquiryMouldDao.findOne(down.getB2b_id_id());
			Set<PurchaseInquiryMouldItem> items = mould.getInquiryMouldItems();
			if (items != null && mould != null) {
				mould.setStatus((short) Status.REPLIED.value());
				mould.setBackStatus((short) Status.NOT_UPLOAD.value());
				mould.setReplySendStatus((short) Status.DOWNLOADED.value());
				for (PurchaseInquiryMouldItem item : items) {
					item.setRemark(String.valueOf(System.currentTimeMillis()));
					Long userUU = mould.getVendUserUU();
					if (userUU == null) {
						userUU = mould.getRecorderuu();
					}
					if (userUU != null) {
						// 消息推送
						if (userUU != null && userUU != 0) {
							UserBaseInfo user = userBaseInfoDao.findOne(userUU);
							XingePusher.pushByUser(user, "询价单回复",
									"单号:" + mould.getCode() + ",第" + item.getDetno() + "行", "", "");
						}
					}
					Set<PurchaseInquiryMouldDetail> details = item.getInquiryMouldDetails();
					if (details != null) {
						for (PurchaseInquiryMouldDetail detail : details) {
							detail.setProdCode(down.getQu_prodcode());// 供应商物料编号
						}
					}
				}

				purchaseInquiryMouldDao.save(mould);
			}
		}
	}

	@SuppressWarnings("deprecation")
	@Override
	public void saveAttach(List<Attach> attachs) {
		List<Attach> validAttachs = new ArrayList<Attach>();
		if (!CollectionUtils.isEmpty(attachs)) {
			long enUU = SystemSession.getUser().getEnterprise().getUu();
			for (Attach attach : attachs) {
				List<PurchaseInquiryMould> inquiries = purchaseInquiryMouldDao.findByEnuuAndSourceId(enUU,
						Long.parseLong(attach.getSourceId()));
				if (!CollectionUtils.isEmpty(inquiries)) {
					PurchaseInquiryMould inquiryMould = inquiries.get(0);
					attach.setRelativeTable("purc$inquirymould");
					attach.setRelativeKey(inquiryMould.getId());
					validAttachs.add(attach);
				}
			}
		}
		if (!CollectionUtils.isEmpty(validAttachs)) {
			attachDao.save(validAttachs);
		}
	}

	@Override
	public PurchaseInquiryMouldInfo findById(Long id) {
		return purchaseInquiryMouldInfoDao.findOne(id);
	}

	@Override
	public void onReplyDecide(List<PurchaseInquiryMould> inquiryMoulds) {
		purchaseInquiryMouldDao.save(inquiryMoulds);
		// 将客户处理报价结果推送通知供应商联系人UU号
		for (PurchaseInquiryMould mould : inquiryMoulds) {
			String tittle = (mould.getAdoptStatus() == Constant.YES) ? "客户同意了您的报价" : "客户不同意您的报价";
			if (mould.getVendUserUU() != null) {
				UserBaseInfo user = userBaseInfoDao.findOne(mould.getVendUserUU());
				Set<PurchaseInquiryMouldItem> items = mould.getInquiryMouldItems();
				for (PurchaseInquiryMouldItem item : items) {
					Set<PurchaseInquiryMouldDetail> details = item.getInquiryMouldDetails();
					for (PurchaseInquiryMouldDetail detail : details) {
						XingePusher.pushByUser(user, tittle,
								"物料:" + detail.getProdTitle() + ",客户:" + mould.getEnterprise().getEnName(), "", "");
					}
				}
			}
		}
	}

	@Override
	public void onReplyDownSuccess(String[] idArray) {
		for (String id : idArray) {
			PurchaseInquiryMould mould = purchaseInquiryMouldDao.findOne(Long.parseLong(id));
			if (mould != null) {
				mould.setReplySendStatus((short) Status.DOWNLOADED.value());
				purchaseInquiryMouldDao.save(mould);
			}
		}
	}

	@Override
	public PurchaseInquiryMouldItem save(PurchaseInquiryMouldItem inquiryMouldItem) {
		return purchaseInquiryMouldItemDao.save(inquiryMouldItem);
	}

	@Override
	public PurchaseInquiryMould reply(PurchaseInquiryMould inquiryMould) {
		PurchaseInquiryMould mould = purchaseInquiryMouldDao.findOne(inquiryMould.getId());
		if (!mould.isReplyable()) {
            throw new IllegalStatusException("该询价单已经报价，不允许再次报价");
        }
		if ((mould.getCheck() != null && mould.getCheck() == Constant.YES) || (mould.getAdoptStatus() != null)) {
            throw new IllegalOperatorException("客户正在审核您的上次报价，当前不允许再次报价");
        }
		mould.setStatus((short) Status.REPLIED.value());
		mould.setSendStatus((short) Status.NOT_UPLOAD.value());
		mould.setBackStatus((short) Status.NOT_UPLOAD.value());
		mould.setReplySendStatus((short) Status.NOT_UPLOAD.value());
		mould.setReplyDate(new Date());
		mould.setAttachs(inquiryMould.getAttachs());
		mould.setSellAttachs(inquiryMould.getSellAttachs());
		Long userUU = mould.getVendUserUU();
		if (userUU == null) {
			userUU = mould.getRecorderuu();
		}
		if (userUU != null && userUU != 0) {
			// 消息推送
			XingePusher.pushByUserUU(userUU, "模具询价单回复", "单号:" + mould.getCode(), "", "");
		}
		mould = purchaseInquiryMouldDao.save(mould);
		Set<PurchaseInquiryMouldItem> items = inquiryMould.getInquiryMouldItems();
		for (PurchaseInquiryMouldItem item : items) {
			PurchaseInquiryMouldItem item2 = purchaseInquiryMouldItemDao.findOne(item.getId());
			item2.setPrice(item.getPrice());
			item2.setReply(item.getPrice());
			purchaseInquiryMouldItemDao.save(item2);
			Set<PurchaseInquiryMouldDetail> details = item.getInquiryMouldDetails();
			for (PurchaseInquiryMouldDetail detail : details) {
				PurchaseInquiryMouldDetail detail2 = purchaseInquiryMouldDetailDao.findOne(detail.getId());
				detail2.setPrice(detail.getPrice());
				detail2.setReply(detail.getPrice());
				purchaseInquiryMouldDetailDao.save(detail2);
			}
		}

		return mould;
	}

	@Override
	public void check(Long[] ids) {
		List<PurchaseInquiryMould> moulds = new ArrayList<>();
		for (Long id : ids) {
			PurchaseInquiryMould mould = purchaseInquiryMouldDao.findOne(id);
			mould.setCheck(Constant.YES);
			moulds.add(mould);
		}
		purchaseInquiryMouldDao.save(moulds);
	}

	@Override
	public void reCheck(Long[] ids) {
		List<PurchaseInquiryMould> moulds = new ArrayList<>();
		for (Long id : ids) {
			PurchaseInquiryMould mould = purchaseInquiryMouldDao.findOne(id);
			mould.setCheck(Constant.NO);
			moulds.add(mould);
		}
		purchaseInquiryMouldDao.save(moulds);
	}

	@Override
	public SPage<PurchaseInquiryMouldInfo> findAllByPageInfo(final PageInfo pageInfo, final String keyword,
														 final SearchFilter filter) {
		SPage<PurchaseInquiryMouldInfo> spage = new SPage<>();
		Page<PurchaseInquiryMouldInfo> purchaseInquiryMoulds = purchaseInquiryMouldInfoDao.findAll(new Specification<PurchaseInquiryMouldInfo>() {
			@Override
			public Predicate toPredicate(Root<PurchaseInquiryMouldInfo> root, CriteriaQuery<?> query,
					CriteriaBuilder builder) {
				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("im_venduu", SystemSession.getUser().getEnterprise().getUu());
					pageParams.setFilters(map);
					for (PurchaseInquiryMouldInfo list : searchService.searchPurcInquiryMouldIds(keyword, pageParams)
							.getContent()) {
						lists.add(list.getId());
					}
					pageInfo.expression(PredicateUtils.in("id", lists, false));
				}
				return query.where(pageInfo.getPredicates(root, query, builder)).getRestriction();
			}
		}, pageInfo);
		spage.setContent(purchaseInquiryMoulds.getContent());
		spage.setPage(purchaseInquiryMoulds.getNumber());
		spage.setTotalPage(purchaseInquiryMoulds.getTotalPages());
		spage.setTotalElement(purchaseInquiryMoulds.getTotalElements());
		spage.setSize(purchaseInquiryMoulds.getSize());
		return spage;
	}

	@Override
	public void save(List<PurchaseInquiryMould> convertInquiryMould) {
		purchaseInquiryMouldDao.save(convertInquiryMould);
		saveUserOrders(convertInquiryMould);
		// 消息事件
		ContextUtils.publishEvent(new PurchaseInquiryMouldSaveReleaseEvent(convertInquiryMould));
	}

	private void saveUserOrders(final List<PurchaseInquiryMould> convertInquiryMould) {

		ThreadTask.getInstance().execute(new Runnable() {
			@Override
			public void run() {
            	/* 添加供应商的阅读记录*/
				for(PurchaseInquiryMould mould : convertInquiryMould) {
					Set<Long> userUUs = new HashSet<>();
					// 添加管理员
					List<Role> roles = roleDao.findByEnUUAndIssys(mould.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(mould.getEnuu(), mould.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, mould.getVenduu(), mould.getId(), "sale", "v$purc$inquirymould");
						list.add(userOrders);
					}

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

	}

	@Override
	public void onInvalid(List<InquiryMould> inquiryMoulds) {
		List<PurchaseInquiryMould> moulds = new ArrayList<>();
		for (InquiryMould inquiryMould : inquiryMoulds) {
			// 因为存在还未报价就作废单据的情况，所以不能用b2b_im_id，而用in_id来查找单据
			if (null != inquiryMould.getIn_id()) {
				PurchaseInquiryMould purchaseInquiryMould = purchaseInquiryMouldDao
						.findByEnuuAndErpSourceId(SystemSession.getUser().getEnterprise().getUu(),inquiryMould.getIn_id());
				if (null != purchaseInquiryMould) {
					// 已作废有效状态设置为0 表示无效
					purchaseInquiryMould.setValid(Constant.NO);
					moulds.add(purchaseInquiryMould);
				}
			}
		}
		purchaseInquiryMouldDao.save(moulds);
		// 作废产生消息
		ContextUtils.publishEvent(new PurchaseInquiryMouldInvalidReleaseEvent(moulds));
	}

}