package com.cyksj.web.controller.manage;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.annotation.Log;
import com.cyksj.common.annotation.NoSubmit;
import com.cyksj.common.constant.Constant;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
import com.cyksj.common.util.IoKit;
import com.cyksj.common.util.Jsons;
import com.cyksj.common.util.Xmls;
import com.cyksj.dto.Result;
import com.cyksj.enums.BusinessType;
import com.cyksj.enums.GatewayApiCode;
import com.cyksj.enums.GatewayResponse;
import com.cyksj.mapper.*;
import com.cyksj.mapper.channel.ChannelPopularizeMapper;
import com.cyksj.mapper.channel.UserPayEquipmentAvailableBenefitsMapper;
import com.cyksj.mapper.channel.UserPayEquipmentReceiveBenefitsRecordMapper;
import com.cyksj.mapper.manage.RealGoodsOrderHandleMapper;
import com.cyksj.mapper.manage.cms.CmsUserMapper;
import com.cyksj.mapper.manage.coupon.CouponMapper;
import com.cyksj.mapper.shop.YhShopMapper;
import com.cyksj.model.dto.OriSkuDto;
import com.cyksj.model.dto.RenewOriOrderSkuDto;
import com.cyksj.model.entity.*;
import com.cyksj.model.excel.*;
import com.cyksj.model.manage.request.ReqSetLogisticsPost;
import com.cyksj.model.manage.views.AccountView;
import com.cyksj.model.manage.views.OrderDonBackView;
import com.cyksj.model.manage.views.UpgradeOrderDonBackView;
import com.cyksj.model.request.*;
import com.cyksj.model.views.*;
import com.cyksj.service.chatgpt.GptUserRechargeRecordService;
import com.cyksj.service.mange.CmsOrderDonService;
import com.cyksj.service.order.OrderDonCommentService;
import com.cyksj.service.user.UserBindRelationService;
import com.cyksj.service.user.UserService;
import com.cyksj.web.util.EasyExcelUtils;
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 com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author chan
 * @date 2021/10/12 下午11:05
 */
@Slf4j
@RequestMapping("/manage/order")
@RestController
@RequiredArgsConstructor
public class CmsOrderController {
    private final HttpServletRequest request;

    private final CmsOrderDonService cmsOrderDonService;

    private final UserService userService;

    private final BeanSearcher beanSearcher;

    private final RealGoodsInterestUserMapper realGoodsInterestUserMapper;

    private final RealGoodsOrderHandleMapper realGoodsOrderHandleMapper;

    private final CouponMapper couponMapper;

	private final OrderCommentMapper orderCommentMapper;

	private final OrderDonCommentService orderDonCommentService;

	private final GoodsDonSkuMapper skuMapper;

	private final ChannelPopularizeMapper channelPopularizeMapper;

	private final GroupsRelationMapper relationMapper;

	private final UserPayEquipmentReceiveBenefitsRecordMapper receiveBenefitsRecordMapper;

	private final UserPayEquipmentAvailableBenefitsMapper availableBenefitsMapper;

	private final YhShopMapper yhShopMapper;

	private final CmsUserMapper cmsUserMapper;

	private final UserMapper userMapper;

	private final OrderDonMapper orderDonMapper;

	private final OrderDonCustomerServiceRelateMapper orderDonCustomerServiceRelateMapper;

	private final MidjourneyUserConversationMapper midjourneyUserConversationMapper;

	private final MidjourneyUserMapper midjourneyUserMapper;

	private final UserBindRelationService userBindRelationService;

	private final OrderDonRenewRecordMapper orderDonRenewRecordMapper;

	private final ChatgptUserMapper chatgptUserMapper;

	private final UserBenefitsOrderRecordMapper userBenefitsOrderRecordMapper;

	private final OrderDonDifferRelateMapper orderDonDifferRelateMapper;

	private final OrderDonDifferGoodsMapper orderDonDifferGoodsMapper;

	private final OrderDiscountPlusPurchaseSkuRelationMapper plusPurchaseSkuRelationMapper;

	private final OrderDonGalaxyCoinRecordMapper orderDonGalaxyCoinRecordMapper;

	private final GptUserRechargeRecordService gptUserRechargeRecordService;

	private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();

