package com.iformall.service.invest.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.afterturn.easypoi.handler.impl.ExcelDataHandlerDefaultImpl;
import cn.afterturn.easypoi.handler.inter.IExcelDataHandler;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.iformall.common.ErrorCode;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.dto.InvestDemandDto;
import com.iformall.domain.dto.InvestTaskDto;
import com.iformall.domain.po.*;
import com.iformall.domain.po.invest.*;
import com.iformall.domain.vo.WxShopVo;
import com.iformall.domain.vo.invest.*;
import com.iformall.enums.*;
import com.iformall.exception.MallinkException;
import com.iformall.service.*;
import com.iformall.service.invest.*;
import com.iformall.utils.Constant;
import com.iformall.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

@Slf4j
@Service
public class InvestBizServiceImpl implements InvestBizService {

	@Autowired
	private InvestDemandService demandService;
	@Autowired
	private InvestTaskService taskService;
	@Autowired
	private InvestFollowRecordService followRecordService;
	@Autowired
	private InvestOperateRecordService operateRecordService;
	@Autowired
	private InvestRemindService remindService;
	@Autowired
	private InvestMessageService messageService;
	@Autowired
	private WxShopService shopService;
	@Autowired
	private InvestCustomerService customerService;
	@Autowired
	private WxBrandService brandService;
	@Autowired
	private MallUserInfoService userInfoService;
	@Autowired
	private WxBusinessService businessService;
	@Autowired
	private WxRentContractService rentContractService;
	@Autowired
	private ExcelService excelService;
	@Autowired
	StringRedisTemplate stringRedisTemplate;
	@Autowired
	private String fmUploadDir;

	@Override
	public InvestPageResult<InvestDemandVo> queryPageDemand(InvestDemandQuery params) {
		InvestPageResult<InvestDemandVo> investPage = new InvestPageResult<>();
		InvestDemandDto queryParams = convert(params, this::doConvertDemand);
		InvestCustomerEntity customerParams = null;
		InvestDemandEntity demandParams = null;
		if (Objects.nonNull(queryParams)) {
			customerParams = queryParams.getCustomer();
			demandParams = queryParams.getDemand();
		}
		List<InvestDemandEntity> demandList = demandService.list(new LambdaQueryWrapper<>(demandParams));
		LambdaQueryWrapper<InvestCustomerEntity> queryWrapperCustomer = new LambdaQueryWrapper<>(customerParams);
		queryWrapperCustomer.like(StringUtils.isNotBlank(params.getPhone()), InvestCustomerEntity::getPhone, params.getPhone());

		if (Objects.isNull(InvestUserContext.getDataUser())) {
			if (CollectionUtils.isEmpty(demandList) && Objects.nonNull(params.getDemandOwner())) {
				return investPage;
			} else {
				queryWrapperCustomer.in(CollectionUtils.isNotEmpty(demandList), InvestCustomerEntity::getId, getIds(demandList, InvestDemandEntity::getCustomerId));
			}
		} else {
			if (CollectionUtils.isEmpty(demandList)) {
				return investPage;
			} else {
				queryWrapperCustomer.in(CollectionUtils.isNotEmpty(demandList), InvestCustomerEntity::getId, getIds(demandList, InvestDemandEntity::getCustomerId));
			}
		}
		if(CollectionUtils.isNotEmpty(params.getCustomerType())) {
			queryWrapperCustomer.in(InvestCustomerEntity::getType,params.getCustomerType()) ;
		}

		queryWrapperCustomer.orderByDesc(InvestCustomerEntity::getCreateDate);
		InvestPageResult<InvestCustomerEntity> customers = customerService.queryPage(buildPageQuery(params, null), queryWrapperCustomer);
		List<InvestDemandVo> resultList = getTargeInfoList(demandList, customers.getRecords());
		BeanUtils.copyProperties(customers, investPage);
		investPage.setRecords(resultList);
		if (CollectionUtils.isEmpty(customers.getRecords())) {
			return investPage;
		}

		return investPage;
	}

	@Override
	public void exportCustomer(InvestDemandQuery params, HttpServletResponse response) {
		InvestDemandDto queryParams = convert(params, this::doConvertDemand);
		InvestCustomerEntity customerParams = null;
		InvestDemandEntity demandParams = null;
		if (Objects.nonNull(queryParams)) {
			customerParams = queryParams.getCustomer();
			demandParams = queryParams.getDemand();
		}
		List<InvestDemandEntity> demandList = demandService.list(new LambdaQueryWrapper<>(demandParams));
		LambdaQueryWrapper<InvestCustomerEntity> queryWrapperCustomer = new LambdaQueryWrapper<>(customerParams);
		if (Objects.isNull(InvestUserContext.getDataUser())) {
			queryWrapperCustomer.in(ObjectUtils.allNotNull(params.getDemandOwner()),
					InvestCustomerEntity::getId, getIds(demandList, InvestDemandEntity::getCustomerId));
		} else {
			if (CollectionUtils.isNotEmpty(demandList)) {
				return;
			} else {
				queryWrapperCustomer.in(InvestCustomerEntity::getId, getIds(demandList, InvestDemandEntity::getCustomerId));
			}
		}
		queryWrapperCustomer.orderByDesc(InvestCustomerEntity::getCreateDate);
		Collection<InvestCustomerEntity> customers = customerService.list(queryWrapperCustomer);
		if (CollectionUtils.isNotEmpty(customers)) {
			List<InvestCustomerVo> resultList = getCustomerVOList(demandList, customers);
			excelService.exportExcel(resultList, null, "客户信息", InvestCustomerVo.class, "客户信息.xlsx", response, false);
		}
	}

	@Override
	public void exportCustomerTemplate(HttpServletResponse response) {
		List<InvestCustomerVo> resultList = new ArrayList<>();
		InvestCustomerVo item = new InvestCustomerVo();
		item.setBusiness("超市");
		item.setRentArea(100);
		item.setShopNumber("A10092");
		item.setBrandName("肯德基");
		item.setName("张三");
		item.setPhone("13588888888");
		item.setOpeningTime("2019-01-01");
		resultList.add(item);
		excelService.exportExcel(resultList, null, "客户信息模板", InvestCustomerVo.class, "客户信息模板.xlsx", response, true);
	}

