package com.cyksj.web.controller.manage.distribute;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.BetweenFormater;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.annotation.Log;
import com.cyksj.common.constant.Constant;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.util.StringUtil;
import com.cyksj.dto.Result;
import com.cyksj.enums.BusinessType;
import com.cyksj.enums.GatewayResponse;
import com.cyksj.mapper.*;
import com.cyksj.mapper.manage.cms.CmsUserMapper;
import com.cyksj.mapper.manage.coupon.CouponDistributePopularizeMapper;
import com.cyksj.mapper.manage.distribute.*;
import com.cyksj.mapper.manage.distribute.equipment.UserDistributeEquipmentMapper;
import com.cyksj.mapper.manage.distribute.sub.UserDistributeSubMapper;
import com.cyksj.model.entity.*;
import com.cyksj.model.request.BusinessDistributeDefaultRateDetailReq;
import com.cyksj.model.request.DistributeApplyMoneyReq;
import com.cyksj.model.request.UserDistributeReq;
import com.cyksj.model.views.*;
import com.cyksj.redis.RedisService;
import com.cyksj.service.distribute.DistributeService;
import com.cyksj.service.distribute.UserDistributeReturnMoneyDetailService;
import com.cyksj.service.mange.business.UserBusinessRateService;
import com.cyksj.service.mange.statistics.StatisticsDataService;
import com.cyksj.service.sys.SysConfigService;
import com.cyksj.service.user.UserBenefitsService;
import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.SearchResult;
import com.ejlchina.searcher.param.Operator;
import com.ejlchina.searcher.util.MapBuilder;
import com.ejlchina.searcher.util.MapUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/** admin/分销管理
 *项目名: netflix
 *文件名: DistributeController
 *创建者: JavaZou
 *创建时间:2022/11/14 12:06
 */
@RestController
@RequestMapping("/manage/distribute")
@RequiredArgsConstructor
@Slf4j
public class DistributeController {

	private final DistributeService distributeService;

	private final UserDistributeMapper userDistributeMapper;

	private final BeanSearcher beanSearcher;

	private final DistributeMoneyApplyMapper distributeMoneyApplyMapper;

	private final DistributePointsExchangeMoneyMapper distributePointsExchangeMoneyMapper;

	private final GoodsDonMapper goodsDonMapper;

	private final UserMapper userMapper;

	private final GoodsDonSkuMapper goodsDonSkuMapper;

	private final StatisticsDataService statisticsDataService;

	private final UserBusinessRateService userBusinessRateService;

	private final UserDistributeBusinessRateMapper userDistributeBusinessRateMapper;

	private final HttpServletRequest request;

	private final CmsUserMapper cmsUserMapper;

	private final UserBusinessDefaultRateConfigMapper defaultRateConfigMapper;

	private final BusinessDistributeDefaultRateConfigMapper businessDefaultRateConfigMapper;

	private final BusinessDistributeDefaultSkuRateConfigMapper businessDistributeDefaultSkuRateConfigMapper;

	private final UserBenefitsService userBenefitsService;

	private final CouponDistributePopularizeMapper couponDistributePopularizeMapper;

	private final SysConfigService sysConfigService;

	private final RedisService redisService;

	private final DistributeGoodsSkuAlertMapper distributeGoodsSkuAlertMapper;

	private final UserDistributeRuleOrderRecordMapper userDistributeRuleOrderRecordMapper;

	private final UserDistributeBusinessGeneralRateMapper businessGeneralRateMapper;

	private final OrderDonMapper orderDonMapper;

	private final UserDistributeTargetAlertMapper targetAlertMapper;

	private final UserDistributeTargetAlertRecordMapper targetAlertRecordMapper;

	private final UserDistributeSharedWhiteMapper userDistributeSharedWhiteMapper;

	private final UserDistributeEquipmentMapper userDistributeEquipmentMapper;

	private final UserDistributeSubMapper userDistributeSubMapper;