	@GetMapping("/get")
	@SaCheckPermission("order:view")
	public Result<SearchResult<OrderDonBackView>> get(Long channelId, String account, String showId, Long acId, String nickname, String register, Boolean isGoogle, Boolean isSubsidy, Boolean isRenewPackage, Integer otherOrderType, Long userMirrorShopId, String operator, Long diffGoodsId, Boolean isTp) {
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		if (channelId != null) {
			List<Long> popularizeIds = channelPopularizeMapper.getPopularizeIdByChannelId(channelId);
			builder.field(OrderDonBackView::getPopularizeId, popularizeIds).op(Operator.InList);
		}
		if (StrUtil.isNotBlank(account)) {
			GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
					.eq(GroupsRelation::getAccount, account).last("limit 1"));
			if (relation != null) {
				builder.field(OrderDonBackView::getRelationId, relation.getId());
			} else {
				builder.field(OrderDonBackView::getRelationId).op(Operator.IsNull);
			}
		}
		if (StrUtil.isNotBlank(showId)) {
			builder.field(OrderDonBackView::getUserId, userService.getUserIdByShowId(showId));
		}
		String conditionSql = StrUtil.EMPTY;
		if (acId != null) {
			conditionSql += String.format(" o.user_id in (select user_id from corp_user where ac_id = %s)", acId);
		}
		if (!ObjectUtil.isAllEmpty(nickname, register, isGoogle)) {
			if (StrUtil.isNotEmpty(conditionSql)) {
				conditionSql += " and ";
			}
			conditionSql += " exists (select u.id from user u where u.id = o.user_id";
			if (StrUtil.isNotEmpty(nickname)) {
				conditionSql += String.format(" and u.nickname like '%s%%'", nickname);
			}
			if (StrUtil.isNotEmpty(register)) {
				if ("phone".equals(register)) {
					conditionSql += " and u.login_phone != ''";
				} else if ("email".equals(register)) {
					conditionSql += " and u.email != ''";
				} else if ("wechat".equals(register)) {
					conditionSql += " and u.unionid != ''";
				}
			}
			if (isGoogle != null && isGoogle) {
				conditionSql += String.format(" and u.is_google is %s", isGoogle);
			}
			conditionSql += " limit 1)";
		}
		if (isSubsidy != null) {
			if (StrUtil.isNotEmpty(conditionSql)) {
				conditionSql += " and ";
			}
			conditionSql += " exists (select 1 from order_don_subsidy_relate ocr where ocr.order_id = o.id limit 1)";
		}
		if (isRenewPackage != null) {
			if (StrUtil.isNotEmpty(conditionSql)) {
				conditionSql += " and ";
			}
			conditionSql += " exists (select 1 from order_don_renew_record odrr1 where odrr1.order_id = o.id limit 1)";
		}
		if (otherOrderType != null) {
			//3.续费升级订单
			if (otherOrderType == 3) {
				builder.put("tb", String.format(" inner join order_don_renew_record odcr on odcr.order_id = o.id and odcr.order_type = 2"));
			}
			if (otherOrderType == 4) {
				//4.用户权益订单
				builder.put("tb", String.format(" inner join user_benefits_order_record ubor on ubor.order_id = o.id and ubor.type = 'RENEW'"));
			}
			if (otherOrderType == 6) {
				//6.加盟订单
				builder.put("tb", String.format(" inner join user_mirror_shop_order_relate umr on umr.order_id = o.id"));
			}
		}
		if (userMirrorShopId != null) {
			if (StrUtil.isNotEmpty(conditionSql)) {
				conditionSql += " and ";
			}
			conditionSql += String.format(" exists (select 1 from user_mirror_shop_order_relate umr where mp_id = %s and umr.order_id = o.id limit 1)", userMirrorShopId);
		}
		if (diffGoodsId != null || StrUtil.isNotBlank(operator) || isTp != null) {
			if (StrUtil.isNotEmpty(conditionSql)) {
				conditionSql += " and ";
			}
			conditionSql += " exists (select 1 from order_don_differ_relate odr where odr.order_id = o.id";
			if (diffGoodsId != null) {
				conditionSql += String.format(" and odr.goods_id = %s", diffGoodsId);
			}
			if (StrUtil.isNotBlank(operator)) {
				conditionSql += String.format(" and odr.operator = '%s'", operator);
			}
			if (isTp != null && isTp) {
				conditionSql += String.format(" and odr.is_tp = %s", isTp);
			}
			conditionSql += ")";
		}
		if (StrUtil.isNotBlank(conditionSql)) {
			builder.put("condition", conditionSql);
		}
		SearchResult<OrderDonBackView> search = beanSearcher.search(OrderDonBackView.class, builder.build());
		search.getDataList().forEach(data -> {
			if (data.getPopularizeId() != null) {
				Optional.ofNullable(channelPopularizeMapper.selectChannelByPid(data.getPopularizeId()))
						.ifPresent(channelName -> data.setChannel(channelName));
			}

			if (data.getGoodsDonType() != null && Constant.realGoodsType.contains(data.getGoodsDonType())) {
				RealGoodsOrderHandle realGoodsOrderHandle = realGoodsOrderHandleMapper.selectOne(Wrappers.lambdaQuery(RealGoodsOrderHandle.class).eq(RealGoodsOrderHandle::getOrderId, data.getId()).last("limit 1"));
				if (realGoodsOrderHandle != null) {
					data.setBeforeServiceName(realGoodsOrderHandle.getBeforeServiceName());
					data.setAfterServiceName(realGoodsOrderHandle.getAfterServiceName());
				}
			}

			//使用优惠码
			if (data.getCouponId() != null) {
				Optional.ofNullable(couponMapper.selectById(data.getCouponId())).ifPresent(coupon -> data.setCouponName(coupon.getName()));
				data.setCouponMoney(data.getCouponMoney() == null ? BigDecimal.ZERO : data.getCouponMoney());
			}

			if (data.getCouponUserId() != 0) {
				data.setCouponName(couponMapper.getCouponNameByCouponUserId(data.getCouponUserId()));
				data.setCouponMoney(data.getCouponMoney() == null ? BigDecimal.ZERO : data.getCouponMoney());
			}

			if (data.getRelationId() != 0) {
				Optional.ofNullable(relationMapper.getGroupRelationAccountView(data.getRelationId()))
						.ifPresent(e -> {
							data.setGtAccount(e.getTripsAccount());
							data.setAccount(e.getAccount());
							data.setActCode(e.getActCode());
						});
			}

			if (data.getIsBenefits() != null && data.getIsBenefits() && !Constant.noOrderAllStatus.contains(data.getStatus())) {
				//是否实物权益已发放
				Integer count = receiveBenefitsRecordMapper.selectCount(Wrappers.lambdaQuery(UserPayEquipmentReceiveBenefitsRecord.class)
						.eq(UserPayEquipmentReceiveBenefitsRecord::getRealOrderId, data.getId()));
				if (count == 0) {
					count = availableBenefitsMapper.selectCount(Wrappers.lambdaQuery(UserPayEquipmentAvailableBenefits.class)
							.eq(UserPayEquipmentAvailableBenefits::getRealOrderId, data.getId()));
				}
				data.setIsHasBenefits(count == 0 ? true : false);
				//是否是套餐优惠权益订单
				if (data.getIsBenefits()) {
					Integer selectCount = userBenefitsOrderRecordMapper.selectCount(Wrappers.lambdaQuery(UserBenefitsOrderRecord.class)
							.eq(UserBenefitsOrderRecord::getOrderId, data.getId()));
					if (selectCount > 0) {
						data.setIsHasBenefits(false);
					}
				}
			}

			if (data.getYhsId() != 0) {
				Optional.ofNullable(yhShopMapper.selectById(data.getYhsId()))
						.ifPresent(e -> {
							data.setShopName(e.getName());
							data.setCustomId(e.getCustomId());
						});
			}

			User user = userMapper.selectById(data.getUserId());
			if (user != null) {
				data.setNickname(user.getNickname());
				data.setLoginPhone(user.getLoginPhone());
				data.setEmail(user.getEmail());
				data.setRegister(StrUtil.isNotEmpty(user.getUnionid()) ? "wechat" : StrUtil.isNotEmpty(user.getLoginPhone()) ? "phone" : "email");

			}
			if (data.getGoodsDonType() != null && data.getGoodsDonType() == 1) {
				//获取订单关联客服
				Optional.ofNullable(orderDonMapper.selectOrderRelate(data.getId())).ifPresent(e -> {
					data.setCmsUserId(e.getCmsUserId());
					data.setNickname(e.getNickname());
				});
			}
			//补差价订单
			if (data.getGoodsDonType() != null && data.getGoodsDonType() == 5) {
				OrderDonDifferRelateView donDifferRelateView = beanSearcher.searchFirst(OrderDonDifferRelateView.class, MapUtils.builder().field(OrderDonDifferRelateView::getOrderId, data.getId()).build());
				if (donDifferRelateView != null) {
					data.setDiffGoodsId(donDifferRelateView.getGoodsId());
					data.setDiffTitle(donDifferRelateView.getTitle());
					data.setDiffOperator(donDifferRelateView.getOperator());
					data.setIsTp(donDifferRelateView.getIsTp());
				}
			}
			OrderDonGalaxyCoinRecord orderDonGalaxyCoinRecord = orderDonGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonGalaxyCoinRecord.class)
					.eq(OrderDonGalaxyCoinRecord::getOrderId, data.getId())
					.last("limit 1"));
			if (orderDonGalaxyCoinRecord != null) {
				data.setGalaxyCoin(orderDonGalaxyCoinRecord.getGalaxyCoin());
				data.setGalaxyCoinDeductMoney(orderDonGalaxyCoinRecord.getDeductMoney());
			}
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 用户退款订单列表
	 */
	@GetMapping("/get/refund/list")
	public Result<SearchResult<RefundOrderDonView>> getRefundOrderDonView() {
		SearchResult<RefundOrderDonView> search = beanSearcher.search(RefundOrderDonView.class, MapUtils.flatBuilder(request.getParameterMap())
				.build());
		search.getDataList().forEach(data -> {
			Optional.ofNullable(userService.getById(data.getUserId()))
					.ifPresent(user -> data.setNickname(user.getNickname()));
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 镜像规格使用详情
	 */
	@GetMapping("/get/order/mj/mirror/detail/{orderId}")
	public Result<MidjourneyUserDetailView> getMjMirrorOrderDetail(@PathVariable Long orderId) {
		OrderDon orderDon = orderDonMapper.selectById(orderId);
		//续费订单
		Date startTime = null;
		Date expiryTime = null;
		if (orderDon.getOrderType() == 2) {
			GoodsDonSku sku = skuMapper.selectById(orderDon.getSkuId());
			GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
					.eq(GroupsRelation::getId, orderDon.getRelationId())
					.eq(GroupsRelation::getUserId, orderDon.getUserId()).last("limit 1"));
			if (relation == null) {
				return GatewayResponse.SUCCESS.newBuilder().toResult();
			}
			startTime = relation.getStartTime();
			startTime = DateUtil.offsetMonth(startTime, sku.getMonths());
			expiryTime = relation.getExpiryTime();
		}
		MidjourneyUserDetailView midjourneyUserDetailView = midjourneyUserConversationMapper.getMjMirrorOrderDetail(orderDon.getRelationId(), startTime, expiryTime);
		return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyUserDetailView);
	}

	/**
	 * 订单导出
	 */
	@GetMapping("/export")
	@SaCheckPermission("order:export")
	@Log(module = "订单管理/导出订单", businessType = BusinessType.EXPORT, isSaveRequestData = true)
	public void exportOrders(HttpServletResponse response, Long channelId, String account, String showId, Long acId, String nickname, String register, Boolean isGoogle, Boolean isSubsidy, Boolean isRenewPackage, Integer otherOrderType, Long userMirrorShopId, String operator, Long diffGoodsId, Boolean isTp) throws InterruptedException {
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		if (channelId != null) {
			List<Long> popularizeIds = channelPopularizeMapper.getPopularizeIdByChannelId(channelId);
			builder.field(ExcelOrderDonData::getPopularizeId, popularizeIds).op(Operator.InList);
		}
		if (StrUtil.isNotBlank(account)) {
			GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
					.eq(GroupsRelation::getAccount, account).last("limit 1"));
			if (relation != null) {
				builder.field(ExcelOrderDonData::getRelationId, relation.getId());
			} else {
				builder.field(ExcelOrderDonData::getRelationId).op(Operator.IsNull);
			}
		}
		if (StrUtil.isNotBlank(showId)) {
			builder.field(ExcelOrderDonData::getUserId, userService.getUserIdByShowId(showId));
		}
		String conditionSql = StrUtil.EMPTY;
		if (acId != null) {
			conditionSql += String.format(" o.user_id in (select user_id from corp_user where ac_id = %s)", acId);
		}
		if (!ObjectUtil.isAllEmpty(nickname, register, isGoogle)) {
			if (StrUtil.isNotEmpty(conditionSql)) {
				conditionSql += " and ";
			}
			conditionSql += " exists (select u.id from user u where u.id = o.user_id";
			if (StrUtil.isNotEmpty(nickname)) {
				conditionSql += String.format(" and u.nickname like '%s%%'", nickname);
			}
			if (StrUtil.isNotEmpty(register)) {
				if ("phone".equals(register)) {
					conditionSql += " and u.login_phone != ''";
				} else if ("email".equals(register)) {
					conditionSql += " and u.email != ''";
				} else if ("wechat".equals(register)) {
					conditionSql += " and u.unionid != ''";
				}
			}
			if (isGoogle != null && isGoogle) {
				conditionSql += String.format(" and u.is_google is %s", isGoogle);
			}
			conditionSql += " limit 1)";
		}
		if (isSubsidy != null) {
			if (StrUtil.isNotEmpty(conditionSql)) {
				conditionSql += " and ";
			}
			conditionSql += " exists (select 1 from order_don_subsidy_relate ocr where ocr.order_id = o.id limit 1)";
		}
		if (isRenewPackage != null) {
			if (StrUtil.isNotEmpty(conditionSql)) {
				conditionSql += " and ";
			}
			conditionSql += " exists (select 1 from order_don_renew_record odrr1 where odrr1.order_id = o.id limit 1)";
		}
		if (otherOrderType != null) {
			//3.续费升级订单
			if (otherOrderType == 3) {
				builder.put("tb", String.format(" inner join order_don_renew_record odcr on odcr.order_id = o.id and odcr.order_type = 2"));
			}
			if (otherOrderType == 4) {
				//4.用户权益订单
				builder.put("tb", String.format(" inner join user_benefits_order_record ubor on ubor.order_id = o.id and ubor.type = 'RENEW'"));
			}
			if (otherOrderType == 6) {
				//6.加盟订单
				builder.put("tb", String.format(" inner join user_mirror_shop_order_relate umr on umr.order_id = o.id"));
			}
		}
		if (diffGoodsId != null || StrUtil.isNotBlank(operator) || isTp != null) {
			if (StrUtil.isNotEmpty(conditionSql)) {
				conditionSql += " and ";
			}
			conditionSql += " exists (select 1 from order_don_differ_relate odr where odr.order_id = o.id";
			if (diffGoodsId != null) {
				conditionSql += String.format(" and odr.goods_id = %s", diffGoodsId);
			}
			if (StrUtil.isNotBlank(operator)) {
				conditionSql += String.format(" and odr.operator = '%s'", operator);
			}
			if (isTp != null && isTp) {
				conditionSql += String.format(" and odr.is_tp = %s", isTp);
			}
			conditionSql += ")";
		}
		if (userMirrorShopId != null) {
			conditionSql += String.format(" exists (select 1 from user_mirror_shop_order_relate umr where mp_id = %s and umr.order_id = o.id limit 1)", userMirrorShopId);
		}
		if (StrUtil.isNotBlank(conditionSql)) {
			builder.put("condition", conditionSql);
		}
		List<ExcelOrderDonData> list = beanSearcher.searchAll(ExcelOrderDonData.class, builder.build());
		List<List<ExcelOrderDonData>> partition = Lists.partition(list, 500);
		CountDownLatch countDownLatch = new CountDownLatch(partition.size());
		for (List<ExcelOrderDonData> excelOrderDonData : partition) {
			TASK_EXECUTOR.execute(() -> setExportOrderInfo(excelOrderDonData, countDownLatch));
		}
		countDownLatch.await(15, TimeUnit.MINUTES);
		EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelOrderDonData.class, list, "订单列表", "订单列表", ExcelTypeEnum.XLSX, null);
	}

	/**
	 * 导出实物模板 订单excel
	 */
	@GetMapping("/export/realGoods")
	public void exportRealGoods(HttpServletResponse response) throws IOException {
		List<ExcelRealGoodsOrderData> list = beanSearcher.searchAll(ExcelRealGoodsOrderData.class, MapUtils.flatBuilder(request.getParameterMap())
				.field(ExcelOrderDonData::getGoodsDonType, Constant.realGoodsType).op(Operator.InList)
				.build());
//		AtomicInteger index = new AtomicInteger(1);
		list.forEach(data -> {
			data.setPayType("寄付现结");
			if (data.getGoodsDonType() == Constant.realGoodsType.get(0)) {
				data.setRealGoodName("路由器");
			} else if (data.getGoodsDonType() == Constant.realGoodsType.get(1)) {
				data.setRealGoodName("银河潮玩");
			}
//			data.setIndex(index.getAndIncrement());
		});
		if (CollUtil.isEmpty(list)) {
			throw BusinessRuntimeException.getInstance("导出数据为空");
		}

		response.setContentType("application/x-download");
		response.setContentType("application/vnd.ms-excel");
		response.setCharacterEncoding("utf-8");
		response.setHeader("Content-disposition",
				"attachment;filename=" + new String("实物订单列表".getBytes("utf-8"), "ISO-8859-1") + ExcelTypeEnum.XLS.getValue());

		EasyExcel.write(response.getOutputStream())
				.head(ExcelRealGoodsOrderData.class)
				//设置合并单元格策略
//				.registerWriteHandler(new RealGoodsOrderLineStrategy())
				.excelType(ExcelTypeEnum.XLS)
				.sheet("实物订单列表")
				//设置头部标题从那行开始
//				.relativeHeadRowIndex(2)
				.doWrite(list);
	}

	@PutMapping("/update/status")
    public Result<String> upStatus(@RequestBody OrderDon orderDon){
        cmsOrderDonService.update(Wrappers.lambdaUpdate(OrderDon.class).eq(OrderDon::getId,orderDon.getId()).set(OrderDon::getStatus,orderDon.getStatus()));
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }

	/**
	 * 编辑自定义订阅节点
	 */
	@PutMapping("/update/subNode")
	public Result<String> updateSubNode(@RequestBody OrderDon orderDon) {
		OrderDon en = cmsOrderDonService.getById(orderDon.getId());
		if (en != null) {
			en.setSubNode(orderDon.getSubNode());
			cmsOrderDonService.updateById(en);
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}


	@GetMapping("/get/transport/{orderId}")
    public Result<OrderDonTransportView> getTransport(@PathVariable Long orderId){
//        OrderDonTransport transport = cmsOrderDonService.getTransport(orderId);
        OrderDonTransportView transportView = beanSearcher.searchFirst(OrderDonTransportView.class, MapUtils.builder().field(OrderDonTransportView::getOrderId, orderId).build());
        return GatewayResponse.SUCCESS.newBuilder().toResult(transportView);
    }

    @PostMapping("/post/setWaybill")
    public Result<OrderDonWaybill> setWaybill(@RequestBody ReqSetLogisticsPost reqSetLogisticsPost){
        OrderDonWaybill orderDonWaybill = cmsOrderDonService.setWaybill(reqSetLogisticsPost);
        return GatewayResponse.SUCCESS.newBuilder().toResult(orderDonWaybill);
    }

	/**
	 * 用户购买实物商品意愿列表
	 */
	@GetMapping("/get/realGooods/interest/users")
	@SaCheckPermission("interest:view")
	public Result<SearchResult> getInterestUserList(RealGoodsInterestUser.Status interestStatus, HttpServletRequest request) {
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		SearchResult<RealGoodsInterestUserView> search;
		if (interestStatus == null) {
			builder.field(RealGoodsInterestUserView::getInterestStatus, "hasPayment").op(Operator.NotEqual);
			search = beanSearcher.search(RealGoodsInterestUserView.class, builder.build());
		} else if (interestStatus != RealGoodsInterestUser.Status.hasPayment) {
			builder.field(RealGoodsInterestUserView::getInterestStatus, interestStatus.name());
			search = beanSearcher.search(RealGoodsInterestUserView.class, builder.build());
		} else {
			search = new SearchResult<>();
			SearchResult<RealGoodsInterestUserHasPaymentView> search2 = beanSearcher.search(RealGoodsInterestUserHasPaymentView.class, builder.build());
			search.setTotalCount(search2.getTotalCount());
			List<RealGoodsInterestUserView> dataList = search.getDataList();
			dataList.addAll(search2.getDataList());
		}
		search.getDataList().forEach(data -> {
			Long goodsId = data.getGoodsId();
			OrderDon order = cmsOrderDonService.getOne(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getUserId, data.getUserId()).eq(OrderDon::getGoodsId, goodsId).ne(OrderDon::getId, data.getId()).gt(OrderDon::getMoney, data.getMoney()).eq(OrderDon::getStatus, "close").last("limit 1"));
			if (order != null) {
				data.setOrderId(order.getId());
				data.setSkuId(order.getSkuId());
				data.setMoney(order.getMoney());
				realGoodsInterestUserMapper.updateData(data.getId(), data.getSkuId(), data.getOrderCreatedTime(), data.getOrderId());
			}
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 修改订单状态
	 */
	@PutMapping("/put/status/{orderId}")
	@Transactional(rollbackFor = Throwable.class)
	public Result<String> updateOrderStatus(@PathVariable Long orderId) {
		long adminId = StpUtil.getLoginIdAsLong();
		CmsUser cmsUser = cmsUserMapper.selectById(adminId);
		OrderDon orderDon = cmsOrderDonService.getById(orderId);
		if (orderDon == null) {
			throw BusinessRuntimeException.getInstance("该订单不存在");
		}
		if (orderDon.getStatus() == OrderDon.Status.complete) {
			throw BusinessRuntimeException.getInstance("该订单已是已完成状态");
		}
		if (orderDon.getStatus() != OrderDon.Status.hasPayment) {
			throw BusinessRuntimeException.getInstance("该订单不是未支付状态");
		}
		orderDon.setStatus(OrderDon.Status.complete);
		cmsOrderDonService.updateById(orderDon);
		Long relationId = orderDon.getRelationId();
		Optional.ofNullable(relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
				.eq(GroupsRelation::getId, relationId)
				.eq(GroupsRelation::getUserId, orderDon.getUserId())
				.last("limit 1"))).ifPresent(relation->{
			GroupsRelation.RechargeStatus rechargeStatus = relation.getRechargeStatus();
			if (rechargeStatus != null && (rechargeStatus == GroupsRelation.RechargeStatus.waiting || rechargeStatus == GroupsRelation.RechargeStatus.recharge_error)) {
				relation.setRechargeStatus(GroupsRelation.RechargeStatus.complete);
				if (cmsUser != null) {
					relation.setOperator(cmsUser.getNickname());
				}
				relation.setSendTime(DateTime.now());
				relation.setStartTime(DateTime.now());
				GoodsDonSku sku = skuMapper.selectById(orderDon.getSkuId());
				DateTime expiryTime;
				if (sku.getDays() != null && sku.getDays() > 0) {
					expiryTime = DateUtil.offsetDay(relation.getStartTime(), sku.getDays());
				} else {
					expiryTime = DateUtil.offsetMonth(relation.getStartTime(), sku.getMonths());
				}
				relation.setExpiryTime(expiryTime);
				relationMapper.updateById(relation);

				//GPT代充
				if (orderDon.getGoodsId() == Constant.GPT_RECHARGE_GOODS_ID) {
					//扣除次数
					Integer rechargeRemainNum = relation.getRechargeRemainNum();
					if (rechargeRemainNum != null && rechargeRemainNum > 0) {
						int update = relationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
								.set(GroupsRelation::getRechargeRemainNum, rechargeRemainNum - 1)
								.eq(GroupsRelation::getId, relationId)
								.eq(GroupsRelation::getRechargeRemainNum, rechargeRemainNum));
						if (update == 0) {
							throw BusinessRuntimeException.getInstance("更新用户代充剩余次数失败，请重试");
						}
						//记录gpt代充记录
						gptUserRechargeRecordService.recordGptUserRechargeNum(relation.getUserId(), relation.getId(), relation.getAccount(), -1, cmsUser != null ? cmsUser.getNickname() : null, "客服手动充值");
					}
				}
			}
		});

		return GatewayResponse.SUCCESS.newBuilder().toResult("修改订单状态成功");
	}

    /**
     * 修改购买意愿记录
     */
    @PutMapping("/put/interest")
    public Result<String> updateInterest(@RequestBody @Validated UserRealGoodsInterestReq req) {
        RealGoodsInterestUser realGoodsInterestUser = realGoodsInterestUserMapper.selectById(req.getId());
        if (realGoodsInterestUser != null) {
            if (req.getStatus() != null) {
                realGoodsInterestUser.setInterestStatus(req.getStatus());
            }
            if (req.getRemark() != null) {
                realGoodsInterestUser.setRemark(req.getRemark());
            }
            realGoodsInterestUserMapper.updateById(realGoodsInterestUser);
        }
        return GatewayResponse.SUCCESS.newBuilder().toResult("修改成功");
    }

	/**
	 * 导出用户意愿列表
	 */
	@GetMapping("/export/interest")
	public void exportInterest(RealGoodsInterestUser.Status interestStatus, HttpServletRequest request, HttpServletResponse response) {
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		List<ExcelRealGoodsUserInterestData> excelRealGoodsUserInterestData;
		if (interestStatus == null) {
			builder.field(RealGoodsInterestUserView::getInterestStatus, "hasPayment").op(Operator.NotEqual);
			excelRealGoodsUserInterestData = beanSearcher.searchAll(ExcelRealGoodsUserInterestData.class, builder.build());
		} else {
			List<ExcelRealGoodsUserInterestHasPaymentData> excelRealGoodsUserInterestData2 = beanSearcher.searchAll(ExcelRealGoodsUserInterestHasPaymentData.class, builder.build());
			excelRealGoodsUserInterestData = new ArrayList<>(excelRealGoodsUserInterestData2);
		}
		excelRealGoodsUserInterestData.forEach(data -> {
			Long goodsId = data.getGoodsId();
			OrderDon order = cmsOrderDonService.getOne(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getUserId, data.getUserId()).eq(OrderDon::getGoodsId, goodsId).ne(OrderDon::getId, data.getId()).gt(OrderDon::getMoney, data.getMoney()).eq(OrderDon::getStatus, "close").last("limit 1"));
			if (order != null) {
				data.setOrderId(order.getId());
				data.setSkuId(order.getSkuId());
				data.setMoney(order.getMoney());
				realGoodsInterestUserMapper.updateData(data.getId(), data.getSkuId(), data.getOrderCreatedTime(), data.getOrderId());
			}
			data.setMoney(data.getMoney().divide(BigDecimal.valueOf(100)));
		});
		EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelRealGoodsUserInterestHasPaymentData.class, excelRealGoodsUserInterestData, "用户意愿列表", "用户意愿列表", ExcelTypeEnum.XLSX, null);
	}

    /**
     * 实物订单配置售前售后客户
     */
    @PostMapping("/put/realGoods/service")
    @NoSubmit
    @Log(module = "订单管理/售前、售后客服", businessType = BusinessType.PUT, isSaveRequestData = true)
    public Result<String> putRealGoodsService(@RequestBody @Validated RealGoodsServiceReq request) {
        OrderDon orderDon = cmsOrderDonService.getById(request.getOrderId());
        if (orderDon == null || orderDon.getRelationId() != 0) {
            throw BusinessRuntimeException.getInstance("该订单不是实物订单");
        }
	    Boolean isBefore = false;
	    Boolean isAfter = false;
	    RealGoodsOrderHandle realGoodsOrderHandle = Optional.ofNullable(realGoodsOrderHandleMapper.selectOne(Wrappers.lambdaQuery(RealGoodsOrderHandle.class).eq(RealGoodsOrderHandle::getOrderId, request.getOrderId()).last("limit 1"))).orElse(new RealGoodsOrderHandle());
	    if (StringUtils.isNotBlank(request.getBeforeServiceName())) {
		    realGoodsOrderHandle.setBeforeServiceName(request.getBeforeServiceName());
		    isBefore = true;
	    }
	    if (StringUtils.isNotBlank(request.getAfterServiceName())) {
		    realGoodsOrderHandle.setAfterServiceName(request.getAfterServiceName());
		    isAfter = true;
	    }
	    if (realGoodsOrderHandle.getId() == null) {
		    realGoodsOrderHandle.setOrderId(request.getOrderId());
		    realGoodsOrderHandleMapper.insert(realGoodsOrderHandle);
	    } else {
		    if (realGoodsOrderHandle.getBeforeOpNum() > 2) {
			    throw BusinessRuntimeException.getInstance("售前客服已两次修改");
		    }
		    if (realGoodsOrderHandle.getAfterOpNum() > 2) {
			    throw BusinessRuntimeException.getInstance("售后客服已两次修改");
		    }
		    if (isBefore) {
			    realGoodsOrderHandle.setBeforeOpNum(realGoodsOrderHandle.getBeforeOpNum() + 1);
		    }
		    if (isAfter) {
			    realGoodsOrderHandle.setAfterOpNum(realGoodsOrderHandle.getAfterOpNum() + 1);
		    }
		    realGoodsOrderHandleMapper.updateById(realGoodsOrderHandle);
	    }
        return GatewayResponse.SUCCESS.newBuilder().toResult("操作成功");
    }

	/**
	 * 新增平台评论
	 */
	@PostMapping("/post/orderComment")
	public Result<String> insertOrderComment(@RequestBody @Validated OrderComment orderComment) {
		if (StrUtil.isEmpty(orderComment.getHeadImgUrl())) {
			orderComment.setHeadImgUrl(Constant.DEFAULT_HEAD_IMG);
		}
		if (orderComment.getCommentTime() == null) {
			orderComment.setCommentTime(DateTime.now().toDateStr());
		}
		orderComment.setVerifyStatus(OrderComment.VerifyStatus.success);
		orderCommentMapper.insert(orderComment);
		return GatewayResponse.SUCCESS.newBuilder().toResult("新增成功");
	}

	/**
	 * 编辑平台评论
	 */
	@PutMapping("/put/orderComment")
	public Result<String> updateOrderComment(@RequestBody @Validated OrderComment orderComment) {
		if (orderComment.getCommentTime() == null) {
			orderComment.setCommentTime(DateTime.now().toDateStr());
		}
		if (orderComment.getVerifyStatus() == null) {
			orderComment.setVerifyStatus(OrderComment.VerifyStatus.success);
		}
		orderCommentMapper.updateById(orderComment);
		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑成功");
	}

	/**
	 * 删除平台评论
	 */
	@DeleteMapping("/delete/orderComment/{id}")
	public Result<String> deleteOrderCommentById(@PathVariable Long id) {
		orderCommentMapper.deleteById(id);
		return GatewayResponse.SUCCESS.newBuilder().toResult("删除成功");
	}

	/**
	 * 平台评论列表
	 */
	@GetMapping("/get/orderComment")
	public Result<SearchResult<OrderCommentView>> getOrderCommentView() {
		SearchResult<OrderCommentView> search = beanSearcher.search(OrderCommentView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 评论审核
	 */
	@PutMapping("/put/orderComment/status")
	@NoSubmit
	public Result<String> updateOrderCommentStatus(@RequestBody OrderComment orderCommentReq) throws Exception {
		orderDonCommentService.verifyCommentStatus(orderCommentReq.getId(), orderCommentReq.getVerifyStatus());
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 配置订单平台评价列表
	 */
	@PostMapping("/post/orderComment/reward/config")
	public Result<String> saveOrUpdateOrderCommentConfig(@RequestBody List<OrderCommentRewardConfig> configs) {
		orderDonCommentService.saveOrUpdateOrderCommentConfig(configs);
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 获取配置 订单平台评价
	 */
	@GetMapping("/get/orderComment/reward/config")
	public Result<List<OrderCommentRewardConfigView>> getOrderCommentRewardConfig() {
		List<OrderCommentRewardConfigView> views = beanSearcher.searchAll(OrderCommentRewardConfigView.class, MapUtils.builder()
				.orderBy(OrderCommentRewardConfigView::getGoodsId).desc()
				.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(views);
	}

	/**
	 * 踢出车队
	 */
	@PutMapping("/kickOut")
	@NoSubmit
	public Result<String> kickOut(@RequestBody @Validated ClickOutReq req) {
		long adminId = StpUtil.getLoginIdAsLong();
		cmsOrderDonService.kickOutRelationId(adminId, req);
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 踢出车队列表
	 */
	@GetMapping("/get/kickOut/list")
	public Result<SearchResult<UserKickOutView>> getKickOutList() {
		SearchResult<UserKickOutView> search = beanSearcher.search(UserKickOutView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 客服修改订单来源
	 */
	@PutMapping("/update/order/source")
	public Result<String> updateOrderSource(@RequestBody OrderDon orderDon) {
		Long id = orderDon.getId();
		String labelSource = orderDon.getLabelSource();
		cmsOrderDonService.update(null, Wrappers.lambdaUpdate(OrderDon.class)
				.set(OrderDon::getLabelSource, labelSource)
				.eq(OrderDon::getId, id));

		realGoodsOrderHandleMapper.update(null, Wrappers.lambdaUpdate(RealGoodsOrderHandle.class)
				.set(RealGoodsOrderHandle::getLabelSource, labelSource)
				.eq(RealGoodsOrderHandle::getOrderId, id));
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 设置实物订单电视机类型
	 */
	@PutMapping("/update/order/tvType")
	public Result<String> updateOrderTvType(@RequestBody OrderDon orderDon) {
		Integer tvType = orderDon.getTvType();
		Long id = orderDon.getId();
		cmsOrderDonService.update(null, Wrappers.lambdaUpdate(OrderDon.class)
				.set(OrderDon::getTvType, tvType)
				.eq(OrderDon::getId, id));
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 订单统一退款
	 */
	@PostMapping("/unified/refund")
	@Log(module = "订单管理/统一退款", businessType = BusinessType.PUT, isSaveRequestData = true)
	public Result<String> unifiedRefund(@RequestBody @Validated OrderRefundReq refundReq) throws Exception {
		long adminId = StpUtil.getLoginIdAsLong();
		CmsUser cmsUser = cmsUserMapper.selectById(adminId);
		if (cmsUser == null) {
			throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
		}
		refundReq.setOperator(cmsUser.getNickname());
		cmsOrderDonService.unifiedRefund(refundReq);
		return GatewayResponse.SUCCESS.newBuilder().toResult("退款成功");
	}

	/**
	 * 微信退款回调
	 */
	@PostMapping("/wx/refund/notify")
	public void wxRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String xml = IoKit.toString(request.getInputStream());
		log.info("=== 退款成功的回调: \n {}", xml);

		// 解析xml
		Map<String, String> map = Xmls.toMap(xml);

		// 退款失败
		if (!StrUtil.equals("SUCCESS", map.get("return_code"))) {
			throw BusinessRuntimeException.getInstance("退款失败.");
		}

		cmsOrderDonService.wxRefundNotify(map);

		String toWechatXmlResponse = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";

		OutputStream out = null;
		try {
			out = response.getOutputStream();
			IoKit.write(toWechatXmlResponse, out);
		} catch (Throwable e) {
			throw BusinessRuntimeException.getInstance(e == null ? null : e.getMessage());
		} finally {
			IoKit.close(out);
		}
	}

	/**
	 * 更换用户车票
	 */
	@PutMapping("/put/sameSpec/empty/relation")
	@Log(module = "更换用户车票", businessType = BusinessType.PUT, isSaveRequestData = true)
	public Result<String> changeRelation(@RequestBody @Validated ChangeRelationReq req) throws Exception {
		cmsOrderDonService.changeRelation(req);
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}


	/**
	 * 多余车位的空账号
	 */
	@GetMapping("/get/sameSpec/empty/relation")
	public Result<SearchResult<EmptyGroupsRelationView>> getSameSpecEmptyRelation(Long skuId, Long groupsId, Long relationId, Boolean isNormal) {
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap())
				.field(EmptyGroupsRelationView::getStatus, GroupsTrips.Status.down.name()).op(Operator.NotEqual).field(EmptyGroupsRelationView::getSkuId, skuId);
		GoodsDonSku sku = skuMapper.selectById(skuId);
		if (sku.getGoodsId() == Constant.NETFLIX_GID) {
			builder.orderBy(EmptyGroupsRelationView::getCreatedTime).desc().orderBy(EmptyGroupsRelationView::getAvailableNum).desc();
		} else {
			builder.orderBy(EmptyGroupsRelationView::getAvailableNum).desc();
		}
		Date expiryTime = null;
		if (relationId != null) {
			GroupsRelation relation = relationMapper.selectById(relationId);
			if (relation != null) expiryTime = relation.getExpiryTime();
		}
		if (groupsId != null) {
			builder.field(EmptyGroupsRelationView::getGroupsId, groupsId).op(Operator.NotEqual);
		}
		String condition = StrUtil.EMPTY;
		if (isNormal != null && isNormal) {
			condition += String.format("gt.account_id not in (select account_id from work_order where sku_id = %s and account_id is not null)", skuId);
		}
		if (StrUtil.isNotEmpty(condition)) {
			condition += " and ";
		}
		Integer maxNum = sku.getNum();
		Integer extraNum = 5;
		//GPT 4人月付
		if (sku.getId() == 178l) {
			extraNum = 2;
		}
		maxNum += extraNum;
		condition += String.format("(available_parking_num = 0 or available_parking_num > (select count(*) from groups_relation gr where gr.groups_id = gt.id and gr.user_id != 0 and gr.num <= %s))", maxNum);
		if (StrUtil.isNotEmpty(condition)) {
			builder.put("condition", condition);
		}
		if (expiryTime != null) {
			builder.field(AccountView::getExpiryTime, expiryTime).op(Operator.GreaterEqual);
			builder.orderBy(AccountView::getExpiryTime).asc();
		}
		if (sku.getNum() == 1 || !Constant.AI_goodsIds.contains(sku.getGoodsId())) {
			builder.field(EmptyGroupsRelationView::getAvailableNum, 0).op(Operator.GreaterThan);
		}
		SearchResult<EmptyGroupsRelationView> search = beanSearcher.search(EmptyGroupsRelationView.class,
				builder.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 订单补差价，补差价退款到余额
	 */
	@PutMapping("/refund/price/differ")
	@Log(module = "订单管理/订单补差价", businessType = BusinessType.PUT, isSaveRequestData = true)
	public Result<String> refundPriceDiffer(@RequestBody OrderRefundReq orderRefundReq) throws Exception {
		long adminId = StpUtil.getLoginIdAsLong();
		CmsUser cmsUser = cmsUserMapper.selectById(adminId);
		if (cmsUser == null) {
			throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
		}
		orderRefundReq.setOperator(cmsUser.getNickname());
		cmsOrderDonService.refundPriceDiffer(orderRefundReq);
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 将余额清零 退款用户支付金额
	 */
	@PutMapping("/clear/balance/refundMoney")
	@NoSubmit
	public Result<String> clearBalanceToRefundMoney(@RequestBody @Validated OrderBalanceRefundReq refundReq) throws Exception {
		cmsOrderDonService.clearBalanceToRefundMoney(refundReq);
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}


	/**
	 * 客服退款每月数据
	 */
	@GetMapping("/get/refundOrder/data")
	public Result<SearchResult<RefundOrderDonServiceDataView>> getRefundOrderData(String startTime, String endTime, String operator) {
		String time = StrUtil.EMPTY;
		if (StrUtil.isNotBlank(startTime)) {
			time += String.format(" and o.created_time >= '%s'", startTime);
		}
		if (StrUtil.isNotBlank(endTime)) {
			time += String.format(" and o.created_time < '%s'", endTime);
		}
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		if (StrUtil.isNotBlank(time)) {
			builder.put("time", time);
		}
		if (StrUtil.isEmpty(operator)) {
			List<CmsUserVO> userVOS = beanSearcher.searchAll(CmsUserVO.class, MapUtils.builder().field(CmsUserVO::getRoleNames, "客服").op(Operator.Contain).build());
			List<String> collect = userVOS.stream().map(CmsUserVO::getNickname).collect(Collectors.toList());
			if (CollUtil.isNotEmpty(collect)) {
				builder.field(RefundOrderDonServiceDataView::getOperator, collect).op(Operator.InList);
			}
		}
		SearchResult<RefundOrderDonServiceDataView> search = beanSearcher.search(RefundOrderDonServiceDataView.class, builder.build());
		search.getDataList().forEach(e->{
			String goodsName = orderDonMapper.selectMaxRefundGoodsName(e.getOperator(), startTime, endTime);
			e.setGoodsName(goodsName);
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 设置订单客服
	 */
	@PutMapping("/set/service")
	public Result<String> setOrderCustomerService(@RequestBody OrderDonCustomerServiceRelate relate) {
		OrderDonCustomerServiceRelate orderDonCustomerServiceRelate = orderDonCustomerServiceRelateMapper.selectOne(Wrappers.lambdaQuery(OrderDonCustomerServiceRelate.class)
				.eq(OrderDonCustomerServiceRelate::getOrderId, relate.getOrderId()).last("limit 1"));
		if (orderDonCustomerServiceRelate != null) {
			relate.setId(orderDonCustomerServiceRelate.getId());
		}
		try {
			if (relate.getId() == null) {
				orderDonCustomerServiceRelateMapper.insert(relate);
			} else {
				orderDonCustomerServiceRelateMapper.updateById(relate);

			}
		} catch (DuplicateKeyException e) {
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}



	/**
	 * 查询套餐订单列表
	 */

	@GetMapping("/upgrade/get")
	@SaCheckPermission("upgradeOrder:view")
	public Result<SearchResult<UpgradeOrderDonBackView>> getUpgradeOrder(String account, String showId, Long acId, String nickname, String register, Boolean isGoogle) {
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());

		if (StrUtil.isNotBlank(account)) {
			GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
					.eq(GroupsRelation::getAccount, account).last("limit 1"));
			if (relation != null) {
				builder.field(OrderDonBackView::getRelationId, relation.getId());
			} else {
				builder.field(OrderDonBackView::getRelationId).op(Operator.IsNull);
			}
		}
		if (StrUtil.isNotBlank(showId)) {
			builder.field(OrderDonBackView::getUserId, userService.getUserIdByShowId(showId));
		}
		String conditionSql = StrUtil.EMPTY;
		if (acId != null) {
			conditionSql += String.format(" o.user_id in (select user_id from corp_user where ac_id = %s)", acId);
		}
		if (!ObjectUtil.isAllEmpty(nickname, register, isGoogle)) {
			if (StrUtil.isNotEmpty(conditionSql)) {
				conditionSql += " and ";
			}
			conditionSql += " exists (select u.id from user u where u.id = o.user_id";
			if (StrUtil.isNotEmpty(nickname)) {
				conditionSql += String.format(" and u.nickname like '%s%%'", nickname);
			}
			if (StrUtil.isNotEmpty(register)) {
				if ("phone".equals(register)) {
					conditionSql += " and u.login_phone != ''";
				} else if ("email".equals(register)) {
					conditionSql += " and u.email != ''";
				} else if ("wechat".equals(register)) {
					conditionSql += " and u.unionid != ''";
				}
			}
			if (isGoogle != null && isGoogle) {
				conditionSql += String.format(" and u.is_google is %s", isGoogle);
			}
			conditionSql += " limit 1)";
		}
		if (StrUtil.isNotBlank(conditionSql)) {
			builder.put("condition", conditionSql);
		}
		SearchResult<UpgradeOrderDonBackView> search = beanSearcher.search(UpgradeOrderDonBackView.class, builder.build());
		search.getDataList().forEach(data -> {
			User user = userMapper.selectById(data.getUserId());
			if (user != null) {
				data.setNickname(user.getNickname());
				data.setLoginPhone(user.getLoginPhone());
				data.setEmail(user.getEmail());
				data.setRegister(StrUtil.isNotEmpty(user.getUnionid()) ? "wechat" : StrUtil.isNotEmpty(user.getLoginPhone()) ? "phone" : "email");
			}
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 套餐退款订单列表
	 */
	@GetMapping("/get/upgrade/refund/list")
	public Result<SearchResult<RefundUpdradeOrderDonView>> getRefundUpgradeOrderDonView(String nickname) {
		List<Long> userIds = null;
		if (StrUtil.isNotBlank(nickname)) {
			userIds = userMapper.selectListByNickname(nickname);
			if (CollUtil.isEmpty(userIds)) {
				userIds.add(0l);
			}
		}
		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
		if (CollUtil.isNotEmpty(userIds)) {
			builder.field(RealGoodsInterestUserView::getUserId, userIds).op(Operator.InList);
		}
		SearchResult<RefundUpdradeOrderDonView> search = beanSearcher.search(RefundUpdradeOrderDonView.class,
				builder.build());
		search.getDataList().forEach(data -> {
			Optional.ofNullable(userService.getById(data.getUserId()))
					.ifPresent(user -> data.setNickname(user.getNickname()));
		});
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 套餐订单导出
	 */
	@GetMapping("/upgrade/export")
	@SaCheckPermission("upgradeOrder:export")
	@Log(module = "套餐订单管理/导出订单", businessType = BusinessType.EXPORT, isSaveRequestData = true)
	public void exportUpgradeOrders(HttpServletResponse response) {
		List<ExcelUpgradeOrderDonData> list = beanSearcher.searchAll(ExcelUpgradeOrderDonData.class, MapUtils.flatBuilder(request.getParameterMap()).build());
		list.forEach(data -> {
			data.setMoney(data.getMoney().divide(BigDecimal.valueOf(100)));
			UpgradeOrderDon.Type type = data.getType();
			data.setTypeStr(type != null ? type.getDesc() : "");
			UpgradeOrderDon.Status status = data.getStatus();
			data.setStatusStr(status != null ? status.getDesc() : "");
		});
		EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelUpgradeOrderDonData.class, list, "订单列表", "订单列表", ExcelTypeEnum.XLSX, null);
	}

	/**
	 * 套餐订单统一退款
	 */
	@PostMapping("/unified/upgrade/refund")
	@Log(module = "套餐订单管理/统一退款", businessType = BusinessType.PUT, isSaveRequestData = true)
	public Result<String> unifiedUpgradeRefund(@RequestBody @Validated OrderRefundReq refundReq) throws Exception {
		long adminId = StpUtil.getLoginIdAsLong();
		CmsUser cmsUser = cmsUserMapper.selectById(adminId);
		if (cmsUser == null) {
			throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
		}
		refundReq.setOperator(cmsUser.getNickname());
		cmsOrderDonService.unifiedUpgradeRefund(refundReq);
		return GatewayResponse.SUCCESS.newBuilder().toResult("退款成功");
	}

	/**
	 * midjourney查询订单用户账号剩余次数
	 */
	@GetMapping("/get/midjourney/user")
	public Result<MidjourneyUserDetailView> getMidjourneyUser(Long orderId) {
		OrderDon orderDon = orderDonMapper.selectById(orderId);
		//续费订单
		Date startTime = null;
		Date expiryTime = null;
		if (orderDon.getOrderType() == 2) {
			GoodsDonSku sku = skuMapper.selectById(orderDon.getSkuId());
			GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
					.eq(GroupsRelation::getId, orderDon.getRelationId())
					.eq(GroupsRelation::getUserId, orderDon.getUserId()).last("limit 1"));
			if (relation == null) {
				return GatewayResponse.SUCCESS.newBuilder().toResult();
			}
			startTime = relation.getStartTime();
			startTime = DateUtil.offsetMonth(startTime, sku.getMonths());
			expiryTime = relation.getExpiryTime();
		}
		MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class)
				.eq(MidjourneyUser::getRelationId, orderDon.getRelationId())
				.last("limit 1"));
		if (midjourneyUser == null) {
			return GatewayResponse.SUCCESS.newBuilder().toResult();
		}
		MidjourneyUserDetailView midjourneyUserDetailView = midjourneyUserConversationMapper.getMjMirrorOrderDetail(orderDon.getRelationId(), startTime, expiryTime);
		GoodsDonSku sku = skuMapper.selectById(orderDon.getSkuId());
		midjourneyUserDetailView.setUserId(orderDon.getUserId());
		midjourneyUserDetailView.setExpiryTime(midjourneyUser.getExpireTime());
		midjourneyUserDetailView.setMjFastNum(sku.getMjFastNum() - midjourneyUserDetailView.getUseFastNum());
		if (sku.getMjRelaxNum() == null) {
			midjourneyUserDetailView.setMjRelaxNum(null);
		} else {
			midjourneyUserDetailView.setMjRelaxNum(sku.getMjRelaxNum() - midjourneyUserDetailView.getUseRelaxNum());
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyUserDetailView);
	}

	/**
	 * 用户退款详情
	 */
	@GetMapping("/get/user/refund/detail")
	public Result<OrderDonUserRefundDetailView> getUserRefundDetail(Long userId) {
		if (userId == null || userId == 0) {
			return GatewayResponse.SUCCESS.newBuilder().toResult();
		}
		List<Long> userIdList = null;
		try {
			userIdList = userBindRelationService.getRelationUserIdList(userId, null);
		} catch (Exception e) {
		}
		String userIds = null;
		if (CollUtil.isNotEmpty(userIdList)) {
			userIds = userIdList.toString().replaceAll("\\[", "").replaceAll("]", "");
		}
		MapBuilder builder = MapUtils.builder();
		if (StrUtil.isNotBlank(userIds)) {
			builder.put("uid", String.format(" and user_id in (%s)", userIds));
		} else {
			builder.put("uid", String.format(" and user_id = %s", userId));
		}
		OrderDonUserRefundDetailView orderDonUserRefundDetailView = beanSearcher.searchFirst(OrderDonUserRefundDetailView.class, builder.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(orderDonUserRefundDetailView);
	}

	/**
	 *  用户订单列表
	 */
	@GetMapping("/get/user/orders")
	public Result<SearchResult<OrderDonUserRefundDetailView.OrderDonDetailView>> getUserOrdersDetail(Long userId) {
		if (userId == null || userId == 0) {
			return GatewayResponse.SUCCESS.newBuilder().toResult();
		}
		List<Long> userIdList = null;
		try {
			userIdList = userBindRelationService.getRelationUserIdList(userId, null);
		} catch (Exception e) {
		}
		if (userIdList == null) {
			userIdList = new ArrayList<>();
			userIdList.add(userId);
		}
		SearchResult<OrderDonUserRefundDetailView.OrderDonDetailView> search = beanSearcher.search(OrderDonUserRefundDetailView.OrderDonDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
				.field(OrderDonUserRefundDetailView.OrderDonDetailView::getUserId, userIdList).op(Operator.InList)
				.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 续费升级订单详情
	 */
	@GetMapping("/renew/orders/detail")
	public Result<RenewOriOrderSkuDto> getRenewOrdersDetail(Long orderId) {
		OrderDon orderDon = orderDonMapper.selectById(orderId);
		if (orderDon.getOrderType() == 2) {
			OrderDonRenewRecord orderDonRenewRecord = orderDonRenewRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonRenewRecord.class)
					.eq(OrderDonRenewRecord::getOrderId, orderDon.getId())
					.last("limit 1"));
			if (orderDonRenewRecord != null) {
				GroupsRelation relation = relationMapper.selectById(orderDon.getRelationId());
				GoodsDonSku sku = skuMapper.selectById(orderDon.getSkuId());
				Date expiryTime = relation.getExpiryTime();
				DateTime lastExpiryTIme = DateUtil.offsetMonth(expiryTime, -sku.getMonths());

				RenewOriOrderSkuDto renewOriOrderSkuDto = new RenewOriOrderSkuDto();
				OriSkuDto oriSku = skuMapper.selectRenewOriSku(orderDonRenewRecord.getOriSkuId());
				renewOriOrderSkuDto.setOriSku(oriSku);
				renewOriOrderSkuDto.setLastExpiryTime(lastExpiryTIme);
				ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class)
						.eq(ChatgptUser::getRelationId, orderDon.getRelationId())
						.last("limit 1"));
				if (chatgptUser != null) {
					renewOriOrderSkuDto.setOrderId(chatgptUser.getRenewOrderId());
				}
				return GatewayResponse.SUCCESS.newBuilder().toResult(renewOriOrderSkuDto);
			}
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	public void setExportOrderInfo(List<ExcelOrderDonData> datas, CountDownLatch countDownLatch) {
		datas.forEach(data -> {
			data.setMoney(data.getMoney().divide(BigDecimal.valueOf(100)));
			OrderDon.Type type = data.getType();
			data.setTypeStr(type != null ? type.getDesc() : "");
			OrderDon.Status status = data.getStatus();
			data.setStatusStr(status != null ? status.getDesc() : "");
			data.setChannel("自然流量渠道");
			if (data.getPopularizeId() != null) {
				Optional.ofNullable(channelPopularizeMapper.selectChannelByPid(data.getPopularizeId()))
						.ifPresent(channelName -> data.setChannel(channelName));
			}
			User user = userMapper.selectById(data.getUserId());
			if (user != null) {
				data.setNickname(user.getNickname());
				data.setRegister(StrUtil.isNotEmpty(user.getUnionid()) ? "wechat" : StrUtil.isNotEmpty(user.getLoginPhone()) ? "phone" : "email");

			}
			if (data.getGoodsDonType() != null && Constant.realGoodsType.contains(data.getGoodsDonType())) {
				OrderDonTransportView transportView = beanSearcher.searchFirst(OrderDonTransportView.class, MapUtils.builder().field(OrderDonTransportView::getOrderId, data.getId()).build());
				if (transportView != null) {
					data.setTransportStr(String.format("%s%s%s%s", transportView.getProvince(), transportView.getCity(), transportView.getDistrict(), transportView.getAddress()));
					data.setPhone(transportView.getPhone());
					data.setReceiver(transportView.getReceiver());
					data.setCodeCn(transportView.getCodeCn());
					data.setTrackingNumber(transportView.getTrackingNumber());
				}
				RealGoodsOrderHandle realGoodsOrderHandle = realGoodsOrderHandleMapper.selectOne(Wrappers.lambdaQuery(RealGoodsOrderHandle.class).eq(RealGoodsOrderHandle::getOrderId, data.getId()).last("limit 1"));
				if (realGoodsOrderHandle != null) {
					data.setBeforeServiceName(realGoodsOrderHandle.getBeforeServiceName());
					data.setAfterServiceName(realGoodsOrderHandle.getAfterServiceName());
				}
			}
			//使用优惠码
			if (data.getCouponId() != null) {
				Optional.ofNullable(couponMapper.selectById(data.getCouponId())).ifPresent(coupon -> data.setCouponName(coupon.getName()));
				data.setCouponMoney(data.getCouponMoney() == null ? BigDecimal.ZERO : data.getCouponMoney());
			}
			if (data.getCouponUserId() != 0) {
				data.setCouponName(couponMapper.getCouponNameByCouponUserId(data.getCouponUserId()));
				data.setCouponMoney(data.getCouponMoney() == null ? BigDecimal.ZERO : data.getCouponMoney());
			}
			//差价订单
			if (data.getGoodsDonType() != null && data.getGoodsDonType() == 5) {
				OrderDonDifferRelateView orderDonDifferRelateView = beanSearcher.searchFirst(OrderDonDifferRelateView.class, MapUtils.builder().field(OrderDonDifferRelateView::getOrderId, data.getId()).build());
				if (orderDonDifferRelateView != null) {
					data.setDiffInfo(orderDonDifferRelateView.getTitle() + "-" + orderDonDifferRelateView.getOperator());
				}
			}
		});
		countDownLatch.countDown();
	}

	/**
	 * 补差价可选平台
	 */
	@GetMapping("/get/diff/goods")
	public Result<List<OrderDonDifferGoods>> getDiffGoods() {
		List<OrderDonDifferGoods> orderDonDifferGoods = beanSearcher.searchAll(OrderDonDifferGoods.class, MapUtils.flatBuilder(request.getParameterMap()).orderBy(OrderDonDifferGoods::getGoodsId).build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(orderDonDifferGoods);
	}

	/**
	 * 新增补差价平台
	 */
	@PostMapping("/post/diff/goods")
	public Result<String> insertDiffGoods(@RequestBody OrderDonDifferGoods orderDonDifferGoods) {
		try {
			orderDonDifferGoodsMapper.insert(orderDonDifferGoods);
		} catch (DuplicateKeyException e) {
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 更新补差价订单关联信息
	 */
	@PutMapping("/update/diff/info")
	public Result<String> updateDiffOrderDonInfo(@RequestBody OrderDonDifferRelate relate) {
		OrderDonDifferRelate orderDonDifferRelate = orderDonDifferRelateMapper.selectOne(Wrappers.lambdaQuery(OrderDonDifferRelate.class)
				.eq(OrderDonDifferRelate::getOrderId, relate.getOrderId())
				.last("limit 1"));
		if (orderDonDifferRelate != null) {
			relate.setId(orderDonDifferRelate.getId());
			orderDonDifferRelateMapper.updateById(relate);
		} else orderDonDifferRelateMapper.insert(relate);
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 用户加购订单车票列表
	 */
	@GetMapping("/get/dp/relations")
	public Result<List<GroupRelationDetailView>> getDpRelations(Long orderId) throws Exception {
		OrderDon orderDon = orderDonMapper.selectById(orderId);
		List relationIds = new ArrayList<>();
		relationIds.add(orderDon.getRelationId());
		OrderDiscountPlusPurchaseSkuRelation orderDiscountPlusPurchaseSkuRelation = plusPurchaseSkuRelationMapper.selectOne(Wrappers.lambdaQuery(OrderDiscountPlusPurchaseSkuRelation.class)
				.eq(OrderDiscountPlusPurchaseSkuRelation::getOrderId, orderId)
				.last("limit 1"));
		if (orderDiscountPlusPurchaseSkuRelation != null && StrUtil.isNotBlank(orderDiscountPlusPurchaseSkuRelation.getRelationIds())) {
			relationIds.addAll(Jsons.parseList(orderDiscountPlusPurchaseSkuRelation.getRelationIds(), Long.class));
		}
		List<GroupRelationDetailView> groupsRelationViews = beanSearcher.searchAll(GroupRelationDetailView.class, MapUtils.builder().field(GroupRelationDetailView::getUserId, orderDon.getUserId()).field(GroupRelationDetailView::getRelationId, relationIds).op(Operator.InList).build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(groupsRelationViews);
	}

	/**
	 * 查看车票账号密码记录
	 */
	@GetMapping("/get/pwd/view/record")
	public Result<SearchResult<TicketPwdViewRecord>> getPwdViewRecord(Long userId, Long relationId, String account) {
		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
		SearchResult<TicketPwdViewRecord> search = beanSearcher.search(TicketPwdViewRecord.class, MapUtils.flatBuilder(request.getParameterMap())
				.field(TicketPwdViewRecord::getUserId, userIdList).op(Operator.InList)
				.field(TicketPwdViewRecord::getRelationId, relationId)
				.field(TicketPwdViewRecord::getAccount, account)
				.orderBy(TicketPwdViewRecord::getId).desc()
				.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}
}