	@Override
	public void importCustomer(MultipartFile mFile) {
		if (mFile.isEmpty()) {
			throw new MallinkException(Result.ERROR, "上传文件不能为空");
		}

		String importKey = Constant.importInvestCustomerPrev + InvestUserContext.getUserId();
		final String tenantId = InvestUserContext.getUser().getTenantId();

		//查询当前用户得到的值是否为空，为空继续，不为空，返回模板正在导入
		Boolean allCount = stringRedisTemplate.opsForHash().hasKey(importKey, "allCount");
		if (allCount) {
			throw new MallinkException(Result.SUCCESS, "模板正在导入");
		}
		setRedisValueIfAbsent(importKey);

		String fpath = fmUploadDir;
		File targetFile = new File(fpath);
		if (!targetFile.exists()) {
			targetFile.mkdirs();
		}
		String fileName = "invest_1.xlsx";
		int dot = mFile.getOriginalFilename().lastIndexOf('.');
		fileName = fileName + mFile.getOriginalFilename().substring(dot);

		File lFile = new File(fpath + File.separator + fileName);

		FileOutputStream fos = null;
		BufferedInputStream fs = null;
		try {
			fos = new FileOutputStream(lFile);
			if (mFile.getInputStream() instanceof ByteArrayInputStream) {
				fs = new BufferedInputStream(mFile.getInputStream());
			} else {
				fs = (BufferedInputStream) mFile.getInputStream();
			}
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = fs.read(buffer)) != -1) {
				fos.write(buffer, 0, len);
			}
			fos.close();
			fs.close();
		} catch (Exception e) {
			setRedisValueIfError(importKey, "1", "1", e);
			throw new MallinkException(ErrorCode.MEM_IMPORT_ERR.getCode(), "模板上传失败");
		} finally {
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					setRedisValueIfError(importKey, "1", "1", e);
					throw new MallinkException(ErrorCode.MEM_IMPORT_ERR.getCode(), "模板上传失败");
				}
			}
			if (fs != null) {
				try {
					fs.close();
				} catch (IOException e) {
					setRedisValueIfError(importKey, "1", "1", e);
					throw new MallinkException(ErrorCode.MEM_IMPORT_ERR.getCode(), "模板上传失败");
				}
			}
		}

		doImport(lFile, importKey);
	}

	@Override
	public Map queryCustomerImportCount() {
		String importKey = Constant.importInvestCustomerPrev + InvestUserContext.getUserId();
		Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries(importKey);
		log.info(JSONArray.toJSONString(entries) + ">>>>>>>>>>>>>>>>>>>>>1");
		if (entries.size() < 4) {
			entries.clear();
			return entries;
		}
		String allCount = entries.get("allCount").toString();
		String allSuccessCount = entries.get("allSuccessCount").toString();
		String processCount = entries.get("processCount").toString();
		String failCount = entries.get("failCount").toString();

		if (StringUtils.isNotBlank(failCount) && allCount.equals(failCount)) {//stringRedisTemplate.expire(userId,1,TimeUnit.SECONDS);
			log.info(JSONArray.toJSONString(entries) + ">>>>>>>>>>>>>>>>>>>>>2");
			//完全失败
			stringRedisTemplate.opsForHash().delete(importKey, "allCount");
			stringRedisTemplate.opsForHash().delete(importKey, "allSuccessCount");
			stringRedisTemplate.opsForHash().delete(importKey, "processCount");
			stringRedisTemplate.opsForHash().delete(importKey, "failCount");
			throw new MallinkException(ErrorCode.MEM_IMPORT_ERR);
		}
		//导入完成
		if (StringUtils.isNotBlank(allSuccessCount) && allSuccessCount.equals(processCount)) {
			stringRedisTemplate.opsForHash().delete(importKey, "allCount");
			stringRedisTemplate.opsForHash().delete(importKey, "allSuccessCount");
			stringRedisTemplate.opsForHash().delete(importKey, "processCount");
			stringRedisTemplate.opsForHash().delete(importKey, "failCount");
			return entries;
		}
		return entries;
	}

	private void doImport(File file, String importKey) {
		ImportParams params = new ImportParams();
		// 需要验证
		params.setImportFields(new String[]{"品牌*", "品牌负责人*", "负责人电话*", "经营业态*", "意向铺位*", "意向租凭面积", "预计开业时间"});
		IExcelDataHandler<InvestCustomerVo> handler = new ExcelDataHandlerDefaultImpl<InvestCustomerVo>() {
			@Override
			public Object importHandler(InvestCustomerVo obj, String name, Object value) {
				if (value == null) {
					value = "";
				}
				System.out.println(name + " + " + value.toString());
				return super.importHandler(obj, name, value);
			}
		};
		handler.setNeedHandlerFields(new String[]{"品牌*", "品牌负责人*", "负责人电话*", "经营业态*", "意向铺位*"});
		params.setNeedVerify(true);

		ExcelImportResult<InvestCustomerVo> datalist = null;

		try {
			datalist = ExcelImportUtil.importExcelMore(file, InvestCustomerVo.class, params);
		} catch (Exception e) {
			setRedisValue(importKey, "1", "0", "0", "1", true);
			log.error(e.getMessage());
			// 删除缓存文件
			file.delete();
			throw new MallinkException(ErrorCode.MEM_IMPORT_ERR.getCode(), "导入模板失败: 模板数据解析失败");
		}
		// 删除缓存文件
		file.delete();

		if (datalist == null) {
			log.error("导入模板失败: 模板数据解析失败");
			setRedisValue(importKey, "1", "0", "0", "1", true);
			throw new MallinkException(ErrorCode.MEM_IMPORT_ERR.getCode(), "导入模板失败: 模板数据解析失败");
		}

		List<InvestCustomerVo> successList = datalist.getList();
		List<InvestCustomerVo> failList = datalist.getFailList();

		log.info("验证通过的数量: " + successList.size());
		log.info("验证未通过的数量: " + failList.size());

		int total = successList.size() + failList.size();
		int all_success = successList.size();
		int all_fail = failList.size();

		//添加到redis里
		setRedisValue(importKey, "" + total, "" + all_success, "0", "" + all_fail, total == all_fail);
		if (CollectionUtils.isEmpty(successList)) {
			stringRedisTemplate.expire(importKey, 3, TimeUnit.SECONDS);
			return;
		}
		//品牌信息
		Map<String, WxBrand> brandMap = getBrandMap();

		//业态信息
		Map<String, WxBusiness> businesseMap = getBusinessMap();

		//商铺信息
		WxShop shopQuery = new WxShop();
		shopQuery.updateTenantInfo(InvestUserContext.getUser());
		List<WxShop> shops = shopService.listAsPage(null, 1, Integer.MAX_VALUE).getList();
		Map<String, WxShop> shopMap = getMap(shops, WxShop::getShopNumber);

		//商铺信息
		LambdaQueryWrapper<InvestCustomerEntity> customerQuery = new LambdaQueryWrapper<>();
		customerQuery.in(InvestCustomerEntity::getPhone, getIds(successList, InvestCustomerVo::getPhone));
		List<InvestCustomerEntity> customers = customerService.list(customerQuery);
		Map<String, InvestCustomerEntity> customerMap = getMap(customers, InvestCustomerEntity::getPhone);

		//商铺信息
		LambdaQueryWrapper<InvestDemandEntity> demandQuery = new LambdaQueryWrapper<>();
		Collection<Long> customerIds = getIds(customers, InvestCustomerEntity::getId);
		demandQuery.in(CollectionUtils.isNotEmpty(customerIds), InvestDemandEntity::getCustomerId, customerIds);
		List<InvestDemandEntity> demandList = demandService.list(demandQuery);
		Map<Long, InvestDemandEntity> demandMap = getMap(demandList, InvestDemandEntity::getCustomerId);

		try {
			successList.forEach(customer -> {
				if (StringUtils.isBlank(customer.getPhone())) {
					redisKeyIncrement(importKey, "processCount", "failCount");
					log.error("负责人电话为空", customer.toString());
					return;
				}
				if (StringUtils.isBlank(customer.getShopNumber())) {
					redisKeyIncrement(importKey, "processCount", "failCount");
					log.error("意向铺位为空", customer.toString());
					return;
				}
				if (StringUtils.isBlank(customer.getBrandName())) {
					redisKeyIncrement(importKey, "processCount", "failCount");
					log.error("品牌为空", customer.toString());
					return;
				}
				//if (StringUtils.isBlank(customer.getName())) {
				//	redisKeyIncrement(importKey, "processCount","failCount") ;
				//	log.error("品牌负责人为空", customer.toString());
				//	return;
				//}
				if (StringUtils.isBlank(customer.getBusiness())) {
					redisKeyIncrement(importKey, "processCount", "failCount");
					log.error("经营业态为空", customer.toString());
					return;
				}
				InvestDemandDto toImportCustomer = convetCustomer(importKey, customer, brandMap, businesseMap, shopMap, customerMap.get(customer.getPhone()), demandMap);
				if (toImportCustomer == null) {
					redisKeyIncrement(importKey, "processCount", "failCount");
					log.error("customerBase null");
					return;
				}
				if (Objects.isNull(customerMap.get(customer.getPhone()))) {
					saveCustomerAndDemand(toImportCustomer);
				} else {
					toImportCustomer.getCustomer().setId(customerMap.get(customer.getPhone()).getId());
					updateCustomerAndDemand(toImportCustomer);
				}
				//记数
				redisKeyIncrement(importKey, "processCount");
				stringRedisTemplate.expire(importKey, 10, TimeUnit.SECONDS);
			});
		} catch (Exception e) {
			setRedisValue(importKey, "1", "0", "0", "1", true);
			log.error("导入模板失败", e);
			throw new MallinkException(ErrorCode.MEM_IMPORT_ERR.getCode(), "导入模板失败");
		}
	}

	private Map<String, WxBusiness> getBusinessMap() {
		List<WxBusiness> businesses = businessService.listAsPage(null, 1, Integer.MAX_VALUE).getList();
		return getMap(businesses, WxBusiness::getTitle);
	}

	private Map<String, WxBrand> getBrandMap() {
		List<WxBrand> brands = brandService.listAsPage(null, 1, Integer.MAX_VALUE).getList();
		return getMap(brands, WxBrand::getName);
	}

	private InvestDemandDto convetCustomer(String importKey, InvestCustomerVo importCustomerVo, Map<String, WxBrand> brandMap, Map<String, WxBusiness> businesseMap, Map<String, WxShop> shopMap, InvestCustomerEntity dbCustomer, Map<Long, InvestDemandEntity> demandMap) {
		InvestCustomerEntity customerEntity = null;
		InvestDemandEntity demandEntity = null;
		if (Objects.isNull(dbCustomer)) {
			customerEntity = new InvestCustomerEntity();
		} else {
			customerEntity = dbCustomer;
			demandEntity = demandMap.get(dbCustomer.getId());
		}
		if (Objects.isNull(demandEntity)) {
			demandEntity = new InvestDemandEntity();
		}
		if (Objects.isNull(brandMap.get(importCustomerVo.getBrandName()))) {
			log.warn("品牌:{} 不存在", importCustomerVo.getBrandName());
			return null;
		}
		customerEntity.setBrandId(brandMap.get(importCustomerVo.getBrandName()).getId());

		if (Objects.isNull(businesseMap.get(importCustomerVo.getBusiness()))) {
			log.warn("业态:{} 不存在", importCustomerVo.getBusiness());
			return null;
		}
		customerEntity.setBusinessId(businesseMap.get(importCustomerVo.getBusiness()).getId());

		if (Objects.isNull(shopMap.get(importCustomerVo.getShopNumber()))) {
			log.warn("意向铺位:{} 不存在", importCustomerVo.getShopNumber());
			return null;
		}
		customerEntity.setName(importCustomerVo.getName());
		customerEntity.setPhone(importCustomerVo.getPhone());
		customerEntity.setType(importCustomerVo.getType());
		demandEntity.setTargetId(shopMap.get(importCustomerVo.getShopNumber()).getId());
		demandEntity.setTargetType(EnumInvestType.RENT);
		Map<String, Object> intent = new HashMap<>();
		if (Objects.nonNull(importCustomerVo.getRentArea())) {
			intent.put(InvestDemandEntity.KEY_RENT_AREA, importCustomerVo.getRentArea());
		}
		if (Objects.nonNull(importCustomerVo.getOpeningTime())) {
			intent.put(InvestDemandEntity.KEY_OPENING_TIME, importCustomerVo.getOpeningTime());
		}

		if (!intent.isEmpty()) {
			demandEntity.setIntent(JSON.toJSONString(intent));
		}

		InvestDemandDto demandDto = new InvestDemandDto();
		demandDto.setCustomer(customerEntity);
		demandDto.setDemand(demandEntity);
		return demandDto;
	}

	private void setRedisValue(String importKey, String allCount, String allSuccessCount, String processCount, String failCount, boolean fail) {
		stringRedisTemplate.opsForHash().put(importKey, "allCount", allCount);
		stringRedisTemplate.opsForHash().put(importKey, "allSuccessCount", allSuccessCount);
		stringRedisTemplate.opsForHash().put(importKey, "processCount", processCount);
		stringRedisTemplate.opsForHash().put(importKey, "failCount", failCount);
		if (fail) {
			stringRedisTemplate.expire(importKey, 3, TimeUnit.SECONDS);
		}
	}

	private void setRedisValueIfAbsent(String importKey) {
		stringRedisTemplate.opsForHash().putIfAbsent(importKey, "allCount", 0 + "");
		stringRedisTemplate.expire(importKey, 30, TimeUnit.MINUTES);
		stringRedisTemplate.opsForHash().putIfAbsent(importKey, "allSuccessCount", 0 + "");
		stringRedisTemplate.opsForHash().putIfAbsent(importKey, "processCount", "");
		stringRedisTemplate.opsForHash().putIfAbsent(importKey, "failCount", "");
	}

	private void setRedisValueIfError(String importKey, String allCount, String failCount, Exception e) {
		stringRedisTemplate.expire(importKey, 3, TimeUnit.SECONDS);
		stringRedisTemplate.opsForHash().putIfAbsent(importKey, "allCount", allCount);
		stringRedisTemplate.opsForHash().putIfAbsent(importKey, "failCount", failCount);
		log.error(e.getMessage());
	}

	private void redisKeyIncrement(String key, String... hashKey) {
		for (String s : hashKey) {
			stringRedisTemplate.opsForHash().increment(key, s, 1);
		}
	}

	@Override
	public List<InvestDemandVo> queryCustomer() {
		List<InvestCustomerEntity> customerEntities = customerService.list();
		return getTargeInfoList(new ArrayList<>(), customerEntities);
	}

	private InvestDemandDto doConvertDemand(InvestDemandQuery params) {
		InvestCustomerEntity customerEntity = null;
		if (ObjectUtils.anyNotNull(params.getBusinessId())) {
			customerEntity = new InvestCustomerEntity();
			//customerEntity.setType(params.getCustomerType());
			customerEntity.setBusinessId(params.getBusinessId());
		}

		InvestDemandEntity demandEntity = new InvestDemandEntity();
		if (Objects.isNull(InvestUserContext.getDataUser())) {
			demandEntity.setOwner(params.getDemandOwner());
		} else {
			demandEntity.setOwner(InvestUserContext.getDataUser());
		}

		InvestDemandDto demandDto = new InvestDemandDto();
		demandDto.setCustomer(customerEntity);
		demandDto.setDemand(demandEntity);
		return demandDto;
	}

	@Override
	public InvestPageResult<InvestTaskVo> queryPageTask(InvestTaskQuery params) {
		InvestTaskDto queryParams = convert(params, this::doConvertTask);
		InvestTaskEntity taskParams = null;
		WxShop shopParams = null;
		if (Objects.nonNull(queryParams)) {
			shopParams = queryParams.getShop();
			taskParams = queryParams.getTask();
		}
		LambdaQueryWrapper<InvestTaskEntity> taskQueryWrapper = new LambdaQueryWrapper<>();
		InvestPageResult<InvestTaskVo> investPage = new InvestPageResult<>();
		taskQueryWrapper.apply(StringUtils.isNotBlank(taskParams.getOwner()), "`owner` REGEXP {0}", taskParams.getOwner());
		if (Objects.nonNull(params.getBusinessId())) {
			taskQueryWrapper.apply("`content` REGEXP {0}", buildBusinessQuery(params));
		}
		taskParams.setOwner(null);
		taskQueryWrapper.setEntity(taskParams);

		if (Objects.nonNull(shopParams)) {
			Collection<WxShop> shops = shopService.selectList(new QueryWrapper<>(shopParams));
			if (CollectionUtils.isEmpty(shops)) {
				return investPage;
			}
			taskQueryWrapper.in(InvestTaskEntity::getTargetId, getIds(shops, WxShop::getId));
		}
		taskQueryWrapper.orderByDesc(InvestTaskEntity::getCreateDate);
		InvestPageResult<InvestTaskEntity> taskPage = taskService.queryPage(buildPageQuery(params, null), taskQueryWrapper);
		if (CollectionUtils.isEmpty(taskPage.getRecords())) {
			return investPage;
		}

		Collection<InvestTaskEntity> taskList = taskPage.getRecords();
		//2、目标信息
		Collection<WxShop> shops = shopService.getByIds(getIds(taskList, InvestTaskEntity::getTargetId));
		//3、商品合同信息
		Map<Long, WxRentContract> shopContractMap = new HashMap<>();
		if (CollectionUtils.isNotEmpty(shops)) {
			Collection<Long> shopPointIds = buildShopContractQuery(shops, EnumRentShopType.POINT);
			Collection<Long> shopIds = buildShopContractQuery(shops, EnumRentShopType.SHOP);
			shopContractMap = rentContractService.selectRentContractByShopIds(shopPointIds,
					StringUtils.join(shopIds, "|"),
					InvestUserContext.getUser());
		}
		for (WxShop shop : shops) {
			WxRentContract contract = shopContractMap.get(shop.getId());
			if (Objects.nonNull(contract)) {
				shop.setStartdate(contract.getRentalStartDate());
				shop.setEnddate(contract.getRentalEndDate());
			}
		}

		Map<Long, WxShop> shopsMap = getMap(shops, WxShop::getId);
		//4、用户信息
		Map<Long, MallUserInfo> usersMap = getMap(this.queryUserList(null), MallUserInfo::getId);
		List<InvestTaskVo> resultList = new ArrayList<>();
		for (InvestTaskEntity item : taskList) {
			WxShop shop = shopsMap.get(item.getTargetId());
			resultList.add(buildTaskItem(item, shop, usersMap));
		}
		BeanUtils.copyProperties(taskPage, investPage);
		investPage.setRecords(resultList);
		return investPage;
	}

	private String buildBusinessQuery(InvestTaskQuery params) {
		if (params.getBusinessId() <= 10) {
			return String.format("\"businessId\": %d[^1%d]", params.getBusinessId(), params.getBusinessId());
		}
		return String.format("\"businessId\": %d", params.getBusinessId());
	}

	private Collection<Long> buildShopContractQuery(Collection<WxShop> shops, EnumRentShopType shopType) {
		Collection<Long> shopIds = new ArrayList<>();
		if (CollectionUtils.isNotEmpty(shops)) {
			shopIds = InvestHelper.getIds(shops, wxShop -> Objects.equals(wxShop.getType(), shopType.getCode()), WxShop::getId);
		}
		if (CollectionUtils.isEmpty(shopIds)) {
			shopIds.add(00L);
		}
		return shopIds;
	}


	private InvestTaskDto doConvertTask(InvestTaskQuery params) {
		InvestTaskEntity task = new InvestTaskEntity();
		if (StringUtils.isNotBlank(params.getTaskOwner())) {
			task.setOwner(params.getTaskOwner());
		} else {
			task.setOwner(Objects.isNull(InvestUserContext.getDataUser()) ? "" : String.valueOf(InvestUserContext.getDataUser()));
		}
		task.setStatus(params.getTaskStatus());

		WxShop shop = null;
		if (ObjectUtils.anyNotNull(params.getShopNumber(), params.getShopStatus(), params.getBusinessId())) {
			shop = new WxShop();
			shop.setShopNumber(params.getShopNumber());
			shop.setStatus(params.getShopStatus());
			//shop.setBusinessId(params.getBusinessId());
		}

		InvestTaskDto taskDto = new InvestTaskDto();
		taskDto.setShop(shop);
		taskDto.setTask(task);
		return taskDto;
	}

	@Override
	public InvestPageResult<InvestFollowRecordVo> queryPageFollowRecord(InvestFollowQuery params) {
		InvestHelper.notNull(params);
		InvestFollowRecordEntity followRecordEntity = new InvestFollowRecordEntity();
		followRecordEntity.setFollowId(params.getFollowId());
		followRecordEntity.setType(params.getType());
		InvestPageQuery<InvestFollowRecordEntity> pageQuery = buildPageQuery(params, followRecordEntity);
		pageQuery.setSortColumn("create_date");
		pageQuery.setSortOrder("desc");
		InvestPageResult<InvestFollowRecordEntity> recordPage = followRecordService.queryPage(pageQuery);

		InvestPageResult<InvestFollowRecordVo> investPage = new InvestPageResult<>();
		if (CollectionUtils.isEmpty(recordPage.getRecords())) {
			return investPage;
		}

		Collection<InvestFollowRecordEntity> recordList = recordPage.getRecords();

		//2、用户信息
		Map<Long, MallUserInfo> usersMap = getMap(this.queryUserList(null), MallUserInfo::getId);

		//3、客户
		Collection<InvestCustomerEntity> customers = customerService.listByIds(getIds(recordList, InvestFollowRecordEntity::getCustomerId));
		Map<Long, InvestCustomerEntity> customerMap = getMap(customers, InvestCustomerEntity::getId);
		//4、 品牌
		Map<Long, WxBrand> brandMap = getMap(brandService.getByIds(getIds(customers, InvestCustomerEntity::getBrandId)), WxBrand::getId);

		List<InvestFollowRecordVo> resultList = new ArrayList<>();
		for (InvestFollowRecordEntity item : recordList) {
			InvestCustomerEntity customerEntity = customerMap.get(item.getCustomerId());
			WxBrand brand = null;
			if (Objects.nonNull(customerEntity)) {
				brand = brandMap.get(customerEntity.getBrandId());
			}
			resultList.add(buildFollowRecordItem(usersMap, item, customerEntity, brand));
		}

		BeanUtils.copyProperties(recordPage, investPage);
		investPage.setRecords(resultList);
		return investPage;
	}

	@Override
	public InvestPageResult<InvestRemindVo> queryPageRemind(InvestRemindQuery params) {
		InvestHelper.notNull(params);
		InvestPageResult<InvestRemindVo> investPage = new InvestPageResult<>();
		InvestPageQuery<InvestRemindEntity> remindPageQuery = new InvestPageQuery<>();
		BeanUtils.copyProperties(params, remindPageQuery);
		InvestRemindEntity remindQuery = new InvestRemindEntity();
		if (Objects.nonNull(InvestUserContext.getDataUser()) && Objects.isNull(params.getOwnerId())) {
			remindQuery.setOwner(InvestUserContext.getDataUser());
		} else {
			remindQuery.setOwner(params.getOwnerId());
		}
		//remindPageQuery.setQueryData(remindQuery);
		LambdaQueryWrapper<InvestRemindEntity> queryWrapper = new LambdaQueryWrapper<>(remindQuery);
		queryWrapper.eq(InvestRemindEntity::getTenantId, InvestUserContext.getUser().getTenantId());
		if (Objects.nonNull(params.getRemindDate())) {
			queryWrapper.apply("date_format(begin_date,'%Y-%m-%d') <= {0}", getDayStart(params.getRemindDate()))
			.apply("date_format(end_date,'%Y-%m-%d') >= {0}", getDayEnd(params.getRemindDate()));
		}
		queryWrapper.orderByDesc(InvestRemindEntity::getCreateDate);
		InvestPageResult<InvestRemindEntity> recordPage = remindService.queryPage(remindPageQuery, queryWrapper);
		if (CollectionUtils.isEmpty(recordPage.getRecords())) {
			return investPage;
		}
		Collection<InvestRemindEntity> recordList = recordPage.getRecords();
		Collection<InvestRemindVo> resultList = new ArrayList<>(Collections.emptyList());
		for (InvestRemindEntity investRemindEntity : recordList) {
			resultList.add(buildRemindItem(investRemindEntity));
		}

		//2、用户信息
		Map<Long, MallUserInfo> usersMap = getMap(userInfoService.getByIds(getIds(recordList, InvestRemindEntity::getOwner)), MallUserInfo::getId);

		//3、客户
		Collection<InvestCustomerEntity> customers = customerService.listByIds(getIds(resultList, InvestRemindVo::getCustomerId));
		Map<Long, InvestCustomerEntity> customerMap = getMap(customers, InvestCustomerEntity::getId);
		//4、 品牌
		Map<Long, WxBrand> brandMap = getMap(brandService.getByIds(getIds(customers, InvestCustomerEntity::getBrandId)), WxBrand::getId);

		for (InvestRemindVo remindVo : resultList) {
			InvestCustomerEntity customerEntity = customerMap.get(remindVo.getCustomerId());
			if (Objects.nonNull(customerEntity)) {
				remindVo.setCustomer(customerEntity);
				remindVo.setBrand(brandMap.get(customerEntity.getBrandId()));
			}
			remindVo.setOwnerInfo(usersMap.get(remindVo.getOwner()));
		}

		BeanUtils.copyProperties(recordPage, investPage);
		investPage.setRecords(resultList);

		return investPage;
	}

	private String getDayEnd(Date date) {
		//Calendar calendar = Calendar.getInstance();
		//calendar.setTime(date);
		//calendar.add(Calendar.DAY_OF_YEAR, 1);
		return DateUtils.format(date);
	}

	private String getDayStart(Date date) {
		return DateUtils.format(date);
	}

	@Override
	public InvestPageResult<InvestMessageEntity> queryPageMessage(InvestMessageQuery params) {
		InvestHelper.notNull(params);
		InvestPageQuery<InvestMessageEntity> query = new InvestPageQuery<>();
		BeanUtils.copyProperties(params, query);
		InvestMessageEntity messageEntity = new InvestMessageEntity();
		messageEntity.setOwner(InvestUserContext.getUserId());
		query.setQueryData(messageEntity);
		query.setSortColumn("create_date");
		query.setSortOrder("desc");
		return messageService.queryPage(query);
	}

	private void buildQueryWrapper(LambdaQueryWrapper<InvestOperateRecordEntity> wrapper, String tbl, Long tId) {
		if (ObjectUtils.allNotNull(tbl, tId)) {
			wrapper.eq(InvestOperateRecordEntity::getTbl, tbl);
			wrapper.eq(InvestOperateRecordEntity::getTid, tId);
			wrapper.orderByDesc(InvestOperateRecordEntity::getCreateDate);
		}
	}

	private List<MallUserInfo> getMallUserInfos(Map<Long, MallUserInfo> usersMap, InvestFollowRecordEntity item) {
		List<MallUserInfo> ownerInfo = null;
		Map contentMap = JSON.parseObject(item.getContent(), Map.class);
		if (MapUtils.isNotEmpty(contentMap)) {
			Object followMember = contentMap.get(InvestFollowRecordEntity.KEY_MEMBER);
			ownerInfo = getMallUserInfos(followMember, usersMap);
		}
		return ownerInfo;
	}

	@Override
	public List<MallUserInfo> queryUserList() {
		return queryUserList(EnumInvestUserType.ALL);
	}

	@Override
	public Map<String, Object> shopRentInfo(Long shopId) {
		WxShop shop = shopService.getById(shopId);
		InvestHelper.notNull(shop, "shop 不存在");
		//3、商品合同信息
		Map<Long, WxRentContract> shopContractMap = rentContractService.selectRentContractByShopIds(Arrays.asList(shop.getId()),
				StringUtils.join(shop.getId()),
				InvestUserContext.getUser());
		WxRentContract contract = shopContractMap.get(shop.getId());
		InvestHelper.notNull(contract, "合同信息不存在");
		Map<String, Object> map = new HashMap<>();
		map.put("startdate", contract.getRentalStartDate());
		map.put("enddate", contract.getRentalEndDate());
		return map;
	}

	public List<MallUserInfo> queryUserList(EnumInvestUserType userType) {
		LambdaQueryWrapper<MallUserInfo> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(MallUserInfo::getStatus, 1);
		if (Objects.nonNull(userType)) {
			queryWrapper.in(MallUserInfo::getInvestRule, EnumInvestUserType.MANAGER.getCode(), EnumInvestUserType.USER.getCode());
		}
		return userInfoService.selectList(queryWrapper);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public boolean saveCustomerAndDemand(InvestDemandDto demandDto) {
		InvestHelper.notNull(demandDto, demandDto.getCustomer(), demandDto.getDemand());
		InvestCustomerEntity customerEntity = demandDto.getCustomer();
		checkCustomer(customerEntity);
		customerService.save(customerEntity);
		InvestDemandEntity demandEntity = demandDto.getDemand();
		demandEntity.setCustomerId(customerEntity.getId());
		demandService.save(demandEntity);
		saveMessage(demandEntity, demandDto.getCustomer());
		return true;
	}

	private void checkCustomer(InvestCustomerEntity customerEntity) {
		if (Objects.equals(customerEntity.getType(), EnumCustomerType.COOPERATIVE)) {
			InvestHelper.notNull(customerEntity.getContractNo(), "合同编号");
			WxRentContract contract = new WxRentContract();
			contract.updateTenantInfo(InvestUserContext.getUser());
			contract.setContractNumber(customerEntity.getContractNo());
			ResultData resultData = rentContractService.hasContractNumber(contract);
			InvestHelper.isTrue(Objects.equals(resultData.data, true),ErrorCode.INVEST_RESULT_NOT_FOUND,"合同编号");
		}
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public boolean updateCustomerAndDemand(InvestDemandDto demandDto) {
		InvestHelper.notNull(demandDto, demandDto.getCustomer(), demandDto.getDemand());
		Long customerId = demandDto.getCustomer().getId();
		InvestCustomerEntity customerEntity = demandDto.getCustomer();
		if (Objects.isNull(customerId)) {
			customerId = demandDto.getDemand().getCustomerId();
			customerEntity.setId(customerId);
		}
		checkCustomer(customerEntity);
		customerService.updateById(customerEntity);
		InvestDemandEntity demandEntity = demandDto.getDemand();
		if (Objects.isNull(demandEntity.getCustomerId())) {
			demandEntity.setCustomerId(customerId);
		}
		InvestDemandEntity dbDemand = demandService.getByCustomerId(customerId);
		if (Objects.isNull(dbDemand)) {
			demandService.save(demandEntity);
		} else {
			demandService.updateById(demandEntity);
		}
		saveMessage(demandEntity, customerEntity);
		return true;
	}

	private void saveMessage(InvestDemandEntity demandEntity, InvestCustomerEntity customerEntity) {
		if (Objects.isNull(demandEntity)) {
			return;
		}
		Long owner = demandEntity.getOwner();
		if (Objects.nonNull(owner) && !Objects.equals(owner, 0L)) {
			List<Long> ownerArray = Collections.singletonList(owner);
			demandService.saveBatchMessage(ownerArray, EnumInvestMessageType.CUSTOMER_CREATE.getInfo(),
					EnumInvestMessageTag.CUSTOMER_CREATE, EnumFollowType.DEMAND, customerEntity.getId(), customerEntity);
		}
	}

	@Override
	public boolean saveTask(InvestTaskEntity investTaskEntity) {
		//syncTargetStatus(investTaskEntity);
		return taskService.save(investTaskEntity);
	}

	@Override
	public boolean updateTask(InvestTaskEntity investTaskEntity) {
		syncTargetStatus(investTaskEntity);
		return taskService.updateById(investTaskEntity);
	}

	@Override
	public InvestDemandVo findDemandById(Long id) {
		InvestCustomerEntity customerEntity = customerService.getByIdNotNull(id);
		InvestDemandEntity demandEntity = demandService.getByCustomerId(customerEntity.getId());
		WxBrand brand = brandService.getById(customerEntity.getBrandId());
		WxShop shop = null;
		Map<Long, MallUserInfo> usersMap = null;
		if (Objects.nonNull(demandEntity)) {
			shop = shopService.getById(demandEntity.getTargetId());
			usersMap = getMap(this.queryUserList(null), MallUserInfo::getId);
		}
		return buildDemindItem(demandEntity, customerEntity, brand, shop, usersMap);
	}

	@Override
	public InvestTaskVo findTaskById(Long id) {
		InvestTaskEntity taskEntity = taskService.getByIdNotNull(id);
		WxShop shop = shopService.getById(taskEntity.getTargetId());
		WxShopVo shopVo = null;
		if (Objects.nonNull(shop)) {
			WxShop shopMapQuery = new WxShop();
			shopMapQuery.setIds(Arrays.asList(taskEntity.getTargetId()));
			Collection<Map<String, Object>> shopMap = shopService.listMapAsPage(shopMapQuery, 1, 10).getList();
			for (Map<String, Object> stringObjectMap : shopMap) {
				Long shopId = Long.valueOf(String.valueOf(stringObjectMap.get("id")));
				if (Objects.nonNull(shop.getId())) {
					shopVo = new WxShopVo();
					shopVo.setId(shopId);
					shopVo.setFloorName(String.valueOf(stringObjectMap.get("floor")));
					shopVo.setBuildingName(String.valueOf(stringObjectMap.get("building")));
					BeanUtils.copyProperties(shop, shopVo);
				}
			}

			//3、商品合同信息
			Map<Long, WxRentContract> shopContractMap = getWxRentContractMap(shop);
			WxRentContract contract = shopContractMap.get(shop.getId());
			if (Objects.nonNull(contract)) {
				shopVo.setStartdate(contract.getRentalStartDate());
				shopVo.setEnddate(contract.getRentalEndDate());
			}

		}
		Map<Long, MallUserInfo> usersMap = getMap(this.queryUserList(null), MallUserInfo::getId);
		return buildTaskItem(taskEntity, shopVo, usersMap);
	}

	/**
	 * 获取商铺对应的正式合同信息
	 *
	 * @param shop
	 * @return
	 */
	private Map<Long, WxRentContract> getWxRentContractMap(WxShop shop) {
		//InvestHelper.notNull(shop, "商铺不存在");
		if (Objects.isNull(shop)) {
			return new HashMap<>();
		}
		return rentContractService.selectRentContractByShopIds(Arrays.asList(shop.getId()),
				StringUtils.join(shop.getId(), ""),
				InvestUserContext.getUser());
	}

	@Override
	public InvestRemindVo findRemindById(Long id) {
		InvestRemindEntity remindEntity = remindService.getByIdNotNull(id);
		InvestRemindVo remindVo = buildRemindItem(remindEntity);

		InvestCustomerEntity customerEntity = customerService.getByIdNotNull(remindVo.getCustomerId());
		if (Objects.nonNull(customerEntity)) {
			remindVo.setCustomer(customerEntity);
			WxBrand brand = brandService.getById(customerEntity.getBrandId());
			if (Objects.nonNull(brand)) {
				remindVo.setBrand(brand);
			}
		}

		MallUserInfo userInfo = userInfoService.getById(remindEntity.getOwner());
		if (Objects.nonNull(userInfo)) {
			remindVo.setOwnerInfo(userInfo);
		}
		return remindVo;
	}

	@Override
	public Collection<InvestOperateRecordVo> findOperateById(InvestOperateRecordQuery params) {
		params.setPageSize(Integer.MAX_VALUE);
		return findOperateListById(params).getRecords();
	}

	@Override
	public InvestPageResult<InvestOperateRecordVo> findOperateListById(InvestOperateRecordQuery params) {
		InvestHelper.notNull(params, params.getRecordType(), params.getTid());
		InvestPageResult<InvestOperateRecordVo> investPage = new InvestPageResult<>();
		InvestPageResult<InvestOperateRecordEntity> entityPageList = operateRecordService.selectPageByTid(params);
		if (entityPageList.getSize() == 0) {
			return investPage;
		}

		Collection<InvestOperateRecordEntity> recordList = entityPageList.getRecords();
		Map<Long, MallUserInfo> usersMap = getMap(userInfoService.findList(new MallUserInfo()), MallUserInfo::getId);

		//品牌信息
		List<WxBrand> brands = brandService.listAsPage(null, 1, Integer.MAX_VALUE).getList();
		Map<Long, WxBrand> brandMap = getMap(brands, WxBrand::getId);

		//业态信息
		List<WxBusiness> businesses = businessService.listAsPage(null, 1, Integer.MAX_VALUE).getList();
		Map<Integer, WxBusiness> businesseMap = getMap(businesses, WxBusiness::getId);

		//业态信息
		List<WxShop> shopList = shopService.listAsPage(null, 1, Integer.MAX_VALUE).getList();
		Map<Long, WxShop> shopMap = getMap(shopList, WxShop::getId);

		List<InvestOperateRecordVo> resultList = new ArrayList<>();
		for (InvestOperateRecordEntity recordEntity : recordList) {
			InvestOperateRecordVo itemVo = new InvestOperateRecordVo();
			BeanUtils.copyProperties(recordEntity, itemVo);
			MallUserInfo userInfo = usersMap.get(recordEntity.getOperator());
			if (Objects.nonNull(userInfo)) {
				itemVo.setOperatorName(userInfo.getName());
			}
			TableTriple content = JSON.parseObject(recordEntity.getContent(), TableTriple.class);
			itemVo.setRecord(convert(content, tableTriple -> {
				Object column = tableTriple.getColumn();
				if (Objects.equals(column, "businessId")) {
					WxBusiness businessBefore = businesseMap.get(tableTriple.getBefore());
					WxBusiness businessAfter = businesseMap.get(tableTriple.getAfter());
					if (Objects.nonNull(businessBefore)) {
						tableTriple.setBefore(businessBefore.getTitle());
					}
					if (Objects.nonNull(businessAfter)) {
						tableTriple.setAfter(businessAfter.getTitle());
					}
				} else if (Objects.equals(column, "brandId")) {
					WxBrand brandBefore = brandMap.get(tableTriple.getBefore());
					WxBrand brandAfter = brandMap.get(tableTriple.getAfter());
					if (Objects.nonNull(brandBefore)) {
						tableTriple.setBefore(brandBefore.getName());
					}
					if (Objects.nonNull(brandAfter)) {
						tableTriple.setAfter(brandAfter.getName());
					}
				} else if (Objects.equals(column, "owner")) {
					MallUserInfo userBefore = usersMap.get(tableTriple.getBefore());
					MallUserInfo userAfter = usersMap.get(tableTriple.getAfter());
					if (Objects.nonNull(userBefore)) {
						tableTriple.setBefore(userBefore.getName());
					}
					if (Objects.nonNull(userAfter)) {
						tableTriple.setAfter(userAfter.getName());
					}
				} else if (Objects.equals(column, "targetId")) {
					Object beforeVal = tableTriple.getBefore();
					Object afterVal = tableTriple.getBefore();
					WxShop shopBefore;
					WxShop shopAfter;
					if (beforeVal instanceof Integer) {
						shopBefore = shopMap.get(Long.valueOf((Integer) beforeVal));
					} else {
						shopBefore = shopMap.get(beforeVal);
					}
					if (afterVal instanceof Integer) {
						shopAfter = shopMap.get(Long.valueOf((Integer) afterVal));
					} else {
						shopAfter = shopMap.get(afterVal);
					}

					if (Objects.nonNull(shopBefore)) {
						tableTriple.setBefore(shopBefore.getShopNumber());
					}
					if (Objects.nonNull(shopAfter)) {
						tableTriple.setAfter(shopAfter.getShopNumber());
					}
				}
				return tableTriple;
			}));
			resultList.add(itemVo);
		}
		BeanUtils.copyProperties(entityPageList, investPage);
		investPage.setRecords(resultList);
		return investPage;
	}

	private List<InvestOperateRecordVo> getRecordList(InvestOperateRecordEntity recordEntity, Collection<TableTriple> contentList, MallUserInfo userInfo) {
		List<InvestOperateRecordVo> recordVo = new ArrayList<>();
		if (CollectionUtils.isEmpty(contentList)) {
			return recordVo;
		}
		for (TableTriple record : contentList) {
			InvestOperateRecordVo itemVo = new InvestOperateRecordVo();
			BeanUtils.copyProperties(recordEntity, itemVo);
			if (Objects.nonNull(userInfo)) {
				itemVo.setOperatorName(userInfo.getName());
			}
			itemVo.setRecord(record);
			recordVo.add(itemVo);
		}
		return recordVo;
	}

	@Override
	public InvestFollowRecordVo findFollowRecordById(Long id) {
		InvestFollowRecordEntity followRecordEntity = followRecordService.getByIdNotNull(id);
		Map<Long, MallUserInfo> usersMap = getMap(this.queryUserList(null), MallUserInfo::getId);
		InvestCustomerEntity customerEntity = customerService.getByIdNotNull(followRecordEntity.getCustomerId());
		WxBrand brand = brandService.getById(customerEntity.getBrandId());
		return buildFollowRecordItem(usersMap, followRecordEntity, customerEntity, brand);
	}

	@Override
	public Map<String, Object> statistics() {
		Map<String, Object> result = new HashMap<>();
		if (Objects.isNull(InvestUserContext.getDataUser())) {
			result.put("taskTotal", taskService.count(new LambdaQueryWrapper<InvestTaskEntity>()
					.ge(InvestTaskEntity::getStatus, EnumTaskStatus.CREATED)
					.eq(InvestTaskEntity::getTenantId, InvestUserContext.getUser().getTenantId())));
			result.put("customerTotal", customerService.count(new LambdaQueryWrapper<InvestCustomerEntity>()
					.eq(InvestCustomerEntity::getTenantId, InvestUserContext.getUser().getTenantId())));
			result.put("customerToday", customerService.count(new LambdaQueryWrapper<InvestCustomerEntity>()
					.apply("date_format(create_date,'%Y-%m-%d') = {0}", DateUtils.format(new Date()))
					.eq(InvestCustomerEntity::getTenantId, InvestUserContext.getUser().getTenantId())));
			result.put("customerImportant", customerService.count(new LambdaQueryWrapper<InvestCustomerEntity>()
					.eq(InvestCustomerEntity::getType, EnumCustomerType.INTENTIONAL)
					.eq(InvestCustomerEntity::getTenantId, InvestUserContext.getUser().getTenantId())));
			result.put("remindTotal", remindService.count(new LambdaQueryWrapper<InvestRemindEntity>()
					.eq(InvestRemindEntity::getTenantId, InvestUserContext.getUser().getTenantId())));
			result.put("taskUnassigned", taskService.count(new LambdaQueryWrapper<InvestTaskEntity>()
					.eq(InvestTaskEntity::getStatus, EnumTaskStatus.CREATED)
					.eq(InvestTaskEntity::getTenantId, InvestUserContext.getUser().getTenantId())));
			result.put("customerUnassigned", customerService.countCustomerUnassigned(InvestUserContext.getUser().getTenantId()));
		} else {
			result.put("taskTotal", taskService.count(new LambdaQueryWrapper<InvestTaskEntity>()
					.ge(InvestTaskEntity::getStatus, EnumTaskStatus.CREATED)
					.apply("`owner` REGEXP {0}", InvestUserContext.getUserId())));
			result.put("customerTotal", demandService.count(new LambdaQueryWrapper<InvestDemandEntity>()
					.eq(InvestDemandEntity::getOwner, InvestUserContext.getUserId())
					.eq(InvestDemandEntity::getTenantId, InvestUserContext.getUser().getTenantId())));
			result.put("taskToday", taskService.count(new LambdaQueryWrapper<InvestTaskEntity>()
					.apply("`owner` REGEXP {0}", InvestUserContext.getUserId())
					.apply("date_format(create_date,'%Y-%m-%d') = {0}", DateUtils.format(new Date()))
					.eq(InvestTaskEntity::getTenantId, InvestUserContext.getUser().getTenantId())));
			result.put("customerToday", demandService.count(new LambdaQueryWrapper<InvestDemandEntity>()
					.eq(InvestDemandEntity::getOwner, InvestUserContext.getUserId())
					.apply("date_format(create_date,'%Y-%m-%d') = {0}", DateUtils.format(new Date()))
					.eq(InvestDemandEntity::getTenantId, InvestUserContext.getUser().getTenantId())));
		}
		return result;
	}

	private void syncTargetStatus(InvestTaskEntity investTaskEntity) {
		//if (!Objects.equals(investTaskEntity.getTargetType(), EnumInvestType.RENT)) {
		//	return;
		//}

		if (InvestHelper.checkOwner(investTaskEntity)) {
			return;
		}
		WxShop shop = shopService.getById(investTaskEntity.getTargetId());
		if (Objects.nonNull(shop)) {
			Map<Long, WxRentContract> shopContractMap = getWxRentContractMap(shop);
			WxRentContract contract = shopContractMap.get(shop.getId());
			if (Objects.nonNull(contract)) {
				InvestHelper.addContractId(investTaskEntity.getContent(), contract.getId(), null);
				investTaskEntity.setStatus(EnumTaskStatus.FINISH);
			} else {
				WxRentContract contractQuery = new WxRentContract();
				contractQuery.updateTenantInfo(InvestUserContext.getUser());
				contractQuery.setShopId(investTaskEntity.getTargetId());
				contractQuery.setStatus(EnumRentContractStatus.INTENTION.getCode());
				//获取意向合同
				int count = rentContractService.selectContractCountByShopId(contractQuery);
				if (count > 0) {
					investTaskEntity.setStatus(EnumTaskStatus.INTENTION);
				}
			}
		}
	}

	private InvestFollowRecordVo buildFollowRecordItem(Map<Long, MallUserInfo> usersMap, InvestFollowRecordEntity item,
	                                                   InvestCustomerEntity customerEntity, WxBrand brand) {
		List<MallUserInfo> ownerInfo = getMallUserInfos(usersMap, item);
		InvestFollowRecordVo followRecordVo = new InvestFollowRecordVo();
		followRecordVo.setCustomer(customerEntity);
		followRecordVo.setMemberInfo(ownerInfo);
		followRecordVo.setBrand(brand);
		if (Objects.nonNull(usersMap.get(item.getOwner()))) {
			followRecordVo.setOwnerInfo(usersMap.get(item.getOwner()));
			followRecordVo.setOperatorName(usersMap.get(item.getOwner()).getName());
		}
		BeanUtils.copyProperties(item, followRecordVo);
		return followRecordVo;
	}

	private InvestDemandVo buildDemindItem(InvestDemandEntity item, InvestCustomerEntity customer, WxBrand brand,
	                                       WxShop shop, Map<Long, MallUserInfo> usersMap) {
		if (Objects.isNull(customer.getBrandId())) {
			customer.setBrandId(null);
		}
		InvestDemandVo resultItemVo = new InvestDemandVo();
		BeanUtils.copyProperties(customer, resultItemVo);
		resultItemVo.setBrand(brand);
		resultItemVo.setTargetInfo(shop);
		if (Objects.nonNull(item)) {
			if (Objects.equals(item.getOwner(), 0L)) {
				item.setOwner(null);
			}
			if (Objects.nonNull(usersMap.get(item.getOwner()))) {
				resultItemVo.setOwnerInfo(usersMap.get(item.getOwner()));
			}
		}
		resultItemVo.setDemand(item);
		return resultItemVo;
	}

	private InvestCustomerVo buildCustomerItem(InvestDemandEntity item, InvestCustomerEntity customer, WxBrand brand,
	                                           WxShop shop, WxBusiness business) {
		InvestCustomerVo resultItemVo = new InvestCustomerVo();
		BeanUtils.copyProperties(customer, resultItemVo);
		if (Objects.nonNull(brand)) {
			resultItemVo.setBrandName(brand.getName());
		}
		if (Objects.nonNull(shop)) {
			resultItemVo.setShopNumber(shop.getShopNumber());
		}
		if (Objects.nonNull(business)) {
			resultItemVo.setBusiness(business.getTitle());
		}
		if (Objects.nonNull(item)) {
			resultItemVo.setDemandOwner(item.getOwner());
			if (StringUtils.isNotBlank(item.getIntent())) {
				Map intentMap = JSON.parseObject(item.getIntent(), Map.class);
				Object rentArea = intentMap.get(InvestDemandEntity.KEY_RENT_AREA);
				Object openingTime = intentMap.get(InvestDemandEntity.KEY_OPENING_TIME);
				if (Objects.nonNull(rentArea)) {
					resultItemVo.setRentArea(Integer.valueOf(String.valueOf(rentArea)));
				}
				if (Objects.nonNull(openingTime)) {
					resultItemVo.setOpeningTime(String.valueOf(openingTime));
				}
			}
		}
		//resultItemVo.setBusiness(usersMap.get(item.getOwner()));
		return resultItemVo;
	}

	private InvestTaskVo buildTaskItem(InvestTaskEntity item, WxShop shop, Map<Long, MallUserInfo> usersMap) {
		List<MallUserInfo> ownerInfo = getMallUserInfos(item.getOwner(), usersMap);
		InvestTaskVo resultItemVo = new InvestTaskVo();
		resultItemVo.setTargetInfo(shop);
		resultItemVo.setOwnerInfo(ownerInfo);
		BeanUtils.copyProperties(item, resultItemVo);
		return resultItemVo;
	}


	private InvestRemindVo buildRemindItem(InvestRemindEntity remindEntity) {
		InvestRemindVo remindVo = new InvestRemindVo();
		BeanUtils.copyProperties(remindEntity, remindVo);
		Map contentMap = JSON.parseObject(remindEntity.getContent(), Map.class);
		if (MapUtils.isNotEmpty(contentMap)) {
			Object customerId = contentMap.get(InvestRemindEntity.KEY_CUSTOMER);
			remindVo.setCustomerId(Objects.isNull(customerId) ? null : Long.parseLong((String) customerId));
			Object negotiationType = contentMap.get(InvestRemindEntity.KEY_NEGOTIATIONTYPE);
			remindVo.setNegotiationType(EnumNegotiationType.getEnum(Integer.valueOf((String) negotiationType)));
		}
		return remindVo;
	}

	private List<MallUserInfo> getMallUserInfos(Object userJson, Map<Long, MallUserInfo> usersMap) {
		List<MallUserInfo> ownerInfo = Lists.newArrayList();
		JSONArray ownerList;
		if (userJson instanceof String) {
			ownerList = JSONArray.parseArray((String) userJson);
		} else {
			ownerList = (JSONArray) userJson;
		}
		if (CollectionUtils.isNotEmpty(ownerList)) {
			for (Object userId : ownerList) {
				if (userId instanceof Long) {
					ownerInfo.add(usersMap.get(userId));
				} else {
					String uId = (String) userId;
					if (StringUtils.isNotBlank(uId)) {
						ownerInfo.add(usersMap.get(Long.parseLong(uId)));
					}
				}
			}
		}
		return ownerInfo;
	}

	private List<InvestCustomerVo> getCustomerVOList(List<InvestDemandEntity> demandList, Collection<InvestCustomerEntity> customers) {
		Map<Long, InvestDemandEntity> demindsMap = getMap(demandList, InvestDemandEntity::getCustomerId);

		//3、目标信息
		Collection<WxShop> shops = shopService.getByIds(getIds(demandList, InvestDemandEntity::getTargetId));
		Map<Long, WxShop> shopsMap = getMap(shops, WxShop::getId);

		//4、品牌
		Map<Long, WxBrand> brandMap = getMap(brandService.getByIds(getIds(customers, InvestCustomerEntity::getBrandId)), WxBrand::getId);
		//5、用户
		Map<Integer, WxBusiness> bussinessMap = getMap(businessService.getByIds(getIds(customers, InvestCustomerEntity::getBusinessId)), WxBusiness::getId);
		List<InvestCustomerVo> resultList = new ArrayList<>();
		for (InvestCustomerEntity costomerItem : customers) {
			InvestDemandEntity demandItem = demindsMap.get(costomerItem.getId());
			WxShop shop = null;
			WxBrand brand = null;
			if (Objects.nonNull(demandItem)) {
				shop = shopsMap.get(demandItem.getTargetId());
				brand = brandMap.get(costomerItem.getBrandId());
			}
			resultList.add(buildCustomerItem(demandItem, costomerItem, brand, shop, bussinessMap.get(costomerItem.getBusinessId())));
		}
		return resultList;
	}

	private List<InvestDemandVo> getTargeInfoList(List<InvestDemandEntity> demandList, Collection<InvestCustomerEntity> customers) {
		Map<Long, InvestDemandEntity> demindsMap = new HashMap<>();
		Map<Long, WxShop> shopsMap = new HashMap<>();
		Map<Long, MallUserInfo> usersMap = new HashMap<>();
		if (CollectionUtils.isNotEmpty(demandList)) {
			demindsMap = getMap(demandList, InvestDemandEntity::getCustomerId);
			//3、目标信息
			Collection<WxShop> shops = shopService.getByIds(getIds(demandList, InvestDemandEntity::getTargetId));
			shopsMap = getMap(shops, WxShop::getId);
			//5、用户
			usersMap = getMap(userInfoService.getByIds(getIds(demandList, InvestDemandEntity::getOwner)), MallUserInfo::getId);
		}

		//4、品牌
		Map<Long, WxBrand> brandMap = getMap(brandService.getByIds(getIds(customers, InvestCustomerEntity::getBrandId)), WxBrand::getId);

		List<InvestDemandVo> resultList = new ArrayList<>();
		for (InvestCustomerEntity costomerItem : customers) {
			InvestDemandEntity demandItem = demindsMap.get(costomerItem.getId());
			WxShop shop = null;
			if (Objects.nonNull(demandItem)) {
				shop = shopsMap.get(demandItem.getTargetId());
			}
			WxBrand brand = brandMap.get(costomerItem.getBrandId());
			resultList.add(buildDemindItem(demandItem, costomerItem, brand, shop, usersMap));
		}
		return resultList;
	}

	private <T> InvestPageQuery<T> buildPageQuery(InvestPageQuery params, T t) {
		InvestPageQuery<T> pageQuery = new InvestPageQuery<>();
		BeanUtils.copyProperties(params, pageQuery);
		if (Objects.nonNull(t)) {
			pageQuery.setQueryData(t);
		}
		return pageQuery;
	}

	public <R, T> R convert(T params, Function<T, R> function) {
		InvestHelper.notNull(params);
		return function.apply(params);
	}

	private <T, R> Map<R, T> getMap(Collection<T> dataList, Function<T, R> keyMapper) {
		if (CollectionUtils.isEmpty(dataList)) {
			return new HashMap<>();
		}
		return InvestHelper.getMap(dataList, keyMapper);
	}

	private <T, R> Collection<R> getIds(Collection<T> dataList, Function<? super T, R> mapper) {
		if (CollectionUtils.isEmpty(dataList)) {
			return Collections.emptyList();
		}
		return InvestHelper.getIds(dataList, mapper);
	}
}