	private final UserDistributeReturnMoneyDetailService userDistributeReturnMoneyDetailService;
	/**
	 * 添加固定推广者
	 */
	@PostMapping
	@SaCheckPermission("distribute:add")
	@Log(module = "分销管理/增加推广者", businessType = BusinessType.POST, isSaveRequestData = true)
	public Result<String> saveDistributes(@RequestBody @NotNull UserDistributeReq userDistributeReq) {
		try {
			distributeService.insertDistribute(userDistributeReq);
			Long businessId = userDistributeReq.getBusinessId();
			//保存商务人员提成比例
			userBusinessRateService.saveBusinessRate(businessId);
			//清除 之前有普通推广专属码
			couponDistributePopularizeMapper.update(null, Wrappers.lambdaUpdate(CouponDistributePopularize.class)
					.set(CouponDistributePopularize::getDeleted, 0)
					.eq(CouponDistributePopularize::getUserId, userDistributeReq.getUserId())
					.eq(CouponDistributePopularize::getIsGeneral, true));
		} catch (Exception e) {
			String cacheKey = RedisService.key.USER_DISTRIBUTE_ADD_KEY.getNameFormat(userDistributeReq.getUserId());
			if (redisService.hasKey(cacheKey)) {
				redisService.del(cacheKey);
			}
			throw BusinessRuntimeException.getInstance(e.getMessage());
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult("添加成功");
	}

	/**
	 * 删除固定推广者
	 */
	@DeleteMapping("/del/{id}")
	@SaCheckPermission("distribute:delete")
	@Log(module = "分销管理/删除推广者", businessType = BusinessType.DELETE, isSaveRequestData = true)
	public Result<String> deleteDistributesById(@PathVariable Long id) {
		if (id == null || id < 1) {
			throw BusinessRuntimeException.getInstance("id不存在");
		}
		userDistributeMapper.deleteById(id);
		userDistributeEquipmentMapper.delete(Wrappers.lambdaQuery(UserDistributeEquipment.class)
				.eq(UserDistributeEquipment::getDistributeId, id));
		//删除对应的优惠码关联
		couponDistributePopularizeMapper.update(null, Wrappers.lambdaUpdate(CouponDistributePopularize.class)
				.set(CouponDistributePopularize::getDeleted, 0)
				.eq(CouponDistributePopularize::getDistributeId, id)
				.eq(CouponDistributePopularize::getDeleted, 1));
		return GatewayResponse.SUCCESS.newBuilder().toResult("删除成功");
	}

	/**
	 * 推广者编辑
	 */
	@PutMapping
	@SaCheckPermission("distribute:update")
	@Log(module = "分销管理/编辑推广者", businessType = BusinessType.PUT, isSaveRequestData = true)
	public Result<String> editDistribute(@RequestBody UserDistributeReq userDistributeReq) {
		distributeService.editDistribute(userDistributeReq);
		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑成功");
	}

	/**
	 * 固定推广者详情
	 */
	@GetMapping("/get/detail/{id}")
	public Result<UserDistributeRateDetailView> getDetailById(@PathVariable Long id) {
		UserDistributeRateDetailView rateDetailView = new UserDistributeRateDetailView();
		List<UserDistributeView> rates = beanSearcher.searchAll(UserDistributeView.class, MapUtils.builder()
				.put("dis_id", String.format(" and up.distribute_id = %s", id))
				.orderBy(UserDistributeView::getGoodsId).asc()
				.build());
		rateDetailView.setRates(rates);
		List<UserSkuDistributeView> skuRates = beanSearcher.searchAll(UserSkuDistributeView.class, MapUtils.builder()
				.put("dis_id", String.format(" and up.distribute_id = %s", id))
				.orderBy(UserSkuDistributeView::getGoodsId).asc()
				.build());
		rateDetailView.setSkuRates(skuRates);

		List<CouponDistributePopularizeDetailView> distributePopularizes = beanSearcher.searchAll(CouponDistributePopularizeDetailView.class, MapUtils.builder()
				.field(CouponDistributePopularizeDetailView::getDistributeId, id)
				.build());
		rateDetailView.setCouponRelates(distributePopularizes);

		List<UserDistributeTargetAlert> targets = targetAlertMapper.selectList(Wrappers.lambdaQuery(UserDistributeTargetAlert.class)
				.eq(UserDistributeTargetAlert::getDistributeId, id));
		rateDetailView.setTargets(targets);
		rateDetailView.setEpRate(userDistributeEquipmentMapper.selectOne(Wrappers.lambdaQuery(UserDistributeEquipment.class)
				.eq(UserDistributeEquipment::getDistributeId, id).last("limit 1")));

		rateDetailView.setUserDistributeSub(beanSearcher.searchFirst(UserDistributeSub.class, MapUtils.builder()
				.field(UserDistributeSub::getSubDistributeId, id)
				.build()));
		return GatewayResponse.SUCCESS.newBuilder().toResult(rateDetailView);
	}

	/**
	 * 下级渠道
	 */
	@GetMapping("/get/sub/{distributeId}")
	public Result<SearchResult<UserDistributeSub>> getSub(@PathVariable Long distributeId) {
		SearchResult<UserDistributeSub> search = beanSearcher.search(UserDistributeSub.class, MapUtils.flatBuilder(request.getParameterMap())
				.field(UserDistributeSub::getDistributeId, distributeId)
				.orderBy(UserDistributeSub::getCreatedTime).desc()
				.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 删除下级渠道
	 */
	@DeleteMapping("/delete/sub/{id}")
	public Result<String> deleteSubById(@PathVariable Long id) {
		userDistributeSubMapper.deleteById(id);
		return GatewayResponse.SUCCESS.newBuilder().toResult("删除成功");

	}

	/**
	 * 固定渠道平台分销详情 趋势图
	 * chain 默认1日 2周 3月
	 */
	@GetMapping("/get/distribute/plat/brokenLine/{sharedId}")
	public Result<BrokenLineObjView> getDsPlatBrokenLine(@PathVariable Long sharedId, Long firstDate, Long lastDate, @RequestParam(defaultValue = "1") Integer chain) {
		String first = null;
		String end = null;
		if (firstDate != null) {
			if (chain == 2) {
				first = DateUtil.format(DateTime.of(firstDate), "yyyy.MM.dd");
			}else if (chain == 3) {
				first = DateUtil.format(DateTime.of(firstDate), "yyyy-MM");
			} else {
				first = DateUtil.format(DateTime.of(firstDate), "yyyy-MM-dd");
			}
		}
		if (lastDate != null) {
			if (chain == 2) {
				end = DateUtil.format(DateTime.of(lastDate), "yyyy.MM.dd");
			}else if (chain == 3) {
				end = DateUtil.format(DateTime.of(lastDate), "yyyy-MM");
			} else {
				end = DateUtil.format(DateTime.of(lastDate), "yyyy-MM-dd");
			}
		}
		BrokenLineObjView brokenLineObjView = Optional.ofNullable(orderDonMapper.selectDsPlatBrokenLineMoney(sharedId, first, end))
				.orElse(new BrokenLineObjView());
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		String dateSqL = "date_format(ifnull(od.created_time,vod.created_time),'%Y-%m-%d')";
		if (chain == 2) {
			dateSqL = "DATE_FORMAT(ifnull(od.created_time,vod.created_time) - INTERVAL (DAYOFWEEK(ifnull(od.created_time,vod.created_time)) + 5) % 7 DAY, '%Y.%m.%d')";
		} else if (chain == 3) {
			dateSqL = "DATE_FORMAT(ifnull(od.created_time,vod.created_time), '%Y-%m')";
		}
		if (brokenLineObjView != null) {
			List<DistributePlatOrderDonBrokenLineView> views = beanSearcher.searchAll(DistributePlatOrderDonBrokenLineView.class, builder
					.put("date", dateSqL)
					.field(DistributePlatOrderDonBrokenLineView::getDate, first, end).op(Operator.Between)
					.put("sid", String.format("where shared_id = %s", sharedId))
					.orderBy(DistributePlatOrderDonBrokenLineView::getDate).asc()
					.build());
			Map<Long, List<DistributePlatOrderDonBrokenLineView>> goodsMap = views.stream().collect(Collectors.groupingBy(DistributePlatOrderDonBrokenLineView::getGoodsId));
			brokenLineObjView.setDsGoodsData(goodsMap);
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult(brokenLineObjView);
	}

	/**
	 * 固定推广者列表
	 */
	@GetMapping
	public Result<SearchResult<UserDistributeViews>> distributeList(String nickname, String showId, String startTime, String endTime, Boolean isSpecialEp) {
		long adminId = StpUtil.getLoginIdAsLong();
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		//是否是商务人员
		if (userBusinessRateService.isBusiness(adminId)) {
			builder.field(UserDistributeViews::getBusinessId, adminId);
		}
		if (StrUtil.isNotBlank(showId)) {
			builder.field(UserDistributeViews::getUserId, userMapper.getUserIdByShowId(showId));
		}
		if (StrUtil.isNotBlank(nickname)) {
			List<Long> userIds = userMapper.selectListByNickname(nickname);
			if (CollUtil.isNotEmpty(userIds)) {
				builder.field(UserDistributeViews::getUserId, userIds).op(Operator.InList);
			}
		}
		String timeSql = StrUtil.EMPTY;
		if (StrUtil.isNotBlank(startTime)) {
			timeSql += String.format("and od.created_time >= '%s'", startTime);
		}
		if (StrUtil.isNotBlank(endTime)) {
			timeSql += String.format("and od.created_time < '%s'", endTime);
		}
		if (StrUtil.isNotBlank(timeSql)) {
			builder.put("time", timeSql);
			//按时间筛选 固定推广人分销情况 倒序
			builder.orderBy(UserDistributeViews::getDistributeOrdersMoney).desc();
		}
		if (isSpecialEp != null) {
			//是否是特殊设备分销渠道商
			String condition = String.format(" and %s (select 1 from user_distribute_equipment up where up.distribute_id = ud.id limit 1)", isSpecialEp ? "exists" : "not exists");
			builder.put("condition", condition);
		}
		Map<Long, String> businessNameMap = new ConcurrentHashMap<>();
		SearchResult<UserDistributeViews> search = beanSearcher.search(UserDistributeViews.class,
				builder.build());
		search.getDataList().forEach(view -> {
			if (view.getDistributeOrdersMoney().compareTo(BigDecimal.ZERO) > 0) {
				Optional.ofNullable(userDistributeMapper.selectSoldMaxGoods(view.getUserId())).ifPresent(title -> view.setGoodsTitle(title));
			}
			String businessName = businessNameMap.get(view.getBusinessId());
			view.setBusinessName(businessName);
			if (StrUtil.isEmpty(businessName)) {
				Optional.ofNullable(cmsUserMapper.selectById(view.getBusinessId()))
						.ifPresent(cmsUser -> {
							businessNameMap.putIfAbsent(view.getBusinessId(), cmsUser.getNickname());
							view.setBusinessName(cmsUser.getNickname());
						});
			}
			Optional.ofNullable(userMapper.selectById(view.getUserId()))
					.ifPresent(user -> view.setNickname(user.getNickname()));
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 渠道推广者查询列表
	 */
	@GetMapping("/search")
	public Result<SearchResult<DistributeSearchView>> searchDistribute() {
		SearchResult<DistributeSearchView> search = beanSearcher.search(DistributeSearchView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 所有固定推广者列表
	 */
	@GetMapping("/get/all")
	public Result<List<UserDistributeVo>> getAllDistributes() {
		List<UserDistributeVo> userDistributes = beanSearcher.searchAll(UserDistributeVo.class, MapUtils.flatBuilder(request.getParameterMap())
				.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(userDistributes);
	}

	/**
	 * 获取平台分销比例
	 */
	@GetMapping("/get/plat")
	public Result<List<GoodsDon>> getGoodsDistributeRate() {
		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsDonMapper.selectList(Wrappers.lambdaQuery(GoodsDon.class).in(GoodsDon::getType, Constant.dsGoodsIds).eq(GoodsDon::getDeleted, true)
				.eq(GoodsDon::getStatus, true).orderByAsc(GoodsDon::getType)
				.eq(GoodsDon::getIsDistribute, true)
				.orderByAsc(GoodsDon::getId)
				.select(GoodsDon::getId, GoodsDon::getType, GoodsDon::getTitle, GoodsDon::getRate, GoodsDon::getSecondRate)));
	}

	/**
	 * 平台开启规格分销
	 */
	@GetMapping("/get/sku/rate")
	public Result<List<GoodsDonSkuRateView>> getSkuRate() {
		List<GoodsDonSkuRateView> goodsDonSkuRateViews = beanSearcher.searchAll(GoodsDonSkuRateView.class, MapUtils.flatBuilder(request.getParameterMap())
				.orderBy(GoodsDonSkuRateView::getGoodsId).asc()
				.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsDonSkuRateViews);
	}

	/**
	 * 设置普通分销平台规格比例
	 */
	@PutMapping("/set/common/sku/rate")
	public Result<String> setDistributeCommonSkuRate(@RequestBody List<DistributeGeneralSkuRate> skuRates) {
		distributeService.setDistributeCommonSkuRate(skuRates);
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 获取推广者分销订单详情
	 */
	@GetMapping("/get/distribute/order/detail")
	public Result<SearchResult<DistributeOrdersDetailView>> getDistributeOrderDetail() {
		SearchResult<DistributeOrdersDetailView> search = beanSearcher.search(DistributeOrdersDetailView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 新注册分销人数
	 */
	@GetMapping("/get/register/distribute/user")
	public Result<SearchResult<RegisterDistributeOrdersView>> getRegisterDistributeUserDetail() {
		SearchResult<RegisterDistributeOrdersView> search = beanSearcher.search(RegisterDistributeOrdersView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
		search.getDataList().forEach(data -> {
			List<RegisterDistributeOrdersDetailView> ordersDetailViewList = beanSearcher.searchAll(RegisterDistributeOrdersDetailView.class, MapUtils.flatBuilder(request.getParameterMap()).field(RegisterDistributeOrdersDetailView::getUserId, data.getUserId()).op(Operator.Equal).build());
			data.setOrderNums(ordersDetailViewList.size());
			Optional<BigDecimal> money = ordersDetailViewList.stream().filter(order -> {
				if (!Constant.noOrderAllStatus.contains(order.getStatus().name())) {
					return true;
				}
				return false;
			}).map(RegisterDistributeOrdersDetailView::getMoney).reduce(BigDecimal::add);
			data.setMoney(money.isPresent() ? money.get() : BigDecimal.ZERO);
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 获取新注册的分销用户订单数据
	 */
	@GetMapping("/get/register/distribute/user/order/detail")
	public Result<SearchResult<RegisterDistributeOrdersDetailView>> getRegisterDistributeOrderDetail() {
		SearchResult<RegisterDistributeOrdersDetailView> search = beanSearcher.search(RegisterDistributeOrdersDetailView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
		search.getDataList().forEach(data -> {
			User user = userMapper.selectById(data.getUserId());
			if (data.getSkuId() != null) {
				GoodsDonSku sku = goodsDonSkuMapper.selectById(data.getSkuId());
				data.setSpecVal(sku != null ? sku.getSpecVal() : "");
			}
			data.setNickname(user != null ? user.getNickname() : "");
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 平台分销比例修改
	 */
	@PutMapping("/put/goods/rate")
	@Log(module = "分销管理/修改平台分销比例", businessType = BusinessType.PUT, isSaveRequestData = true)
	public Result<String> editGoodsDistributeRate(@RequestBody UserDistributeReq userDistributeReq) {
		for (UserPlatDistributeRate rate : userDistributeReq.getRates()) {
			if (rate.getRate() == null) {
				rate.setRate(0);
			}
			if (rate.getSecondRate() == null) {
				rate.setSecondRate(0);
			}
			if (rate.getRate() < 0 || rate.getRate() > 100) {
				throw new BusinessRuntimeException("比例错误");
			}
			GoodsDon goodsDon = goodsDonMapper.selectById(rate.getGoodsId());
			if (goodsDon == null || goodsDon.getType() == 3) {
				throw new BusinessRuntimeException("平台错误");
			}
			goodsDon.setRate(rate.getRate());
			goodsDon.setSecondRate(rate.getSecondRate());
			goodsDonMapper.updateById(goodsDon);
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑成功");
	}

	/**
	 * 提现title
	 */
	@GetMapping("/get/applyMoney/title")
	public Result<MoneyApplyView> applyMoneyTitle() {
		MoneyApplyView moneyApplyView = new MoneyApplyView();
		moneyApplyView.setThreshold(distributePointsExchangeMoneyMapper.selectOne(null));
		List<DistributeMoneyApply> distributeMoneyApplies = distributeMoneyApplyMapper.selectList(Wrappers.lambdaQuery(DistributeMoneyApply.class).eq(DistributeMoneyApply::getVerifyStatus, DistributeMoneyApply.Status.success).select(DistributeMoneyApply::getMoney));
		Optional<BigDecimal> reduce = distributeMoneyApplies.stream().map(DistributeMoneyApply::getMoney).reduce(BigDecimal::add);
		moneyApplyView.setGotMoney(reduce.isPresent() ? reduce.get() : BigDecimal.ZERO);
		return GatewayResponse.SUCCESS.newBuilder().toResult(moneyApplyView);
	}

	/**
	 * 提现列表
	 */
	@GetMapping("/get/applyMoney/list")
	@SaCheckPermission("distribute:applyView")
	public Result<SearchResult<DistributeMoneyApplyView>> applyMoneyList() {
		SearchResult<DistributeMoneyApplyView> search = beanSearcher.search(DistributeMoneyApplyView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 提现审核
	 */
	@PutMapping("/verify/applyMoney")
	public Result<String> verifyApplyMoney(@RequestBody @Validated DistributeApplyMoneyReq distributeApplyMoneyReq) {
		DistributeMoneyApply.Status status = DistributeMoneyApply.Status.checkStatus(distributeApplyMoneyReq.getVerifyStatus());
		if (status == null || status == DistributeMoneyApply.Status.verifying) {
			throw BusinessRuntimeException.getInstance("审核状态错误");
		}
		DistributeMoneyApply distributeMoneyApply = distributeMoneyApplyMapper.selectById(distributeApplyMoneyReq.getId());
		if (distributeMoneyApply == null) {
			throw BusinessRuntimeException.getInstance("提现记录不存在");
		}
		if (distributeMoneyApply.getVerifyStatus() != DistributeMoneyApply.Status.verifying) {
			throw BusinessRuntimeException.getInstance("该提现记录已处理,无法再进行审核");
		}
		distributeMoneyApply.setVerifyStatus(status);
		if (DistributeMoneyApply.Status.fail.name().equals(distributeApplyMoneyReq.getVerifyStatus()) && StrUtil.isEmpty(distributeApplyMoneyReq.getReason())) {
			throw BusinessRuntimeException.getInstance("拒绝原因为空");
		}
		if (DistributeMoneyApply.Status.fail.name().equals(distributeApplyMoneyReq.getVerifyStatus())) {
			distributeMoneyApply.setReason(distributeApplyMoneyReq.getReason());
			Long userId = distributeMoneyApply.getUserId();
			userBenefitsService.addDistributePoints(userId, distributeMoneyApply.getPoints());
			log.info("归还积分:{}至用户{}结束", distributeMoneyApply.getPoints(), userId);
			//记录返现明细
			userDistributeReturnMoneyDetailService.recordDistributeReturnMoney(distributeMoneyApply.getUserId(), distributeMoneyApply.getMoney(), "提现失败");
		}
		if (DistributeMoneyApply.Status.success.name().equals(distributeApplyMoneyReq.getVerifyStatus())) {
//			if (StrUtil.isBlank(distributeApplyMoneyReq.getImg())) {
//				throw BusinessRuntimeException.getInstance("审核成功时,打款图片不存在");
//			}
			distributeMoneyApply.setImg(distributeApplyMoneyReq.getImg());
		}
		distributeMoneyApplyMapper.updateById(distributeMoneyApply);

		if (distributeMoneyApply.getVerifyStatus() == DistributeMoneyApply.Status.fail) {
			String key = String.format(RedisService.key.APPLY_MONEY_DAY_LIMIT_KEY.getName(), distributeMoneyApply.getUserId().toString(), DistributeMoneyApply.MType.ds.name(), distributeMoneyApply.getUserId());
			redisService.del(key);
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult("审核操作成功");
	}

	/**
	 * 审核成功,编辑打款截图
	 */
	@PutMapping("/verify/applyMoney/img")
	public Result<String> putApplyMoneyImg(@RequestBody @Validated DistributeApplyMoneyReq distributeApplyMoneyReq) {
		DistributeMoneyApply entity = distributeMoneyApplyMapper.selectById(distributeApplyMoneyReq.getId());
		if (entity == null || entity.getVerifyStatus() != DistributeMoneyApply.Status.success) {
			throw BusinessRuntimeException.getInstance("审核记录错误");
		}
//		if (StrUtil.isBlank(distributeApplyMoneyReq.getImg())) {
//			throw BusinessRuntimeException.getInstance("打款截图为空");
//		}
		DistributeMoneyApply apply = new DistributeMoneyApply();
		apply.setImg(distributeApplyMoneyReq.getImg());
		apply.setId(distributeApplyMoneyReq.getId());
		distributeMoneyApplyMapper.updateById(apply);
		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑成功");
	}

	/**
	 * 获取分销head
	 */
	@GetMapping("/get/headData")
	public Result<BackgroundDataView> getDistributeHeadData(Long startTime, Long endTime) {
		BackgroundDataView backgroundDataView = new BackgroundDataView();
		Date startDate = null;
		Date endDate = null;
		if (startTime != null) {
			startDate = DateUtil.date(startTime);
		}
		if (endTime != null) {
			endDate = DateUtil.date(endTime);
		}
		//分销金额数据统计
		statisticsDataService.distribute(backgroundDataView, startDate, endDate);
		return GatewayResponse.SUCCESS.newBuilder().toResult(backgroundDataView);
	}

	/**
	 * 实物设备分销邀请新用户人数
	 */
	@GetMapping("/get/equipment/distribute/newUser")
	public Result<Integer> getEquipmentDistributeNewUser() {
		Number number = beanSearcher.searchCount(EquipmentDistributeNewUserView.class, MapUtils.builder()
				.field(EquipmentDistributeNewUserView::getIsNewUser, true)
				.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(number.intValue());
	}

	/**
	 * 绑定固定分销者的商务人员详情
	 */
	@GetMapping("/get/business/list")
	public Result<SearchResult<DistributeBusinessView>> getDistributeBusinessView() {
		long adminId = StpUtil.getLoginIdAsLong();
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		DateTime beginOfMonth = DateUtil.beginOfMonth(DateTime.now());
		String thisMonth = beginOfMonth.toString("yyyy-MM");
		//是否是商务人员
		if (userBusinessRateService.isBusiness(adminId)) {
			builder.field(DistributeBusinessView::getBusinessId, adminId);
		}
		builder.put("time", String.format("date_format(ubr.order_created_time,'%%Y-%%m') = '%s'", thisMonth));
		SearchResult<DistributeBusinessView> search = beanSearcher.search(DistributeBusinessView.class, builder.build());
		search.getDataList().forEach(data -> {
			Number numOfRelation = beanSearcher.searchCount(UserDistribute.class, MapUtils.builder().field(UserDistribute::getBusinessId, data.getBusinessId()).field(UserDistribute::getDeleted, true).build());
			data.setNumOfRelation(numOfRelation.intValue());
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 商务人员列表
	 */
	@GetMapping("/get/businessList")
	public Result<List<DistributeBusinessListVo>> getBusinessList() {
		long adminId = StpUtil.getLoginIdAsLong();
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		//是否是商务人员
		if (userBusinessRateService.isBusiness(adminId)) {
			builder.field(DistributeBusinessListVo::getBusinessId, adminId);
		}
		List<DistributeBusinessListVo> list = beanSearcher.searchAll(DistributeBusinessListVo.class, builder.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(list);
	}

	/**
	 * 商务人员提成详情
	 */
	@GetMapping("/get/takeMoney/detail")
	public Result<SearchResult<BusinessTakeMoneyDetail>> getTakeMoneyDetail(String firstMonthDate, String secondMonthDate) {
		long adminId = StpUtil.getLoginIdAsLong();
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		//是否是商务人员
		if (userBusinessRateService.isBusiness(adminId)) {
			builder.field(BusinessTakeMoneyDetail::getBusinessId, adminId);
		}
		String timeSql = StringUtil.EMPTY;
		if (StrUtil.isNotBlank(firstMonthDate)) {
			timeSql += String.format("date_format(ubr.order_created_time,'%%Y-%%m') >= '%s'", firstMonthDate);
		}
		if (StrUtil.isNotBlank(secondMonthDate)) {
			timeSql += String.format("and date_format(ubr.order_created_time,'%%Y-%%m') <= '%s'", secondMonthDate);
		}
		if (StrUtil.isNotBlank(timeSql)) {
			builder.put("time", timeSql);
		}
		SearchResult<BusinessTakeMoneyDetail> search = beanSearcher.search(BusinessTakeMoneyDetail.class, builder.build());
		search.getDataList().forEach(data -> {
			User user = userMapper.selectById(data.getUserId());
			Optional.ofNullable(user).ifPresent(u -> {
				data.setNickname(u.getNickname());
				data.setCreatedTime(u.getCreatedTime());
			});
			CmsUser business = cmsUserMapper.selectById(data.getBusinessId());
			Optional.ofNullable(business).ifPresent(bs -> data.setBusinessName(bs.getNickname()));
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 商务提成head
	 */
	@GetMapping("/get/business/headData")
	public Result<BusinessTakeMoneyHeadView> getTakeMoneyHeadDetail(String firstMonthDate, String secondMonthDate) {
		long adminId = StpUtil.getLoginIdAsLong();
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		//是否是商务人员
		if (userBusinessRateService.isBusiness(adminId)) {
			builder.field(BusinessTakeMoneyHeadView::getBusinessId, adminId);
		}
		String timeSql = StringUtil.EMPTY;
		if (StrUtil.isNotBlank(firstMonthDate)) {
			timeSql += String.format("date_format(ubr.order_created_time,'%%Y-%%m') >= '%s'", firstMonthDate);
		}
		if (StrUtil.isNotBlank(secondMonthDate)) {
			timeSql += String.format("and date_format(ubr.order_created_time,'%%Y-%%m') <= '%s'", secondMonthDate);
		}
		if (StrUtil.isNotBlank(timeSql)) {
			builder.put("time", timeSql);
		}
		BusinessTakeMoneyHeadView headView = beanSearcher.searchFirst(BusinessTakeMoneyHeadView.class, builder.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(headView);
	}

	/**
	 * 查看商务人员提成比例
	 */
	@GetMapping("/get/business/rate")
	public Result<List<UserDistributeBusinessRateRecordView>> getUserDistributeBusinessRateDetail(Long businessId, Integer type) {
		if (type == null) type = 1;
		List<UserDistributeBusinessRateRecordView> userDistributeBusinessRate = beanSearcher.searchAll(UserDistributeBusinessRateRecordView.class, MapUtils.builder()
				.put("business_id", String.format(" and ur.business_id = %s", businessId))
				.field(UserDistributeBusinessRateRecordView::getType, type)
				.orderBy(UserDistributeBusinessRateRecordView::getGoodsId).asc()
				.orderBy(UserDistributeBusinessRateRecordView::getSkuId).asc()
				.build());
		userDistributeBusinessRate.forEach(data -> {
			data.setBusinessId(businessId);
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(userDistributeBusinessRate);
	}

	/**
	 * 修改商务人员提成比例
	 */
	@PutMapping("/put/business/rate")
	@Log(module = "分销管理/修改商务人员比例", businessType = BusinessType.PUT, isSaveRequestData = true)
	public Result<String> updateBusinessRate(@RequestBody @Validated List<UserDistributeBusinessRate> rates) {
		List<Long> newDsSkuIds = new ArrayList<>();
		rates.forEach(userDistributeBusinessRate -> {
			Long rateId = userDistributeBusinessRate.getId();
			UserDistributeBusinessRate businessRate = Optional.ofNullable(userDistributeBusinessRateMapper.selectById(rateId)).orElse(new UserDistributeBusinessRate());
			BeanUtil.copyProperties(userDistributeBusinessRate, businessRate);
			Number number = beanSearcher.searchCount(GoodsDonSkuView.class, MapUtils.builder()
					.field(GoodsDonSkuView::getGoodsId, userDistributeBusinessRate.getGoodsId())
					.field(GoodsDonSkuView::getSkuId, userDistributeBusinessRate.getSkuId())
					.field(GoodsDonSkuView::getGoodsDonDeleted, true)
					.build());
			if (number.intValue() == 0) {
				userDistributeBusinessRateMapper.delete(Wrappers.lambdaQuery(UserDistributeBusinessRate.class)
						.eq(UserDistributeBusinessRate::getBusinessId, userDistributeBusinessRate.getBusinessId())
						.eq(UserDistributeBusinessRate::getGoodsId, userDistributeBusinessRate.getGoodsId())
						.eq(UserDistributeBusinessRate::getSkuId, userDistributeBusinessRate.getSkuId()));
				return;
			}
			if (businessRate.getId() == null) {
				try {
					userDistributeBusinessRateMapper.insert(businessRate);

					newDsSkuIds.add(businessRate.getSkuId());
				} catch (DuplicateKeyException e) {
				}
			} else {
				userDistributeBusinessRateMapper.updateById(businessRate);
			}
		});

		if (CollUtil.isNotEmpty(newDsSkuIds)) {
			//删除存在告警的平台规格
			distributeGoodsSkuAlertMapper.delete(Wrappers.lambdaQuery(DistributeGoodsSkuAlert.class)
					.in(DistributeGoodsSkuAlert::getSkuId, newDsSkuIds));
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult("修改比例成功");
	}

	/**
	 * 商务默认分配平台比例
	 */
	@GetMapping("/get/defaultRateConfig")
	public Result<List<UserBusinessDefaultRateConfigView>> getDefaultRateConfig() {
		List<UserBusinessDefaultRateConfigView> search = beanSearcher.searchAll(UserBusinessDefaultRateConfigView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 编辑商务默认平台比例
	 */
	@PutMapping("/update/business/defaultRate")
	public Result<String> updateBusinessDefaultRate(@RequestBody List<UserBusinessDefaultRateConfig> configs) {
		configs.forEach(rateConfig -> {
			Long rateConfigId = rateConfig.getId();
			UserBusinessDefaultRateConfig config = Optional.ofNullable(defaultRateConfigMapper.selectById(rateConfigId)).orElse(new UserBusinessDefaultRateConfig());
			BeanUtil.copyProperties(rateConfig, config);
			Number number = beanSearcher.searchCount(GoodsDonSkuView.class, MapUtils.builder()
					.field(GoodsDonSkuView::getGoodsId, rateConfig.getGoodsId())
					.field(GoodsDonSkuView::getGoodsDonDeleted, true)
					.build());
			if (number.intValue() == 0) {
				defaultRateConfigMapper.delete(Wrappers.lambdaQuery(UserBusinessDefaultRateConfig.class)
						.eq(UserBusinessDefaultRateConfig::getGoodsId, rateConfig.getGoodsId()));
				return;
			}
			if (rateConfig.getId() == null) {
				try {
					defaultRateConfigMapper.insert(config);
					return;
				} catch (DuplicateKeyException e) {

				}
			}
			defaultRateConfigMapper.updateById(config);
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 商务人员推广平台分销比例默认配置列表
	 */
	@GetMapping("/get/business/distribute/rate")
	public Result<BusinessDistributeRateDetailView> getBusinessDistributeRateConfigList() {
		BusinessDistributeRateDetailView rateDetailView = new BusinessDistributeRateDetailView();
		List<BusinessDistributeRateView> rates = beanSearcher.searchAll(BusinessDistributeRateView.class,
				MapUtils.flatBuilder(request.getParameterMap())
						.build());
		rateDetailView.setRates(rates);
		List<BusinessDistributeSkuRateView> skuRates = beanSearcher.searchAll(BusinessDistributeSkuRateView.class,
				MapUtils.flatBuilder(request.getParameterMap())
						.build());
		rateDetailView.setSkuRates(skuRates);
		return GatewayResponse.SUCCESS.newBuilder().toResult(rateDetailView);
	}

	/**
	 * 编辑商务人员推广平台分销比例默认配置列表
	 */
	@PutMapping("/put/business/distribute/rate")
	@Transactional(rollbackFor = Throwable.class)
	public Result<String> updateBusinessDistributeRate(@RequestBody BusinessDistributeDefaultRateDetailReq req) {
		List<BusinessDistributeDefaultRateConfig> rates = req.getRates();
		List<BusinessDistributeDefaultSkuRateConfig> skuRates = req.getSkuRates();
		List<Long> alertGoodsId = new ArrayList<>();
		if (CollUtil.isNotEmpty(rates)) {
			rates.forEach(config -> {
				Long id = config.getId();
				Long goodsId = config.getGoodsId();
				if (config.getRate() == null) {
					config.setRate(0);
				}
				Integer rate = config.getRate();
				if (goodsId == null) {
					throw BusinessRuntimeException.getInstance("平台id为空");
				}
				if (rate < 0 && rate > 100) {
					throw BusinessRuntimeException.getInstance("请输入正确的比例");
				}
				if (id == null) {
					try {
						businessDefaultRateConfigMapper.insert(config);
						alertGoodsId.add(config.getGoodsId());
					} catch (DuplicateKeyException e) {
					}
				} else {
					businessDefaultRateConfigMapper.updateById(config);
				}
			});
		}

		//sku规格比例设置
		if (CollUtil.isNotEmpty(skuRates)) {
			List<Long> collect = skuRates.stream().map(BusinessDistributeDefaultSkuRateConfig::getSkuId).collect(Collectors.toList());
			if (CollUtil.isNotEmpty(collect)) {
				businessDistributeDefaultSkuRateConfigMapper.delete(Wrappers.lambdaQuery(BusinessDistributeDefaultSkuRateConfig.class)
						.notIn(BusinessDistributeDefaultSkuRateConfig::getSkuId, collect));
			}
			skuRates.forEach(config -> {
				if (config.getRate() == null) {
					config.setRate(0);
				}
				Integer rate = config.getRate();
				if (rate < 0 && rate > 100) {
					throw BusinessRuntimeException.getInstance("请输入正确的比例");
				}
				if (config.getId() == null) {
					try {
						businessDistributeDefaultSkuRateConfigMapper.insert(config);
						alertGoodsId.add(config.getGoodsId());
					} catch (DuplicateKeyException e) {
					}
				} else {
					businessDistributeDefaultSkuRateConfigMapper.updateById(config);
				}
			});
		}

		if (CollUtil.isNotEmpty(alertGoodsId)) {
			//删除存在告警的平台
			distributeGoodsSkuAlertMapper.delete(Wrappers.lambdaQuery(DistributeGoodsSkuAlert.class)
					.in(DistributeGoodsSkuAlert::getGoodsId, alertGoodsId));
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 商务人员数据表
	 */
	@GetMapping("/get/business/data")
	@SaCheckPermission("business:dataView")
	public Result<SearchResult<BusinessDistributesDataView>> getBusinessDistributesData(String startTime, String endTime) {
		long adminId = StpUtil.getLoginIdAsLong();
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		String time1Sql = StrUtil.EMPTY;
		String time2Sql = StrUtil.EMPTY;
		String time3Sql = StrUtil.EMPTY;
		if (StrUtil.isNotBlank(startTime)) {
			time1Sql += String.format(" and ud.business_bind_time >= '%s'", startTime);
			time2Sql += String.format(" and us.created_time >= '%s'", startTime);
			time3Sql += String.format(" and od.created_time >= '%s'", startTime);
		}
		if (StrUtil.isNotBlank(endTime)) {
			time1Sql += String.format(" and ud.business_bind_time < '%s'", endTime);
			time2Sql += String.format(" and us.created_time < '%s'", endTime);
			time3Sql += String.format(" and od.created_time < '%s'", endTime);
		}
		if (StrUtil.isNotBlank(time1Sql)) {
			builder.put("time1", time1Sql);
		}
		if (StrUtil.isNotBlank(time2Sql)) {
			builder.put("time2", time2Sql);
		}
		if (StrUtil.isNotBlank(time3Sql)) {
			builder.put("time3", time3Sql);
		}
		//是否是商务人员
		if (userBusinessRateService.isBusiness(adminId)) {
			builder.field(BusinessDistributesDataView::getBusinessId, adminId);
		}
		SearchResult<BusinessDistributesDataView> search = beanSearcher.search(BusinessDistributesDataView.class, builder.build());
		search.getDataList().forEach(data -> {
			Optional.ofNullable(cmsUserMapper.selectById(data.getBusinessId()))
					.ifPresent(cmsUser -> data.setBusinessName(cmsUser.getNickname()));

		});
//		search.getDataList().forEach(data -> {
//			Map<String, Object> reMap = orderDonMapper.selectNumOfDistributeOrders(data.getBusinessId(), startTime, endTime, Constant.noOrderAllStatus);
//			Object num = reMap.get("num");
//			Object money = reMap.get("money");
//			data.setNumOfDistributeOrders(Integer.parseInt(num.toString()));
//			data.setDistributeOrdersMoney(BigDecimal.valueOf(Long.valueOf(money.toString())));
//			Integer numOfNewUser = userDistributeSharedMapper.countByBusinessId(data.getBusinessId(), startTime, endTime);
//			data.setNumOfNewUser(numOfNewUser);
//		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 渠道积分提现详情
	 */
	@GetMapping("/get/apply/detail/{userId}")
	public Result<UserDistributeViews> getApplyDetail(@PathVariable Long userId) {
		UserDistributeViews userDistributeViews = userDistributeMapper.getApplyDetailByUserId(userId);
		return GatewayResponse.SUCCESS.newBuilder().toResult(userDistributeViews);
	}

	/**
	 * 获取渠道分销规则开启 状态
	 */
	@GetMapping("/get/rule/status")
	public Result<Boolean> getRuleStatus() {
		String ruleKey = Constant.DISTRIBUTE_RULE_KEY;
		SysConfig ruleConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
				.eq(SysConfig::getSysKey, ruleKey).last("limit 1"));
		if (ruleConfig == null) {
			ruleConfig = new SysConfig();
			ruleConfig.setSysKey(ruleKey);
			ruleConfig.setRemark("渠道分销规则key");
			//默认开启
			ruleConfig.setSysValue(Constant.ONE_STR);
			if (redisService.setNx(ruleKey, 1, 5l)) {
				sysConfigService.save(ruleConfig);
			}
		}
		if (StrUtil.equals(Constant.ONE_STR, ruleConfig.getSysValue())) {
			return GatewayResponse.SUCCESS.newBuilder().toResult(true);
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult(false);
	}

	/**
	 * 开启/关闭 渠道分销规则 默认开启
	 */
	@PutMapping("/update/status/rule")
	public Result<String> updateDsRuleStatus() {
		String ruleKey = Constant.DISTRIBUTE_RULE_KEY;
		SysConfig ruleConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
				.eq(SysConfig::getSysKey, ruleKey).last("limit 1"));
		if (ruleConfig == null) {
			throw BusinessRuntimeException.getInstance("渠道分销规则配置不存在");
		}
		if (Constant.ZERO_STR.equals(ruleConfig.getSysValue())) {
			ruleConfig.setSysValue(Constant.ONE_STR);
		} else {
			ruleConfig.setSysValue(Constant.ZERO_STR);
		}
		sysConfigService.saveOrUpdate(ruleConfig);
		//记录关闭打开状态
		//关闭 记录一次
		//距离上一次时间
		UserDistributeRuleOrderRecord userDistributeRuleOrderRecord = Optional.ofNullable(userDistributeRuleOrderRecordMapper.selectOne(Wrappers.lambdaQuery(UserDistributeRuleOrderRecord.class)
				.orderByDesc(UserDistributeRuleOrderRecord::getId).last("limit 1"))).orElse(new UserDistributeRuleOrderRecord());
		if (StrUtil.equals(Constant.ZERO_STR, ruleConfig.getSysValue())) {
			//距离上次关闭时间少于10分钟 不记录关闭时间
			if (userDistributeRuleOrderRecord.getId() == null) {
				if (redisService.setNx(RedisService.key.DISTRIBUTE_RULE_TIME_KEY.getName(), 1, RedisService.key.DISTRIBUTE_RULE_TIME_KEY.getTimeout())) {
					userDistributeRuleOrderRecord.setEndTime(DateTime.now());
					userDistributeRuleOrderRecordMapper.insert(userDistributeRuleOrderRecord);
				}
			} else {
				if (userDistributeRuleOrderRecord.getStartTime() != null) {
					Date startTime = userDistributeRuleOrderRecord.getStartTime();
					if (DateTime.now().isAfter(DateUtil.offsetMinute(startTime, 10))) {
						if (redisService.setNx(RedisService.key.DISTRIBUTE_RULE_TIME_KEY.getName(), 1, RedisService.key.DISTRIBUTE_RULE_TIME_KEY.getTimeout())) {
							UserDistributeRuleOrderRecord newRecord = new UserDistributeRuleOrderRecord();
							newRecord.setEndTime(DateTime.now());
							userDistributeRuleOrderRecordMapper.insert(newRecord);
						}
					}
				}
			}
		} else {
			if (userDistributeRuleOrderRecord.getId() != null && userDistributeRuleOrderRecord.getStartTime() == null) {
				if (DateTime.now().isAfter(DateUtil.offsetMinute(userDistributeRuleOrderRecord.getEndTime(), 10))) {
					userDistributeRuleOrderRecord.setStartTime(DateTime.now());
					userDistributeRuleOrderRecord.setDuration(DateUtil.formatBetween(userDistributeRuleOrderRecord.getEndTime(), userDistributeRuleOrderRecord.getStartTime(), BetweenFormater.Level.SECOND));
					userDistributeRuleOrderRecordMapper.updateById(userDistributeRuleOrderRecord);
				}
			}
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 渠道分销规则列表
	 */
	@GetMapping("/get/rule/list")
	public Result<SearchResult<UserDistributeRuleOrderRecordView>> getDistributeRuleList() {
		SearchResult<UserDistributeRuleOrderRecordView> search = beanSearcher.search(UserDistributeRuleOrderRecordView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
		search.getDataList().forEach(data -> {
			Date endTime = data.getEndTime();
			Date startTime = data.getStartTime();
			String time = StrUtil.EMPTY;
			if (endTime != null) {
				time = String.format("created_time >= '%s'", DateUtil.format(endTime, "yyyy-MM-dd HH:mm:ss"));
			}
			if (startTime != null) {
				if (StrUtil.isNotBlank(time)) {
					time += " and ";
				}
				time += String.format("created_time < '%s'", DateUtil.format(startTime, "yyyy-MM-dd HH:mm:ss"));
			}
			String condition = "where is_rule is true";
			if (StrUtil.isNotBlank(time)) {
				condition += String.format(" and %s", time);
			}
			DistributeWaitingOrderPointsRuleView ruleView = beanSearcher.searchFirst(DistributeWaitingOrderPointsRuleView.class, MapUtils.builder()
					.put("condition", condition).build());
			data.setNumOfOrder(ruleView.getNumOfOrder());
			data.setOrderAmount(ruleView.getOrderAmount() == null ? BigDecimal.ZERO : ruleView.getOrderAmount());
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 商务分销当月渠道商以及历史渠道商在当月的数据
	 */
	@GetMapping("/get/business/distribute/monthlyData")
	public Result<List<BusinessDistributesMonthlyDataView>> getBusinessMonthlyData(String firstMonthDate, String secondMonthDate) {
		long adminId = StpUtil.getLoginIdAsLong();
		if (StrUtil.isEmpty(firstMonthDate)) {
			firstMonthDate = DateUtil.beginOfMonth(DateTime.now()).toDateStr();
		}
		if (StrUtil.isEmpty(secondMonthDate)) {
			secondMonthDate = DateUtil.offsetMonth(DateUtil.beginOfMonth(DateTime.now()), 1).toDateStr();
		}
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		//是否是商务人员
		Boolean isBusiness = userBusinessRateService.isBusiness(adminId);
		if (isBusiness) {
			builder.field(BusinessDistributesMonthlyDataView::getBusinessId, adminId);
		}
		builder.put("n", "(select nickname from cms_user where id = ur.business_id limit 1)");
		//当月渠道本月数据
		String time1Sql = StrUtil.EMPTY;
		String time2Sql = StrUtil.EMPTY;
		String time3Sql = StrUtil.EMPTY;
		if (StrUtil.isNotBlank(firstMonthDate)) {
			time1Sql += String.format(" and ud.business_bind_time >= '%s'", firstMonthDate);
			time2Sql += String.format(" and us.created_time >= '%s'", firstMonthDate);
			time3Sql += String.format(" and od.created_time >= '%s'", firstMonthDate);
		}
		if (StrUtil.isNotBlank(secondMonthDate)) {
			time1Sql += String.format(" and ud.business_bind_time < '%s'", secondMonthDate);
			time2Sql += String.format(" and us.created_time < '%s'", secondMonthDate);
			time3Sql += String.format(" and od.created_time < '%s'", secondMonthDate);
		}
		if (StrUtil.isNotBlank(time1Sql)) {
			builder.put("time1", time1Sql);
		}
		if (StrUtil.isNotBlank(time2Sql)) {
			builder.put("time2", time2Sql);
		}
		if (StrUtil.isNotBlank(time3Sql)) {
			builder.put("time3", time3Sql);
		}
		builder.put("type", 1);
		builder.put("sorted", 0);
		List<BusinessDistributesMonthlyDataView> search = beanSearcher.searchAll(BusinessDistributesMonthlyDataView.class, builder.build());
		//历史渠道 当月数据
		time1Sql = StrUtil.EMPTY;
		time2Sql = StrUtil.EMPTY;
		time3Sql = StrUtil.EMPTY;
		if (StrUtil.isNotBlank(firstMonthDate)) {
			time1Sql += String.format(" and ud.business_bind_time < '%s'", firstMonthDate);
			time2Sql += String.format(" and us.created_time >= '%s'", firstMonthDate);
			time3Sql += String.format(" and od.created_time >= '%s'", firstMonthDate);
		}
		if (StrUtil.isNotBlank(secondMonthDate)) {
			time2Sql += String.format(" and us.created_time < '%s'", secondMonthDate);
			time3Sql += String.format(" and od.created_time < '%s'", secondMonthDate);
		}
		if (StrUtil.isNotBlank(time1Sql)) {
			builder.put("time1", time1Sql);
		}
		if (StrUtil.isNotBlank(time2Sql)) {
			builder.put("time2", time2Sql);
		}
		if (StrUtil.isNotBlank(time3Sql)) {
			builder.put("time3", time3Sql);
		}
		builder.put("type", 2);
		builder.put("sorted", 99);

		List<BusinessDistributesMonthlyDataView> search2 = beanSearcher.searchAll(BusinessDistributesMonthlyDataView.class, builder.build());

		time1Sql = StrUtil.EMPTY;
		time2Sql = StrUtil.EMPTY;
		time3Sql = StrUtil.EMPTY;
		if (StrUtil.isNotBlank(firstMonthDate)) {
			time1Sql += String.format(" and ud.business_bind_time between '%s' and '%s'", DateUtil.offsetMonth(DateUtil.parse(firstMonthDate, "yyyy-MM-dd"), -1), firstMonthDate);
			time2Sql += String.format(" and us.created_time >= '%s'", firstMonthDate);
			time3Sql += String.format(" and od.created_time >= '%s'", firstMonthDate);
		}
		if (StrUtil.isNotBlank(secondMonthDate)) {
			time2Sql += String.format(" and us.created_time < '%s'", secondMonthDate);
			time3Sql += String.format(" and od.created_time < '%s'", secondMonthDate);
		}
		if (StrUtil.isNotBlank(time1Sql)) {
			builder.put("time1", time1Sql);
		}
		if (StrUtil.isNotBlank(time2Sql)) {
			builder.put("time2", time2Sql);
		}
		if (StrUtil.isNotBlank(time3Sql)) {
			builder.put("time3", time3Sql);
		}
		builder.put("type", 3);
		builder.put("sorted", 1);
		//上个月渠道在本月历史数据
		List<BusinessDistributesMonthlyDataView> search3 = beanSearcher.searchAll(BusinessDistributesMonthlyDataView.class, builder.build());

		Collection<BusinessDistributesMonthlyDataView> businessDistributesDataViews = CollUtil.addAll(search, search2);
		businessDistributesDataViews = CollUtil.addAll(businessDistributesDataViews, search3);
		List<BusinessDistributesMonthlyDataView> collect = businessDistributesDataViews.stream().sorted(Comparator.comparing(BusinessDistributesMonthlyDataView::getBusinessId).thenComparing(BusinessDistributesMonthlyDataView::getSorted)).collect(Collectors.toList());
		return GatewayResponse.SUCCESS.newBuilder().toResult(collect);
	}

	/**
	 * 针对商务
	 * 获取商务 分销平台通用比例
	 */
	@GetMapping("/get/business/general/rate")
	public Result<List<UserDistributeBusinessGeneralRateView>> getBusinessGeneralRate(@RequestParam(defaultValue = "1") Integer type) {
		List<UserDistributeBusinessGeneralRateView> userDistributeBusinessGeneralRateViews = beanSearcher.searchAll(UserDistributeBusinessGeneralRateView.class, MapUtils.flatBuilder(request.getParameterMap())
				.field(UserDistributeBusinessGeneralRateView::getType, type).build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(userDistributeBusinessGeneralRateViews);
	}

	/**
	 * 编辑商务 分销平台通用比例
	 * 商务的平台规格提成 根据这个改变
	 */
	@PutMapping("/put/business/general/rate")
	@Transactional(rollbackFor = Throwable.class)
	public Result<String> updateBusinessGeneralRate(@RequestBody List<UserDistributeBusinessGeneralRate> generalRates) {
		List<CmsUserVO> userVOS = beanSearcher.searchAll(CmsUserVO.class, MapUtils.builder().field(CmsUserVO::getRoleNames, "商务").op(Operator.Contain).build());
		List<Long> collect = userVOS.stream().map(CmsUserVO::getId).collect(Collectors.toList());
		final List<Long> businessIds = collect;
		List<Long> newDsSkuIds = new ArrayList<>();
		generalRates.forEach(data -> {
			if (data.getId() == null) {
				try {
					//新增
					UserDistributeBusinessGeneralRate businessGeneralRate = new UserDistributeBusinessGeneralRate();
					if (data.getGoodsId() == null || data.getSkuId() == null) {
						throw BusinessRuntimeException.getInstance("缺少必要参数");
					}
					businessGeneralRate.setGoodsId(data.getGoodsId());
					businessGeneralRate.setSkuId(data.getSkuId());
					Integer firstOrderRate = Optional.ofNullable(data.getFirstOrderRate()).orElse(0);
					businessGeneralRate.setFirstOrderRate(firstOrderRate);
					Integer renewOrderRate = Optional.ofNullable(data.getRenewOrderRate()).orElse(0);
					businessGeneralRate.setRenewOrderRate(renewOrderRate);
					businessGeneralRateMapper.insert(businessGeneralRate);
					if (CollUtil.isNotEmpty(businessIds)) {
						userDistributeBusinessRateMapper.insertOrUpdateBusinessGoodsSkuRate(businessIds, data.getGoodsId(), data.getSkuId(), firstOrderRate, renewOrderRate);
					}
					newDsSkuIds.add(data.getSkuId());
				} catch (DuplicateKeyException e) {
				}
				return;
			}
			UserDistributeBusinessGeneralRate dbGeneralRate = businessGeneralRateMapper.selectById(data.getId());
			if (dbGeneralRate != null) {
				Integer firstOrderRate_new = null;
				Integer renewOrderRate_new = null;
				AtomicBoolean is_change = new AtomicBoolean(false);
				//需要更新首单比例
				if (data.getFirstOrderRate() != null && dbGeneralRate.getFirstOrderRate() != data.getFirstOrderRate()) {
					firstOrderRate_new = data.getFirstOrderRate();
					is_change.set(true);
				}
				//需要更新续费比例
				if (data.getRenewOrderRate() != null && dbGeneralRate.getRenewOrderRate() != data.getRenewOrderRate()) {
					renewOrderRate_new = data.getRenewOrderRate();
					is_change.set(true);
				}
				if (is_change.get()) {
					businessGeneralRateMapper.updateById(data);
					newDsSkuIds.add(data.getSkuId());
					if (CollUtil.isNotEmpty(businessIds)) {
						//获取所有商务
						userDistributeBusinessRateMapper.insertOrUpdateBusinessGoodsSkuRate(businessIds, data.getGoodsId(), data.getSkuId(), firstOrderRate_new, renewOrderRate_new);
					}
				}
			}

			if (CollUtil.isNotEmpty(newDsSkuIds)) {
				//删除存在告警的平台规格
				distributeGoodsSkuAlertMapper.delete(Wrappers.lambdaQuery(DistributeGoodsSkuAlert.class)
						.in(DistributeGoodsSkuAlert::getSkuId, newDsSkuIds));
			}
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 是否有未配置比例的规格
	 */
	@GetMapping("/get/goodsSku/alert")
	public Result<Boolean> getGoodsSkuAlert() {
		Integer count = distributeGoodsSkuAlertMapper.selectCountByCondition();
		return GatewayResponse.SUCCESS.newBuilder().toResult(count > 0 ? true : false);
	}

	/**
	 * 渠道预警列表
	 */
	@GetMapping("/get/target/alert/list")
	public Result<SearchResult<UserDistributeTargetAlertView>> getTargetAlertList() {
		long adminId = StpUtil.getLoginIdAsLong();
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		//是否是商务人员
		if (userBusinessRateService.isBusiness(adminId)) {
			builder.field(UserDistributeTargetAlertView::getBusinessId, adminId);
		}
		SearchResult<UserDistributeTargetAlertView> search = beanSearcher.search(UserDistributeTargetAlertView.class, builder
				.orderBy(UserDistributeTargetAlertView::getId).desc()
				.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 跟进渠道预警
	 */
	@PutMapping("/update/target/alert/status/{id}")
	public Result<String> updateTargetAlertStatus(@PathVariable Long id) {
		UserDistributeTargetAlertRecord record = targetAlertRecordMapper.selectById(id);
		if (record != null && !record.getStatus()) {
			record.setStatus(true);
			targetAlertRecordMapper.updateById(record);
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 批量待解绑的用户渠道关联关系记录
	 */
	@PostMapping("/import/unbind/distribute/shared")
	public Result<String> unbindUserDistributeShared(MultipartFile file) throws Exception {
		if (!file.getOriginalFilename().contains(".xls")) {
			throw BusinessRuntimeException.getInstance("请导入excel文件");
		}
		List<Object> userBind = EasyExcel.read(file.getInputStream()).sheet().headRowNumber(0).doReadSync();
		distributeService.unbindUserDistributeShared(userBind);
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 解绑渠道关系下单金额，以及佣金
	 */
	@GetMapping("/get/unbind/orderMoney/detail")
	public Result<UserDistributeUnbindOrderMoneyView> getUnbindDistributeOrderMoneyDetail(String startTime, String endTime) {
		String timeSql = StrUtil.EMPTY;
		if (startTime != null) {
			timeSql += String.format(" and o.created_time >= '%s'", startTime);
		}
		if (endTime != null) {
			timeSql += String.format(" and o.created_time < '%s'", endTime);
		}
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		if (StrUtil.isNotEmpty(timeSql)) {
			builder.put("time", timeSql);
		}
		UserDistributeUnbindOrderMoneyView userDistributeUnbindOrderMoneyView = beanSearcher.searchFirst(UserDistributeUnbindOrderMoneyView.class, builder.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(userDistributeUnbindOrderMoneyView);
	}

	/**
	 * 新增分销渠道白名单
	 */
	@PostMapping("/post/white")
	@Log(module = "分销管理/渠道分销/新增渠道白名单", businessType = BusinessType.POST, isSaveRequestData = true)
	public Result<String> postDistributeWhite(@RequestBody UserDistributeSharedWhite sharedWhite) {
		if (sharedWhite.getUserId() == null) {
			throw BusinessRuntimeException.getInstance("请指定对应渠道用户");
		}
		UserDistributeSharedWhite userDistributeSharedWhite = userDistributeSharedWhiteMapper.selectOne(Wrappers.lambdaQuery(UserDistributeSharedWhite.class)
				.eq(UserDistributeSharedWhite::getUserId, sharedWhite.getUserId())
				.last("limit 1"));
		if (userDistributeSharedWhite != null) {
			throw BusinessRuntimeException.getInstance("已添加该渠道用户");
		}
		userDistributeSharedWhiteMapper.insert(sharedWhite);
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 删除渠道用户白名单
	 */
	@DeleteMapping("/del/white/{id}")
	@Log(module = "分销管理/渠道分销/删除渠道白名单", businessType = BusinessType.DELETE, isSaveRequestData = true)
	public Result<String> delDistributeWhite(@PathVariable Long id) {
		userDistributeSharedWhiteMapper.deleteById(id);
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 用户白名单列表
	 */
	@GetMapping("/get/white")
	public Result<SearchResult<UserDistributeSharedWhite>> getDistributeWhite() {
		SearchResult<UserDistributeSharedWhite> search = beanSearcher.search(UserDistributeSharedWhite.class, MapUtils.flatBuilder(request.getParameterMap()).build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 普通渠道列表
	 */
	@GetMapping("/get/common/distribute")
	public Result<SearchResult<UserCommonDistributeView>> getCommonDistribute(Long userId, String nickname) {
		String condition = StrUtil.EMPTY;
		if (userId != null) {
			condition += String.format(" and id = %s", userId);
		}
		if (StrUtil.isNotEmpty(nickname)) {
			condition += String.format(" and nickname like '%%%s%%'", nickname);
		}
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		if (StrUtil.isNotEmpty(condition)) {
			builder.put("condition", condition);
		}
		SearchResult<UserCommonDistributeView> search = beanSearcher.search(UserCommonDistributeView.class,
				builder.build());
		search.getDataList().forEach(view -> {
			if (view.getDistributeOrdersMoney().compareTo(BigDecimal.ZERO) > 0) {
				Optional.ofNullable(userDistributeMapper.selectSoldMaxGoods(view.getUserId())).ifPresent(title -> view.setGoodsTitle(title));
			}
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}
}