package com.younike.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.younike.common.config.AmqpDelayedConfig;
import com.younike.common.core.domain.AjaxResult;
import com.younike.common.core.domain.entity.SysUser;
import com.younike.common.core.redis.RedisCache;
import com.younike.common.exception.GlobalException;
import com.younike.common.exception.ServiceException;
import com.younike.common.utils.DateUtils;
import com.younike.common.utils.bean.BeanUtils;
import com.younike.common.utils.geo.DistanceUtil;
import com.younike.common.utils.id.GoodsIndexGenerate;
import com.younike.common.utils.id.OrderIndexGenerate;
import com.younike.common.utils.id.RandomCodeGenerate;
import com.younike.hlpay.dto.OrderParam;
import com.younike.hlpay.dto.PaymentParam;
import com.younike.hlpay.service.IPayService;
import com.younike.system.domain.*;
import com.younike.system.domain.vo.*;
import com.younike.system.enums.*;
import com.younike.system.mapper.*;
import com.younike.system.param.OrderGroupParam;
import com.younike.system.param.OrderPublishParam;
import com.younike.system.param.OrderQueryParam;
import com.younike.system.param.OredrRefundParam;
import com.younike.system.service.*;
import com.younike.wxpay.params.*;
import com.younike.wxpay.responses.NotificationResponse;
import com.younike.wxpay.responses.TransactionResponse;
import com.younike.wxpay.service.ISupplierPayService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.time.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

import static com.younike.common.constant.Constants.EXPIRE_TIME_MINUTES;
import static com.younike.common.constant.Constants.PREFIX_NO_PAY_ORDER;
import static com.younike.common.utils.MoneyUtils.fromCents;
import static com.younike.common.utils.MoneyUtils.toCents;
import static com.younike.system.enums.OrderStateEnum.PENDING_PAYMENT;
import static com.younike.wxpay.enums.TransactionType.*;
import static com.younike.wxpay.utils.Contants.*;
import static com.younike.wxpay.utils.Contants.ADD_PAY_SUFFIX;
import static com.younike.wxpay.utils.Contants.MOD_PAY_SUFFIX;
import static java.math.BigDecimal.ZERO;

/**
 * 订单主Service业务层处理
 *
 * @author elev
 * @date 2022-01-07
 */
@Service
@Log4j2
public class OrderServiceImpl implements IOrderService {
    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private IOrderModifyService orderModifyService;

    @Autowired
    private OrderAddressMapper orderAddressMapper;

    @Autowired
    private IOrderAddressService orderAddressService;

    @Autowired
    private SysConfigMapper sysConfigMapper;

    @Autowired
    private SysCodeMapper sysCodeMapper;

    @Autowired
    private SysDictDataMapper sysDictDataMapper;

    @Autowired
    private OrderRefundMapper orderRefundMapper;

    @Autowired
    private MerchantMapper merchantMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ServerTimeMapper serverTimeMapper;

    @Autowired
    private IServerTimeSectionService serverTimeSectionService;

    @Autowired
    private IMerchantService merchantService;

    /**
     * 会员地址
     */
    @Autowired
    private MemberAddressMapper memberAddressMapper;

    @Autowired
    private IMemberAddressService memberAddressService;

    /**
     * 商品数据
     */
    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private IGoodsService goodsService;

    /**
     * 订单商品
     */
    @Autowired
    private OrderGoodsMapper orderGoodsMapper;

    @Autowired
    private IOrderGoodsService orderGoodsService;

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private IntegralRecordMapper integralRecordMapper;

    @Autowired
    private SysUserMapper sysUserMapper;


    /**
     * 服务人员
     */
    @Autowired
    private IServerUserService serverUserService;

    /**
     * 订单服务人员
     */
    @Autowired
    private IOrderGoodsServerService orderGoodsServerService;
    /**
     * 订单记录
     */
    @Autowired
    private IOrderRecordService orderRecordService;

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private CoinService coinService;
    @Autowired
    private ServerTimeSectionMapper serverTimeSectionMapper;
    @Autowired
    private IOrderRefundService orderRefundService;

    @Autowired
    private ISysCodeService sysCodeService;

    @Autowired
    private IServerTimeBookService serverTimeBookService;

    @Autowired
    private GoodsCommentMapper goodsCommentMapper;

    @Autowired
    private IMemberService memberService;
    @Autowired
    private OrderRecordMapper orderRecordMapper;

    @Autowired
    private GoodsImageMapper goodsImageMapper;

    @Autowired
    private IGoodsServerService goodsServerService;

    @Value("${domain}")
    private String domain;

    @Value("${wechat.xcx.openidUrl}")
    private String xcxOpenIdUrl;

    @Value("${wechat.xcx.appid}")
    private String xcxAppId;

    @Value("${wechat.xcx.secret}")
    private String xcxAppSecret;

    @Autowired
    private IPayService payService;

    @Autowired
    private IOrderPaymentService orderPaymentService;

    @Autowired
    private IMerchantSettleInfoService merchantSettleInfoService;

    /**
     * 商家结算
     */
    @Autowired
    private IMerchantSettleInfoService settleInfoService;


    /**发布需求*/
    @Autowired
    private IPublishService publishService;

    /**需求报价*/
    @Autowired
    private IPublishQuoteService publishQuoteService;

    /**需求服务地址*/
    @Autowired
    private IPublishAddressService publishAddressService;

    /**需求资源*/
    @Autowired
    private IPublishImageService publishImageService;

    /**
     * 商品资源
     */
    @Autowired
    private IGoodsImageService goodsImageService;

    @Autowired
    private AmqpTemplate rabbitTemplate;

    @Autowired
    private ISupplierPayService supplierPayService;

    @Autowired
    private IBondPaymentService bondPaymentService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private UjdChangeRecordMapper ujdChangeRecordMapper;
    /**
     * 团购商品规格
     */
    @Autowired
    private IGoodsSpecificationService iGoodsSpecificationService;

    /**
     * 团购核销记录
     *
     * @param orderRefund
     * @return
     */
    @Autowired
    private IOrderVerificationRecordService orderVerificationRecordService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult doRefund(OrderRefund orderRefund) {
        if (orderRefund == null || StringUtils.isEmpty(orderRefund.getStatus()) || StringUtils.isEmpty(orderRefund.getRefundResult())) {
            return AjaxResult.error("参数错误");
        }
        System.err.println(JSONObject.toJSONString(orderRefund));
        OrderRefund oldRefund = orderRefundService.selectOrderRefundByOrderRefundId(orderRefund.getOrderRefundId());
        if (oldRefund == null) {
            return AjaxResult.error("退款数据不存在");
        }
        if (!"001".equals(oldRefund.getStatus())) {
            return AjaxResult.error("退款数据状态为已处理");
        }
        OrderRefund updateRefund = new OrderRefund();
        updateRefund.setOrderRefundId(orderRefund.getOrderRefundId());
        updateRefund.setStatus(orderRefund.getStatus());
        updateRefund.setRefundResult(orderRefund.getRefundResult());
        updateRefund.setUpdateTime(LocalDateTime.now());

        Order order = orderMapper.selectOrderByOrderId(orderRefund.getOrderId());

        Order updateOrder = new Order();
        updateOrder.setOrderId(oldRefund.getOrderId());
        if (updateRefund.getStatus().equals("003")) {
            // 驳回
            updateOrder.setOrderState("007");
        } else if (updateRefund.getStatus().equals("004")) {
            // 同意
            updateRefund.setRefundMoney(orderRefund.getRefundMoney());

            if (order == null) {
                return AjaxResult.error("退款订单数据错误");
            }
            if (updateRefund.getRefundMoney() == null) {
                return AjaxResult.error("退款金额不能为空");
            }
            if (updateRefund.getRefundMoney().compareTo(new BigDecimal(0)) < 1) {
                return AjaxResult.error("退款金额不能小余0");
            }
            if (updateRefund.getRefundMoney().compareTo(order.getTotalAmount()) == 1) {
                return AjaxResult.error("退款金额不能大于实付金额");
            }

            updateOrder.setOrderState("006");
        } else {
            return AjaxResult.error("数据异常");
        }
        this.updateOrder(updateOrder);
        orderRefundService.updateOrderRefund(updateRefund);

        /**
         * 数据库更新完成之后，再处理外部退款
         */
        if (updateRefund.getStatus().equals("004")) {
            Member member = memberService.selectMemberByMemberId(order.getMemberId());
            Merchant merchant = merchantService.selectMerchantByMerchantId(order.getMerchantId());
            MerchantSettleInfo merchantSettleInfo = merchantSettleInfoService.selectMerchantSettleInfoByMerchantId(order.getMerchantId());
            if (member == null) {
                throw new GlobalException("获取下单用户信息失败");
            }
            if (merchant == null) {
                throw new GlobalException("获取商家信息失败");
            }
            if (merchantSettleInfo == null || StringUtils.isEmpty(merchantSettleInfo.getEmail())) {
                throw new GlobalException("获取商户邮箱失败");
            }
            //todo 退钱，退优金豆
            // 退优金豆
            FamilyParam familyParam = new FamilyParam();
            familyParam.setTargetId(order.getOrderId().toString());    // 设置 关联id
            familyParam.setCode("002");            // 设置 积分变动类型（001-消费 002-退款 003-抵扣 004-评价订单新增）
            familyParam.setPhone(member.getPhone());
            familyParam.setOperation(merchant.getMerchantName());  // 设置 备注（商家名称）
            familyParam.setNum(new BigDecimal(-order.getBeanAmount()));    // 设置 扣除的积分数量

            String integralId = coinService.increasePoints(familyParam);
            if (StringUtils.isBlank(integralId)) {
                throw new GlobalException("退回优金豆失败");
            }

            // 申请微信退款
            merchantService.applyOrderRefund(order, updateRefund.getRefundMoney(), updateRefund.getOrderRefundId());
        }
        return AjaxResult.success();
    }

    @Override
    public List<OrderVo> orderList(OrderQueryParam param) {
        List<OrderVo> orderVoList = orderMapper.orderList(param);
        if (CollectionUtils.isEmpty(orderVoList)) {
            return orderVoList;
        }

        for (OrderVo orderVo : orderVoList) {
            if ("1".equals(orderVo.getMerchantType())) {
                // 个人商家 查询用户名
                SysUser sysUser = sysUserMapper.selectSysUserById(orderVo.getAdminId());
                if (sysUser != null) {
                    orderVo.setMerchantNameJoin(sysUser.getNickName());
                }
            }
            if("003".equals(param.getOrderType())) {
                // 次数
                if (orderVo.getGroupTimes() != null && orderVo.getGroupRemainingTimes() != null) {
                    orderVo.setTimes(orderVo.getGroupRemainingTimes() + "/" + orderVo.getGroupTimes());
                }
            }
        }
        return orderVoList;
    }

    /**
     * 查询订单主
     *
     * @param orderId 订单主主键
     * @return 订单主
     */
    @Override
    public Order selectOrderByOrderId(Long orderId) {
        Order order = orderMapper.selectOrderByOrderId(orderId);
        if (Objects.isNull(order)){
            throw new ServiceException("订单不存在或已被删除");
        }
        return order;
    }

    /**
     * 查询订单主列表
     *
     * @param order 订单主
     * @return 订单主
     */
    @Override
    public List<Order> selectOrderList(Order order) {
        return orderMapper.selectOrderList(order);
    }

    /**
     * 新增订单主
     *
     * @param order 订单主
     * @return 结果
     */
    @Override
    public int insertOrder(Order order) {
        order.setCreateTime(LocalDateTime.now());
        return orderMapper.insertOrder(order);
    }

    /**
     * 修改订单主
     *
     * @param order 订单主
     * @return 结果
     */
    @Override
    public int updateOrder(Order order) {
        order.setUpdateTime(LocalDateTime.now());
        return orderMapper.updateOrder(order);
    }


    /**
     * 批量删除订单主
     *
     * @param orderIds 需要删除的订单主主键
     * @return 结果
     */
    @Override
    public int deleteOrderByOrderIds(Long[] orderIds) {
        return orderMapper.deleteOrderByOrderIds(orderIds);
    }

    /**
     * 删除订单主信息
     *
     * @param orderId 订单主主键
     * @return 结果
     */
    @Override
    public int deleteOrderByOrderId(Long orderId) {
        return orderMapper.deleteOrderByOrderId(orderId);
    }

    /**
     * 修改订单主
     *
     * @param order 订单主
     * @return 结果
     */
    @Override
    public int updateOrderCustom(Order order) {
        // todo 如果是待服务   1.需要获取当前经纬度存下来
        // todo              2.判断距离客户地址是否200米范围内 ，若在范围内才允许更改状态
        //配送范围
//        BigDecimal maxDeliverDistance = BigDecimal.valueOf(merchant.getServiceDistance());

        //根据订单id查订单数据
        Order order1 = orderMapper.selectOrderId(order.getOrderId());
        if(ObjectUtils.isEmpty(order1)){
            return 996;
        }

        OrderRecord orderRecord = new OrderRecord();
        if("002".equals(order.getOrderState())){
            if(!"001".equals(order1.getOrderState())){
                return 997;
            }
            orderRecord.setPreState("001");
            boolean isSameDay = false;
            if(!ObjectUtils.isEmpty(order.getAppointmentStartTime())){
                //今天和服务时间是否为同一天
                isSameDay = DateUtils.isSameDay(Date.from( order.getAppointmentStartTime().atZone( ZoneId.systemDefault()).toInstant()),new Date());
            }
            if(!isSameDay){
                //今天和服务时间不为同一天
                return 998;
            }

            order.setServiceStartTime(LocalDateTime.now());
            BigDecimal maxDeliverDistance = new BigDecimal(sysConfigMapper.checkConfigKeyUnique("home.server.maxDistance").getConfigValue());
            //商家与会员距离
            BigDecimal shortestDistance = null;
            OrderAddress orderAddress = orderAddressMapper.selectOrderAddressByOrderId(order.getOrderId());
            // 计算距离
            shortestDistance = DistanceUtil.getShortestDistance(order.getServiceLatitude(),
                    order.getServiceLongitude(), orderAddress.getAddressLatitude(), orderAddress.getAddressLongitude());

            //验证坐标是否超出范围
            if(shortestDistance.compareTo(maxDeliverDistance)>0){
                //超出配送范围
                return 999;
            }
        }
        if("003".equals(order.getOrderState())){
            if(!"002".equals(order1.getOrderState())){
                return 997;
            }
            order.setServiceEndTime(LocalDateTime.now());
            orderRecord.setPreState("002");
        }

        //根据订单id查询最近一条订单记录数据
        orderRecord.setOrderId(order.getOrderId());
        orderRecord.setNowState(order.getOrderState());
        orderRecord.setOperateInfo(sysCodeService.getDecodeValue("003",order.getOrderState()));
        if(orderRecordService.insertOrderRecord(orderRecord)<1){
            throw new ArithmeticException("添加订单追踪信息失败");
        }

        order.setUpdateTime(LocalDateTime.now());
//        order.setUpdateBy(getUsername());
        return orderMapper.updateOrderCustom(order);
    }

    /**
     * 查询近days天的特定订单状态（orderStates）订单列表
     *
     * @param days 天数
     * @param orderStates 订单状态
     * @return 订单列表
     */
    @Override
    public List<OrderStat> listLastOrders(int days, String[] orderStates) {
        return orderMapper.listLastOrders(days, StringUtils.join(orderStates, ","));
    }

    @Override
    public List<GoodsServerDimension> statisticGoodsServerDimension(int days, String[] orderStates) {
        return orderMapper.statisticGoodsServerDimension(days, StringUtils.join(orderStates, ","));
    }

    /**
     * 查询会员端订单分页列表
     *
     * @param order
     * @return
     */
    @Override
    public List<MemberOrderVo> listMemberOrderByOrderState(Order order) {
        String[] orderStateArr = new String[]{};
        if (StringUtils.isNotEmpty(order.getOrderState())) {
            orderStateArr = order.getOrderState().split(",");
        }

        // 查询会员订单列表
        List<MemberOrderVo> memberOrderVoList = orderMapper.listMemberOrderByOrderState(order, Arrays.asList(orderStateArr));
        if (StringUtils.isNotEmpty(order.getOrderState()) && Objects.equals("004", order.getOrderState())) {
            // 筛选出待评价订单
            memberOrderVoList = memberOrderVoList.stream()
                    .filter(vo -> Objects.equals("001", vo.getCommentState())).collect(Collectors.toList());
        }
        // 查询订单状态等字典值
        if (CollectionUtils.isNotEmpty(memberOrderVoList)) {
            for (MemberOrderVo vo : memberOrderVoList) {
                // 是否追评(默认为0-否)
                vo.setIsAddComment("0");
                // 获取订单状态名称
                vo.setOrderStateName(OrderStateEnum.getDescription(vo.getOrderState()));
                // 获取家政等级名称
                vo.setServerLevelName(ServerLevelEnum.getDescription(vo.getServerLevel()));
                // 处理其他商品单位名称
                if (Objects.equals(vo.getGoodsUnit(), "999")) {
                    vo.setGoodsUnitName(vo.getOtherUnit());
                }
//                } else {
//                    String goodsUnitName = sysDictDataMapper.selectDictLabel("goods_unit", vo.getGoodsUnit());
//                    vo.setGoodsUnitName(goodsUnitName);
//                }
                // 查询评价id
                if (Objects.equals(vo.getCommentState(), "002")) {
                    GoodsComment goodsComment = goodsCommentMapper.getByOrderId(vo.getOrderId());
                    if (goodsComment != null) {
                        vo.setCommentId(goodsComment.getCommontId());
                        vo.setIsAddComment(StringUtils.isBlank(goodsComment.getReContent()) ? "0" : "1");
                    }
                }
                // 查询商品图片列表
                List<GoodsImage> goodsImageList = goodsImageMapper.goodsImageList(Arrays.asList(vo.getGoodsId()));
                vo.setGoodsImageList(goodsImageList);
                // 查询商家类型
                Merchant merchant = merchantService.selectMerchantByMerchantId(vo.getMerchantId());
                vo.setMerchantType(merchant == null ? null : merchant.getMerchantType());
                // 查询评价可得优金豆数量
                Goods goods = goodsMapper.selectGoodsByGoodsId(vo.getGoodsId());
                vo.setCoin(goods == null ? ZERO : goods.getCoin());
            }
        }
        return memberOrderVoList;
    }

    /**
     * 根据订单金额和追加服务金额计算店铺可得
     * @param order
     */
    @Override
    public void calculateShopAmount(Order order) {
        BigDecimal totalAmount = order.getTotalAmount();
        if (Objects.isNull(totalAmount)){
            throw new ServiceException("订单金额不能为空");
        }
        if (Objects.isNull(order.getMerchantId())){
            throw new ServiceException("订单所属商户不能为空");
        }
        Merchant merchant = merchantMapper.selectMerchantByMerchantId(order.getMerchantId());
        BigDecimal platformPercent = new BigDecimal(Optional.ofNullable(
                sysConfigMapper.checkConfigKeyUnique("platform.commission.rate").getConfigValue()).orElse("0"));
        BigDecimal recommenderPercent = Objects.isNull(merchant.getAgentId()) ? ZERO : new BigDecimal(Optional.ofNullable(
                sysConfigMapper.checkConfigKeyUnique("recommender.commission.rate").getConfigValue()).orElse("0"));
        BiFunction<BigDecimal, BigDecimal, BigDecimal> divideBy = (amount, percent) ->
                amount.multiply(percent).divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP);

        // 1. 计算总金额的分成费用
        BigDecimal platformAmount = divideBy.apply(totalAmount, platformPercent);
        BigDecimal recommenderAmount = divideBy.apply(totalAmount, recommenderPercent);
        BigDecimal shopAmount= totalAmount.subtract(platformAmount).subtract(recommenderAmount);
        order.setShopAmount(shopAmount);
        order.setRecommenderAmount(recommenderAmount);
        // 2. 计算追加服务的分成费用
        BigDecimal addAmount = order.getAddAmount();
        if (Objects.isNull(addAmount)){
            addAmount = Objects.isNull(order.getMaintenanceAmount()) ? ZERO: order.getMaintenanceAmount();
        }
        BigDecimal addPlatformAmount = divideBy.apply(addAmount, platformPercent);
        BigDecimal addRecommenderAmount = divideBy.apply(addAmount, recommenderPercent);
        BigDecimal addShopAmount= addAmount.subtract(addPlatformAmount).subtract(addRecommenderAmount);
        order.setAddShopAmount(addShopAmount);
        order.setAddRecommenderAmount(addRecommenderAmount);
    }

    /**
     * 会员下单
     *
     * @param param
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult addOrder(OrderParam param) {
        // 1. 判断是否可以下单
        MemberAddress memberAddress = memberAddressService.selectMemberAddressByAddressId(param.getAddressId());
        Merchant merchant = merchantService.selectMerchantByMerchantId(param.getMerchantId());
        if (outOfMerchantServiceRange(memberAddress, merchant)){
            throw new ServiceException("下单地址不在商家服务范围之内");
        }

        Long goodsId = param.getGoodsId();
        Goods goods = goodsService.selectGoodsByGoodsId(goodsId);
        if (goods.getIsSale() == 0) {
            throw new ServiceException("商品未上架");
        }
        if (goods.getIsSale() == 2) {
            throw new ServiceException("商品已售空");
        }

        Long serverId = param.getServerId();
        ServerUser serverUser = serverUserService.selectServerUserByServerId(serverId);
        if ("1".equals(serverUser.getStatus())){
            throw new ServiceException("该服务人员已被停用，无法下单");
        }

        GoodsServer goodsServer = goodsServerService.getGoodsServer(goodsId, serverId);
        BigDecimal price = param.getPrice();
        if (price.compareTo(goodsServer.getGoodsServerPrice()) != 0){
            throw new ServiceException("商品单价与服务人员当前报价不一致");
        }
        Integer goodsCounts = param.getGoodsCounts();
        if (Objects.isNull(goodsCounts) || goodsCounts <= 0){
            throw new ServiceException("商品数量不能为空且必须大于0");
        }

        // 2. 扣减用户优金豆并占用服务人员可用时间
        subtractMemberCoins(param.getPhone(), param.getGoodsCoin());
        BigDecimal multiply = new BigDecimal(goodsCounts).multiply(goods.getSingleTime());
        LocalDateTime appointmentEndTime = recordAppointmentInfo(param.getAppointmentStartTime(), multiply, serverId, merchant.getAllowCompose());

        // 3. 保存订单信息
        Order order = new Order();
        BeanUtils.copyProperties(param, order);
        order.setAppointmentEndTime(appointmentEndTime);
        order.setMerchantName(merchant.getMerchantName());
        order.setBeanAmount(param.getGoodsCoin());
        order.setCreateTime(LocalDateTime.now());
        calculateShopAmount(order);
        if (orderMapper.addOrder(order) < 1) {
            throw new ServiceException("添加订单失败");
        }
        String index = OrderIndexGenerate.getIndexByOrderId(order.getOrderId());
        order.setOrderIndex(index);
        order.setUpdateTime(LocalDateTime.now());
        if (orderMapper.updateOrderCustom(order) < 1) {
            throw new ServiceException("更新订单编号失败");
        }
        Long orderId = order.getOrderId();
        orderAddressService.saveOrderAddress(orderId, memberAddress);
        orderGoodsService.saveOrderGoodsServerInfo(orderId, goodsId, serverId, price, goodsCounts);
        orderRecordService.recordOrderStatus(orderId, PENDING_PAYMENT, PENDING_PAYMENT);

        log.info("创建订单：未支付：" + order.getOrderId());
        rabbitTemplate.convertAndSend(AmqpDelayedConfig.EXCHANGE_NAME, AmqpDelayedConfig.QUEUE_NAME, PREFIX_NO_PAY_ORDER + order.getOrderId(), message -> {
            message.getMessageProperties().setHeader("x-delay", EXPIRE_TIME_MINUTES * 60 * 1000);
            log.info("创建订单：创建延迟消息：" + AmqpDelayedConfig.QUEUE_NAME);
            return message;
        });
        return AjaxResult.success(order);
    }

    /**
     * 检查下单地址是否在商家的服务范围之内
     * @param memberAddress 下单地址
     * @param merchant 商家
     */
    private boolean outOfMerchantServiceRange(MemberAddress memberAddress, Merchant merchant){
        BigDecimal shortestDistance = DistanceUtil.getShortestDistance( merchant.getLatitude(), merchant.getLongitude(),memberAddress.getLatitude(),
                memberAddress.getLongitude());

        BigDecimal maxDeliverDistance = Objects.isNull(merchant.getServiceDistance()) ?
                new BigDecimal(sysConfigMapper.checkConfigKeyUnique("home.server.distance").getConfigValue()) :
                new BigDecimal(String.valueOf(merchant.getServiceDistance()));

        return shortestDistance.compareTo(maxDeliverDistance) <= 0;
    }

    private void subtractMemberCoins(String phone, Integer amount) {
        if (Objects.isNull(amount) || amount == 0) return;
        if(amount< 0 || amount > 500) {
            throw new ServiceException("优金豆数量必须大于0且不得超过500");
        }
        if (StringUtils.isBlank(phone)) {
            throw new ServiceException("会员手机号不能为空");
        }

        FamilyParam familyParam = new FamilyParam();
        familyParam.setNum(BigDecimal.valueOf(-amount));
        familyParam.setPhone(phone);
        if (!"200".equals(coinService.increasePoints(familyParam))){
            throw new ServiceException("优金豆更新失败");
        }
    }

    /**
     * 保存预约信息，并返回服务的结束时间
     * @param start 服务预约开始时间
     * @param cost 服务时长
     * @param serverId 服务人员id
     * @param allowCompose 是否允许组合时间段配置 0：否，1：是
     * @return 预约结束时间
     */
    @Override
    public LocalDateTime recordAppointmentInfo(LocalDateTime start, BigDecimal cost, Long serverId, Integer allowCompose) {
        // 1. 获取需要的配置信息
        ServerTime serverTime = serverTimeMapper.selectServerTimeByServerId(serverId);
        if(ObjectUtils.isEmpty(serverTime)){
            throw new ServiceException("服务人员查无服务时间");
        }

        // 1. 获取该日期该服务人员的服务时间配置
        DayOfWeek startDay = start.getDayOfWeek();
        Integer dayOfWeek = DayOfWeek.SUNDAY.equals(startDay) ? 0: startDay.getValue();
        List<ServerTimeSection> sectionList = serverTimeSectionService.selectSectionBy(dayOfWeek, serverId);
        if (CollectionUtils.isEmpty(sectionList)){
            throw new ServiceException("未找到服务人员的时间配置信息");
        }

        LocalDateTime appointmentEndTime = start.plusMinutes((long)(cost.doubleValue() * 60));
        ServerTimeSection prev = null;
        for (ServerTimeSection serverTimeSection: sectionList){
            if (Objects.isNull(prev)){
                prev = serverTimeSection;
                continue;
            }
            LocalTime currentStart = serverTimeSection.getHoursFrom();
            LocalTime prevEnd = prev.getHoursEnd();
            if (start.toLocalTime().isBefore(prevEnd) && appointmentEndTime.toLocalTime().isAfter(prevEnd)){
                if(allowCompose == 0){
                    throw new ServiceException("超出可预约的时间范围，下单失败");
                }
                long breakTime = (currentStart.getHour() - prevEnd.getHour()) * 60 + (currentStart.getMinute() - prevEnd.getMinute());
                appointmentEndTime = appointmentEndTime.plusMinutes(breakTime);
            }

        }
        if (appointmentEndTime.toLocalTime().isAfter(sectionList.get(sectionList.size()-1).getHoursEnd())){
            throw new ServiceException("超出可预约的时间范围，下单失败");
        }

        BigDecimal serverGrap = serverTime.getServerGrap();
        LocalDateTime serverEndTime = appointmentEndTime.plusMinutes((long)(serverGrap.doubleValue() * 60));
        // 服务人员预约时间段列表
        if (serverEndTime.getDayOfMonth() > start.getDayOfMonth()){
            serverEndTime = serverEndTime.minusDays(1L).withHour(23).withMinute(30);
        }
        List<ServerTimeBook> serverTimeBookList = serverTimeBookService
                .selectAvailableServerTimeBookList(serverId, start.toLocalDate(),
                        start.toLocalTime(), serverEndTime.toLocalTime());
         if (CollectionUtils.isEmpty(serverTimeBookList)){
            throw new ServiceException("不存在可预约的时间段（请确认该时间是否在该服务人员今天往后一周的工作时间内）");
        }
        for (ServerTimeBook serverTimeBook : serverTimeBookList) {
            if (serverTimeBook.getBooked() == 1) {
                throw new ServiceException("预约时间段中存在已被预约时间段，下单失败");
            }
            if (serverTimeBook.getStartTime().compareTo(appointmentEndTime.toLocalTime()) >= 0) {
                // 服务间隔时间，不可约（2）
                serverTimeBook.setBooked(2);
            } else {
                serverTimeBook.setBooked(1);
            }
        }
        serverTimeBookService.updateServerTimeBooks(serverTimeBookList);
        return appointmentEndTime;
    }


    /**
     * 查询会员订单详情
     *
     * @param orderId
     * @return
     */
    @Override
    public MemberOrderDetailVo getMemberOrderByOrderId(Long orderId) {
        // 查询会员订单详情
        MemberOrderDetailVo memberOrderDetailVo = orderMapper.getMemberOrderByOrderId(orderId);
        if (memberOrderDetailVo == null) {
            return null;
        }
        // 是否追评(默认为0-否)
        memberOrderDetailVo.setIsAddComment("0");
        // 获取商家电话
        Merchant merchant = merchantMapper.selectMerchantByMerchantId(memberOrderDetailVo.getMerchantId());
        //商家头像
        memberOrderDetailVo.setMerchantAvatar(merchant.getAvatar());
        memberOrderDetailVo.setMerchantPhone(merchant == null ? StringUtils.EMPTY : merchant.getMerchantPhone());
        memberOrderDetailVo.setMerchantType(merchant == null ? null : merchant.getMerchantType());
        // 获取订单状态名称
        memberOrderDetailVo.setOrderStateName(OrderStateEnum.getDescription(memberOrderDetailVo.getOrderState()));
        // 获取家政等级名称
        memberOrderDetailVo.setServerLevelName(ServerLevelEnum.getDescription(memberOrderDetailVo.getServerLevel()));
        // 获取服务类别名称
        if (!Objects.isNull(memberOrderDetailVo.getCateId())) {
            Category category = categoryMapper.selectCategoryByCategoryId(memberOrderDetailVo.getCateId());
            memberOrderDetailVo.setCateName(category == null ? StringUtils.EMPTY : category.getCategoryName());
            if (!Objects.isNull(category) && !Objects.isNull(category.getParentId())) {
                // 查询父级分类名称
                Category parentCategory = categoryMapper.selectCategoryByCategoryId(Long.valueOf(category.getParentId()));
                memberOrderDetailVo.setParentCateName(parentCategory == null ? StringUtils.EMPTY : parentCategory.getCategoryName());
            }
        }
        // 获取商品单位名称

        // 处理其他商品单位名称
        if (Objects.equals(memberOrderDetailVo.getGoodsUnit(), "999")) {
            memberOrderDetailVo.setGoodsUnitName(memberOrderDetailVo.getOtherUnit());
        }

//        if (StringUtils.isNotBlank(memberOrderDetailVo.getGoodsUnit())) {
//            String goodsUnitName = sysDictDataMapper.selectDictLabel("goods_unit", memberOrderDetailVo.getGoodsUnit());
//            memberOrderDetailVo.setGoodsUnitName(goodsUnitName);
//        }
        // 已申请退款/已退款
        if (Objects.equals(OrderStateEnum.PENDING_REFUNDED.getCode(), memberOrderDetailVo.getOrderState())
                || Objects.equals(OrderStateEnum.REFUNDED.getCode(), memberOrderDetailVo.getOrderState())
                || Objects.equals(OrderStateEnum.REJECTED.getCode(), memberOrderDetailVo.getOrderState())) {
            // 查询退款信息
            OrderRefund orderRefund = orderRefundMapper.getByOrderId(orderId);
            if (orderRefund != null) {
                memberOrderDetailVo.setPayMoney(orderRefund.getPayMoney());
                memberOrderDetailVo.setRefundReason(orderRefund.getRefundReason());
                memberOrderDetailVo.setRefundMoney(orderRefund.getRefundMoney());
                memberOrderDetailVo.setRefundState(orderRefund.getStatus());
                memberOrderDetailVo.setRefundStateName(OrderRefundStateEnum.getDescription(orderRefund.getStatus()));
            }
        }
        // 查询评价id
        if (Objects.equals(memberOrderDetailVo.getCommentState(), "002")) {
            GoodsComment goodsComment = goodsCommentMapper.getByOrderId(orderId);
            if (goodsComment != null) {
                memberOrderDetailVo.setCommentId(goodsComment.getCommontId());
                memberOrderDetailVo.setIsAddComment(StringUtils.isBlank(goodsComment.getReContent()) ? "0" : "1");
            }
        }
        // 查询商品信息，获取商品是否下架
        Goods goods = goodsMapper.selectGoodsByGoodsId(memberOrderDetailVo.getGoodsId());
        if (goods == null || goods.getIsSale() == 0) {
            memberOrderDetailVo.setIsGoodsClosed("1");
        } else {
            memberOrderDetailVo.setIsGoodsClosed("0");
            if ("001".equals(merchant.getBusinessState())) {
                memberOrderDetailVo.setIsGoodsClosed("0");
            } else {
                memberOrderDetailVo.setIsGoodsClosed("1");
            }

        }
        // 查询商品图片列表
        List<GoodsImage> goodsImageList = goodsImageMapper.goodsImageList(Arrays.asList(memberOrderDetailVo.getGoodsId()));
        memberOrderDetailVo.setGoodsImageList(goodsImageList);

        if("003".equals(memberOrderDetailVo.getOrderType())) {
            //查询订单核销记录
            OrderVerificationRecord orderVerificationRecord = new OrderVerificationRecord();
            orderVerificationRecord.setOrderId(orderId);
            orderVerificationRecord.setDelFlag("0");

            List<OrderVerificationRecord> orderVerificationRecordList = orderVerificationRecordService.selectOrderVerificationRecordList(orderVerificationRecord);
            if(orderVerificationRecordList.size()>0){
                memberOrderDetailVo.setOrderVerificationRecordList(orderVerificationRecordList);
            }
        }

        return memberOrderDetailVo;
    }

    /**
     * 订单支付
     * @param param
     * @return
     */
    @Override
    @Transactional
    public AjaxResult payment(PaymentParam param) {
        // 1. 参数校验
        Long orderId = param.getOrderId();
        Order order = orderMapper.selectOrderByOrderId(orderId);
        if(Objects.isNull(order)){
            return AjaxResult.error("订单不存在");
        }
        if(!"000".equals(order.getOrderState())){
            return AjaxResult.error("订单非支付状态");
        }
        BigDecimal totalAmount = param.getTotalAmount();
        if(Objects.nonNull(totalAmount) && totalAmount.compareTo(order.getOrderAmount()) != 0){
            return AjaxResult.error("付款金额与订单金额不符");
        }

        // 2. 构造并存储支付订单号
        String outTradeNo = order.getOrderIndex();
        OrderModify current = orderModifyService.getLatestRecord(orderId);
        if (Objects.nonNull(current)){
            outTradeNo = outTradeNo + MOD_PAY_SUFFIX + current.getModifyIndex();
        }
        OrderPayment orderPayment = orderPaymentService.selectOrderPaymentByOrderId(orderId);
        OrderPayment data = new OrderPayment();
        data.setOrderId(param.getOrderId());
        data.setPaymentId(outTradeNo);
        int result = Objects.nonNull(orderPayment) ?
                orderPaymentService.updateOrderPayment(data): orderPaymentService.insertOrderPayment(data);
        if (result < 1) {
            throw new ServiceException("订单支付信息保存失败");
        }

        // 3. 调用微信支付
        TransactionResponse response = supplierPayService.transaction(APP,
                TransactionParams.builder()
                        .sub_mchid(merchantSettleInfoService.getMerchantNo(order.getMerchantId()))
                        .description("下单")
                        .out_trade_no(outTradeNo)
                        .notify_url(domain + "member/order/payment/cb")
                        .amount(Amount.pay(toCents(totalAmount)))
                        .build());
        return AjaxResult.success(response);
    }

    /**
     * 追加服务
     * @param param
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult addServer(OrderParam param) {
        // 1. 参数校验
        Long orderId = param.getOrderId();
        Order order = orderMapper.selectOrderByOrderId(orderId);
        if (Objects.isNull(order)){
            throw new ServiceException("订单不存在或已被删除，追加服务失败");
        }
        if (Integer.valueOf(1).equals(order.getAddPayStatus())){
            throw new ServiceException("追加服务已支付，请勿重复提交");
        }

        // 2. 构造并存储支付订单号
        OrderPayment orderPayment = orderPaymentService.selectOrderPaymentByOrderId(orderId);
        String outTradeNo = order.getOrderIndex() + ADD_PAY_SUFFIX + orderPayment.getAddCountIndex() + 1;
        OrderPayment data = new OrderPayment();
        data.setOrderId(param.getOrderId());
        data.setAddPaymentId(outTradeNo);
        data.setAddCountIndex(orderPayment.getAddCountIndex() + 1);
        int result = orderPaymentService.updateOrderPayment(data);
        if (result < 1) {
            throw new ServiceException("订单追加服务支付信息保存失败");
        }

        // 3. 追加信息存入缓存，待支付成功后才更新
        redisCache.setCacheObject(outTradeNo, JSON.toJSON(param),60, TimeUnit.MINUTES);

        // 4. 调用微信支付
        TransactionResponse response = supplierPayService.transaction(APP,
                TransactionParams.builder()
                        .sub_mchid(merchantSettleInfoService.getMerchantNo(order.getMerchantId()))
                        .description("追加服务")
                        .out_trade_no(outTradeNo)
                        .notify_url(domain + "member/order/addServer/cb")
                        .amount(Amount.pay(toCents(param.getAddAmount())))
                        .build());
        return AjaxResult.success(response);
    }

    /**
     * 支付维修配件费
     * @param param
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult addMaintenanceServer(OrderParam param) {
        // 1. 参数校验
        Long orderId = param.getOrderId();
        Order order = orderMapper.selectOrderByOrderId(orderId);
        if (Objects.isNull(order)){
            throw new ServiceException("订单不存在或已被删除，追加维修配件费失败");
        }
        if (Integer.valueOf(1).equals(order.getAddPayStatus())){
            throw new ServiceException("维修配件费已支付，请勿重复提交");
        }

        // 2. 构造并存储支付订单号
        OrderPayment orderPayment = orderPaymentService.selectOrderPaymentByOrderId(orderId);
        String outTradeNo = order.getOrderIndex() + ADD_PAY_SUFFIX + orderPayment.getAddCountIndex() + 1;
        OrderPayment data = new OrderPayment();
        data.setOrderId(param.getOrderId());
        data.setManPaymentId(outTradeNo);
        data.setAddCountIndex(orderPayment.getAddCountIndex() + 1);
        int result = orderPaymentService.updateOrderPayment(data);
        if (result < 1) {
            throw new ServiceException("订单追加维修配件费支付信息保存失败");
        }

        // 3. 调用微信支付
        TransactionResponse response = supplierPayService.transaction(APP,
                TransactionParams.builder()
                        .sub_mchid(merchantSettleInfoService.getMerchantNo(order.getMerchantId()))
                        .description("追加服务")
                        .out_trade_no(outTradeNo)
                        .notify_url(domain + "member/order/addMaintenance/cb")
                        .amount(Amount.pay(toCents(order.getMaintenanceAmount())))
                        .build());
        return AjaxResult.success(response);
    }

    /**
     * 申请平台退款
     * @param param
     * @return
     */
    @Override
    @Transactional
    public AjaxResult applyForRefund(OredrRefundParam param) {
        //根据订单id查询订单数据
        Order order = orderMapper.selectOrderByOrderId(param.getOrderId());
        if (ObjectUtils.isEmpty(order)) {
            return AjaxResult.error("订单不存在");
        }
        // 订单更新前状态
        String oldOrderState = order.getOrderState();
        // 校验订单完成时间是否已经超过24小时(即一天)
        if ("004".equals(order.getOrderState()) && Duration.between(order.getServiceEndTime(), LocalDateTime.now()).toHours() >= 24){
            throw new ServiceException("订单完成已超过24小时，不能退款");
        }
        //查询申请退款记录
        OredrRefundParam refund = orderRefundService.selectOrderId(param.getOrderId());
        if (!ObjectUtils.isEmpty(refund)) {
            return AjaxResult.error("请务重复提交申请");
        }

        order.setOrderState("005");
        order.setUpdateTime(LocalDateTime.now());
        if (orderMapper.updateOrderCustom(order) < 0) {
            throw new ArithmeticException("更新订单信息失败");
        }

        //根据订单id查询最近一条订单记录数据
        OrderRecord orderRecord = orderRecordService.selectRefunfd(order.getOrderId());
        OrderRecord record = new OrderRecord();
        if(!ObjectUtils.isEmpty(orderRecord)){
            record.setPreState(orderRecord.getNowState());
        } else {
            record.setPreState(oldOrderState);
        }
        record.setOrderId(order.getOrderId());
        record.setNowState("005");
        record.setOperateInfo(sysCodeService.getDecodeValue("003","005"));
        if(orderRecordService.insertOrderRecord(record)<1){
            throw new ArithmeticException("添加订单追踪信息失败");
        }

        //添加一条退款处理
        OredrRefundParam oredrRefundParam = new OredrRefundParam();
        BeanUtils.copyProperties(param,oredrRefundParam);
        //需要退回金额是实际付款金额
        oredrRefundParam.setPayMoney(order.getTotalAmount());
        //退款状态
        oredrRefundParam.setStatus("001");
        if(orderRefundService.insertOrderRefund(oredrRefundParam)<1){
            throw new ArithmeticException("添加退款处理记录失败");
        }


        return AjaxResult.success();
    }

    /**
     * 取消订单
     * @param param
     * @return
     */
    @Override
    @Transactional
    public AjaxResult cancal (OredrRefundParam param) {
        //根据订单id查询订单数据
        Order order = orderMapper.selectOrderByOrderId(param.getOrderId());
        if(ObjectUtils.isEmpty(order)){
            return AjaxResult.error("订单不存在");
        }
        if(!"000".equals(order.getOrderState())){
            return AjaxResult.error("订单待服务，不可取消");
        }
        if(!publishService.cancelPublishOrder(param.getOrderId())){
            throw new ArithmeticException("更改服务状态失败");
        }
        order.setOrderState("099");
        order.setUpdateTime(LocalDateTime.now());
        if(orderMapper.updateOrderCustom(order)<=0){
            throw new ArithmeticException("更新订单信息失败");
        }
        //根据订单id查询最近一条订单记录数据
        OrderRecord orderRecord = orderRecordService.selectRefunfd(order.getOrderId());
        OrderRecord record = new OrderRecord();
        if(!ObjectUtils.isEmpty(orderRecord)){
            record.setPreState(orderRecord.getNowState());
        }
        record.setOrderId(order.getOrderId());
        record.setNowState("099");
        record.setOperateInfo(sysCodeService.getDecodeValue("003","099"));
        if(orderRecordService.insertOrderRecord(record)<1){
            throw new ArithmeticException("添加订单追踪信息失败");
        }

        if(!publishService.cancelPublishOrder(param.getOrderId())){
            throw new ArithmeticException("更改服务状态失败");
        }

        // 如果使用优金豆或者优惠券，调用远程接口恢复用户优金豆数量
        if (order.getBeanAmount() != null && order.getBeanAmount() > 0) {
            // 查询会员信息
            Member member = memberMapper.selectMemberByMemberId(order.getMemberId());
            if (member != null) {
                FamilyParam familyParam = new FamilyParam();
                familyParam.setNum(BigDecimal.valueOf(order.getBeanAmount()));
                familyParam.setPhone(member.getPhone());
                familyParam.setCode(BeanPointCodeEnum.REFUNDS.getCode());
                String jsonCode = coinService.increasePoints(familyParam);
                if (Objects.equals(jsonCode, "200")) {
                    // 优金豆增加成功
                    IntegralRecord integralRecord = new IntegralRecord();
                    integralRecord.setChange(order.getBeanAmount());
                    integralRecord.setReason(BeanPointCodeEnum.REFUNDS.getCode());
                    integralRecord.setResult(1);
                    integralRecord.setMsg(JSON.toJSONString(familyParam));
                    int insertIntegralRecord = integralRecordMapper.insertIntegralRecord(integralRecord);
                    if (insertIntegralRecord <= 0) {
                        log.error("订单取消优金豆增加成功，但是优金豆积分变动记录insert失败!integralRecord=" + JSON.toJSONString(integralRecord));
                    }
                } else {
                    // 优金豆增加失败
                    IntegralRecord integralRecord = new IntegralRecord();
                    integralRecord.setChange(order.getBeanAmount());
                    integralRecord.setReason(BeanPointCodeEnum.REFUNDS.getCode());
                    integralRecord.setResult(0);
                    integralRecord.setMsg(JSON.toJSONString(familyParam));
                    int insertIntegralRecord = integralRecordMapper.insertIntegralRecord(integralRecord);
                    if (insertIntegralRecord <= 0) {
                        log.error("订单取消优金豆增加失败，并且优金豆积分变动记录insert失败!integralRecord=" + JSON.toJSONString(integralRecord));
                    }
                }
            } else {
                log.error("订单取消增加优金豆时通过会员id未查询到会员信息!memberId=" + order.getMemberId());
            }
        }

        //判断订单是否是团购订单
        if("003".equals(order.getOrderType())){
            return AjaxResult.success();
        }
        // 取消已预定记录
        cancelBook(order);
        return AjaxResult.success();
    }

    /**
     * 取消已预定记录
     */
    public void cancelBook(Order order) {
        OrderGoodsServer orderGoodsServer = orderGoodsServerService.selectOrderGoodsServerByOrderId(order.getOrderId());
        Long serverId = orderGoodsServer.getServerId();
        ServerTime serverTime = serverTimeMapper.selectServerTimeByServerId(serverId);
        LocalDateTime endTime = order.getAppointmentEndTime().plusMinutes(serverTime.getServerGrap().multiply(BigDecimal.valueOf(60)).longValue());
        // 防止结束时间到了第二天查不出数据
        if (endTime.getDayOfMonth() > order.getAppointmentStartTime().getDayOfMonth()){
            endTime = endTime.minusDays(1L).withHour(23).withMinute(30);
        }
        List<ServerTimeBook> serverTimeBookList = serverTimeBookService
                .selectAvailableServerTimeBookList(serverId, order.getAppointmentStartTime().toLocalDate(),
                        order.getAppointmentStartTime().toLocalTime(), endTime.toLocalTime());
        for (ServerTimeBook serverTimeBook : serverTimeBookList) {
            serverTimeBook.setBooked(0);
        }
        serverTimeBookService.updateServerTimeBooks(serverTimeBookList);
    }

    /**
     * 确认完成
     * @param param
     * @return
     */
    @Override
    @Transactional
    public AjaxResult affirm(OredrRefundParam param) {

        //根据订单id查询订单数据
        Order order = orderMapper.selectOrderByOrderId(param.getOrderId());
        if(ObjectUtils.isEmpty(order)){
            return AjaxResult.error("订单不存在");
        }
        if(!"003".equals(order.getOrderState())){
            return AjaxResult.error("订单不可点击完成");
        }
        order.setUpdateTime(LocalDateTime.now());
        order.setOrderState("004");
        //更新订单数据
        if(orderMapper.updateOrderCustom(order)<1){
            throw new ArithmeticException("订单更新失败");
        }

        //根据订单id查询最近一条订单记录数据
        OrderRecord orderRecord = orderRecordService.selectRefunfd(order.getOrderId());
        OrderRecord record = new OrderRecord();
        if(!ObjectUtils.isEmpty(orderRecord)){
            record.setPreState(orderRecord.getNowState());
        }
        record.setOrderId(order.getOrderId());
        record.setNowState("004");
        record.setOperateInfo(sysCodeService.getDecodeValue("003","004"));
        if(orderRecordService.insertOrderRecord(record)<1){
            throw new ArithmeticException("添加订单追踪信息失败");
        }
        if(! publishService.cancelPublishOrder(param.getOrderId())){
            throw new ArithmeticException("更改服务状态失败");
        }

        return AjaxResult.success();
    }

    /**
     * 取消申请平台介入
     * @param param
     * @return
     */
    @Override
    public AjaxResult cancelRefund(OrderParam param) {
        // 根据订单id查询订单数据
        Order order = orderMapper.selectOrderByOrderId(param.getOrderId());
        if(ObjectUtils.isEmpty(order)){
            return AjaxResult.error("订单不存在");
        }
        // 查询订单退款记录
        OredrRefundParam refund = orderRefundService.selectOrderId(param.getOrderId());
        if(ObjectUtils.isEmpty(refund)){
            return AjaxResult.error("退款申请不存在");
        }
        if(!Objects.equals(OrderStateEnum.PENDING_REFUNDED.getCode(), order.getOrderState())){
            return AjaxResult.error("退款申请已处理，不可取消");
        }

        // 根据订单id查询最近一条订单记录数据
        OrderRecord orderRecord = orderRecordService.selectRefunfd(order.getOrderId());
        order.setUpdateTime(LocalDateTime.now());
        order.setOrderState(orderRecord == null ? OrderStateEnum.FINISHED.getCode() : orderRecord.getPreState());
        // 更新订单数据
        if(orderMapper.updateOrderCustom(order) < 1){
            throw new ServiceException("订单更新失败");
        }

        // 逻辑删除退款记录
        OrderRefund orderRefund = new OrderRefund();
        orderRefund.setOrderRefundId(refund.getOrderRefundId());
        orderRefund.setIsDel(1);
        if(orderRefundService.updateOrderRefund(orderRefund) < 1){
            throw new ServiceException("取消申请平台介入失败");
        }
        // 新增订单追踪记录
        OrderRecord record = new OrderRecord();
        record.setOrderId(order.getOrderId());
        record.setPreState(OrderStateEnum.PENDING_REFUNDED.getCode());
        record.setNowState(order.getOrderState());
        record.setOperateInfo("客户取消退款申请");
        if(orderRecordService.insertOrderRecord(record) < 1){
            throw new ServiceException("添加订单追踪信息失败");
        }
        return AjaxResult.success();

    }

    /**
     * @param settleDate 结算截止时间
     */
    @Override
    public Map<Long, List<Order>> selectPreSettleOrders(Date settleDate) {
        List<Order> list = orderMapper.selectPreSettleOrders(settleDate);
        if (list != null && list.size() > 0) {
            return list.stream().collect(Collectors.groupingBy(Order::getMerchantId));
        }
        return null;
    }

    @Override
    public List<Order> selectPreSettleOrderList(Date settleDate) {
        return orderMapper.selectPreSettleOrders(settleDate);
    }

    @Override
    public List<OrderPaymentVO> selectPreProfitSharingOrders(Date settleDate) {
        return orderMapper.selectPreProfitSharingOrders(settleDate);
    }

    @Override
    public boolean updateBatchById(List<Order> updated) {
        return orderMapper.updateBatchById(updated);
    }

    @Override
    public MerchantDashboardVO dashboard(Long merchantId) {
        // 1. 获取今日订单统计数据
        MerchantDashboardVO result = orderMapper.statisticsToday(merchantId);

        // 2. 统计近30天的订单
        List<OrderStatisticsVO> orderStatisticsVOList = orderMapper.statisticsByMonth(merchantId);
        result.setOrderStatisticsList(orderStatisticsVOList);

        // 3. 获取服务人员订单数top5
        List<ServerUserVo> serverUserVoList = orderMapper.getTopServerUser(merchantId);
        result.setServerUserList(serverUserVoList);

        return result;
    }

    /**
     * 根据订单id查询订单支付状态
     */
    @Override
    public AjaxResult payState(Long orderId) {
        Order order = orderMapper.selectOrderId(orderId);
        if(ObjectUtils.isEmpty(order)){
            return AjaxResult.success("订单不存在",false);
        }
        if(order.getIsSettle()==0){
            return AjaxResult.success("待支付",true);
        }
        return AjaxResult.success("订单已支付",false);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public NotificationResponse paymentCb(TransactionNotificationParams data) {
        if (!"SUCCESS".equals(data.getTrade_state())){
            return NotificationResponse.fail("支付状态异常");
        }
        String outTradeNo = data.getOut_trade_no();
        String orderIndex = outTradeNo.split(",")[0];
        Order order = orderMapper.selectOrderByOrderIndex(orderIndex);
        // 1. 检查订单状态
        if(ObjectUtils.isEmpty(order)){
            return NotificationResponse.fail("订单不存在");
        }
        if(!"000".equals(order.getOrderState())){
            return NotificationResponse.fail("订单状态异常，当前订单非待支付状态");
        }

        // 2. 订单变为已支付
        Order update = new Order();
        update.setOrderId(order.getOrderId());
        update.setOrderState("001");
        update.setUpdateTime(LocalDateTime.now());
        if(orderMapper.updateOrderCustom(order) < 1){
            throw new ServiceException("更新订单信息失败");
        }

        // 3. 记录微信交易id
        OrderPayment orderPayment = orderPaymentService.selectOrderPaymentByOrderId(order.getOrderId());
        orderPayment.setTransactionId(data.getTransaction_id());
        if(orderPaymentService.updateOrderPayment(orderPayment) < 1){
            throw new ServiceException("记录微信交易id信息失败");
        }

        //根据订单id查询最近一条订单记录数据
        OrderRecord orderRecord = orderRecordService.selectRefunfd(order.getOrderId());
        OrderRecord record = new OrderRecord();
        if(!ObjectUtils.isEmpty(orderRecord)){
            record.setPreState(orderRecord.getNowState());
        }
        record.setOrderId(order.getOrderId());
        record.setNowState("001");
        record.setOperateInfo(sysCodeService.getDecodeValue("003","001"));
        if(orderRecordService.insertOrderRecord(record)<1){
            throw new ServiceException("添加订单追踪信息失败");
        }
        log.info("支付回调 -- success");
        return NotificationResponse.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public NotificationResponse paymentAddServerCb(TransactionNotificationParams data) {
        if (!"SUCCESS".equals(data.getTrade_state())){
            return NotificationResponse.fail("支付状态异常");
        }
        String outTradeNo = data.getOut_trade_no();
        OrderParam orderParam = JSONObject.parseObject(redisCache.getCacheObject(outTradeNo), OrderParam.class);
        MemberOrderDetailVo order = orderMapper.getMemberOrderByOrderId(orderParam.getOrderId());
        // 1. 检查订单状态
        if(ObjectUtils.isEmpty(order)){
            return NotificationResponse.fail("订单不存在");
        }
        if (Integer.valueOf(1).equals(order.getAddPayStatus())){
            return NotificationResponse.fail("订单状态异常，已存在支付过的追加服务");
        }

        // 2. 修改订单信息
        Order update = new Order();
        update.setOrderId(order.getOrderId());
        update.setMerchantId(order.getMerchantId());
        update.setTotalAmount(order.getTotalAmount().add(orderParam.getAddAmount()));
        update.setAddAmount(orderParam.getAddAmount());
        calculateShopAmount(update);
        update.setAddPayStatus(1);
        BigDecimal multiply = new BigDecimal(orderParam.getAddCounts()).multiply(order.getSingleTime());
        update.setAppointmentEndTime(order.getAppointmentEndTime().plusHours(multiply.longValue()));
        update.setUpdateTime(LocalDateTime.now());
        if(orderMapper.updateOrderCustom(update) < 1){
            log.error("支付回调 -- 更新订单信息失败");
            throw new ServiceException("更新订单信息失败");
        }

        // 3. 记录微信交易id
        OrderPayment orderPayment = orderPaymentService.selectOrderPaymentByOrderId(order.getOrderId());
        orderPayment.setAddTransactionId(data.getTransaction_id());
        if(orderPaymentService.updateOrderPayment(orderPayment) < 1){
            throw new ServiceException("记录微信交易id信息失败");
        }

        OrderGoods orderGoods = orderGoodsMapper.selectOrderGoodsByOrderId(order.getOrderId());
        if(ObjectUtils.isEmpty(orderGoods)){
            log.error("支付回调 -- 订单商品表不存在失败");
            throw new ArithmeticException("订单商品表不存在失败");
        }
        orderGoods.setAddCounts(orderParam.getAddCounts());
        orderGoods.setUpdateTime(LocalDateTime.now());
        if(orderGoodsMapper.updateOrderGoods(orderGoods)<1){
            log.error("支付回调 -- 订单商品表更新失败");
            throw new ArithmeticException("订单商品表更新失败");
        }

        //订单变更记录
        //根据订单id查询最近一条订单记录数据
        OrderRecord orderRecord = orderRecordService.selectRefunfd(order.getOrderId());
        OrderRecord record = new OrderRecord();
        if(!ObjectUtils.isEmpty(orderRecord)){
            record.setPreState(orderRecord.getNowState());
            record.setNowState(orderRecord.getNowState());
        }
        record.setOrderId(order.getOrderId());
        record.setOperateInfo("追加服务");
        if(orderRecordService.insertOrderRecord(record)<1){
            log.error("支付回调 -- 添加订单追踪信息失败");
            throw new ArithmeticException("添加订单追踪信息失败");
        }
        log.info("支付回调 -- success");
        return NotificationResponse.success();
    }

    @Override
    public NotificationResponse paymentAddMaintanceCb(TransactionNotificationParams data) {
        if (!"SUCCESS".equals(data.getTrade_state())){
            return NotificationResponse.fail("支付状态异常");
        }
        String outTradeNo = data.getOut_trade_no();
        String orderIndex = outTradeNo.split(",")[0];
        Order order = orderMapper.selectOrderByOrderIndex(orderIndex);
        // 1. 检查订单状态
        if(ObjectUtils.isEmpty(order)){
            return NotificationResponse.fail("订单不存在");
        }
        if (Integer.valueOf(1).equals(order.getAddPayStatus())){
            return NotificationResponse.fail("订单状态异常，已存在支付过的追加服务");
        }

        // 2. 修改订单信息
        Order update = new Order();
        update.setOrderId(order.getOrderId());
        update.setAddPayStatus(1);
        update.setUpdateTime(LocalDateTime.now());
        if(orderMapper.updateOrderCustom(order) < 1){
            log.error("支付回调 -- 更新订单信息失败");
            throw new ArithmeticException("更新订单信息失败");
        }

        // 3. 记录微信交易id
        OrderPayment orderPayment = orderPaymentService.selectOrderPaymentByOrderId(order.getOrderId());
        orderPayment.setManTransactionId(data.getTransaction_id());
        if(orderPaymentService.updateOrderPayment(orderPayment) < 1){
            throw new ServiceException("记录微信交易id信息失败");
        }

        OrderRecord orderRecord = orderRecordService.selectRefunfd(order.getOrderId());
        OrderRecord record = new OrderRecord();
        if(!ObjectUtils.isEmpty(orderRecord)){
            record.setPreState(orderRecord.getNowState());
            record.setNowState(orderRecord.getNowState());
        }
        record.setOrderId(order.getOrderId());
        record.setOperateInfo("维修/配件费付款成功");
        if(orderRecordService.insertOrderRecord(record)<1){
            log.error("支付回调 -- 添加订单追踪信息失败");
            throw new ArithmeticException("添加订单追踪信息失败");
        }
        log.info("支付回调 -- success");
        return NotificationResponse.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public NotificationResponse refundCb(RefundNotificationParams data) {
        if (!"SUCCESS".equals(data.getRefund_status())){
            return NotificationResponse.fail("退款状态异常");
        }
        String outRefundNo = data.getOut_refund_no();
        String[] arr = outRefundNo.split("-");
        Long orderRefundId = Long.valueOf(arr[0]);
        boolean isMaster = MASTER_REFUND_FlAG.equals(arr[1]);
        OrderRefund orderRefund = orderRefundService.selectOrderRefundByOrderRefundId(orderRefundId);
        if (Objects.isNull(orderRefund)){
            return NotificationResponse.fail("退款数据不存在或已被删除: " + orderRefundId);
        }

        String refundSuccess = "1";
        if (isMaster){
            if (refundSuccess.equals(orderRefund.getOrderRefundFlag())){
                return NotificationResponse.fail("主订单已退款成功，不能重复退款: " + orderRefundId);
            }
            orderRefund.setOrderRefundFlag(refundSuccess);
        } else {
            if (refundSuccess.equals(orderRefund.getAddRefundFlag())){
                return NotificationResponse.fail("子订单已退款成功，不能重复退款: " + orderRefundId);
            }
            orderRefund.setAddRefundFlag(refundSuccess);
        }
        orderRefund.setRefundMoney(orderRefund.getRefundMoney()
                .add(fromCents(data.getAmount().getRefund())));
        int result = orderRefundService.updateOrderRefund(orderRefund);
        if (result != 1){
            return NotificationResponse.fail("订单退款状态更新失败: " + outRefundNo);
        }
        return NotificationResponse.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public NotificationResponse bondCb(TransactionNotificationParams data) {
        if (!"SUCCESS".equals(data.getTrade_state())){
            return NotificationResponse.fail("支付状态异常");
        }
        String paymentId = data.getOut_trade_no();
        BondPayment bondPayment = bondPaymentService.selectBondPaymentByPaymentId(paymentId);
        if ("001".equals(bondPayment.getBondState())){
            Merchant merchant = merchantService.selectMerchantByMerchantId(bondPayment.getMerchantId());
            BondPayment bondUpdate = new BondPayment();
            bondUpdate.setPaymentId(paymentId);
            bondUpdate.setBondState("002");
            bondPayment.setBondBefore(merchant.getBondMoney());
            bondPayment.setBondAfter(merchant.getBondMoney().add(bondPayment.getBondMoney()));
            bondPaymentService.updateBondPayment(bondUpdate);

            Merchant merchantUpdate = new Merchant();
            merchantUpdate.setMerchantId(bondPayment.getMerchantId());
            merchantUpdate.setBondMoney(bondPayment.getBondAfter());
            // 充值后金额大于0，才将店铺改为已上架
            if (ZERO.compareTo(bondPayment.getBondAfter()) < 0) {
                merchantUpdate.setBusinessState("001");
            }
            merchantService.updateMerchant(merchantUpdate);

            // 新增优金豆变动记录
            UjdChangeRecord ujdChangeRecord = new UjdChangeRecord();
            ujdChangeRecord.setChangeQty(BigDecimal.valueOf(100).multiply(bondPayment.getBondMoney()).intValue());
            ujdChangeRecord.setChangeType(UjdChangeTypeEnum.CASH_DEPOSIT_RECHARGE.getCode());
            ujdChangeRecord.setChangeProperty("1");
            ujdChangeRecord.setChangeTime(LocalDateTime.now());
            ujdChangeRecord.setMerchantId(merchant.getMerchantId());
            ujdChangeRecord.setMerchantIndex(merchant.getMerchantIndex());
            ujdChangeRecord.setMerchantName(merchant.getMerchantName());
            // TODO 支付方式在改动
            ujdChangeRecord.setTradeNo("支付方式更换中");
            // 个人商家，查询用户名称
            if (Objects.equals(merchant.getMerchantType(), 1)) {
                SysUser sysUser = sysUserService.selectSysUserById(merchant.getAdminId());
                ujdChangeRecord.setMerchantName(sysUser == null ? "-" : sysUser.getNickName());
            }
            int ujdChangeRecordInsertResult = ujdChangeRecordMapper.insertUjdChangeRecord(ujdChangeRecord);
            if (ujdChangeRecordInsertResult <= 0) {
                log.error("商家充值保证金-优金豆变动记录保存失败!ujdChangeRecord=" + JSON.toJSONString(ujdChangeRecord));
            }
        }
        return NotificationResponse.success();
    }

    /**
     * 查询会员订单查询追加服务支付结果
     * @param orderId
     * @return
     */
    @Override
    public AjaxResult addServerCb(Long orderId) {
        Order order = orderMapper.selectOrderId(orderId);

        if(ObjectUtils.isEmpty(order)){
            return AjaxResult.success("订单不存在",false);
        }
        if(order.getAddPayStatus() == null || order.getAddPayStatus()==0){
            return AjaxResult.success("待支付",true);
        }
        return AjaxResult.success("订单已支付",false);
    }

    /**
     * 查询会员端未支付订单分页列表
     *
     * @param orderState
     * @return
     */
    @Override
    public List<Order> listMemberOrderOfPendingPayment(String orderState) {
        return orderMapper.listMemberOrderOfPendingPayment(orderState);
    }

    /**
     * 更新超时未支付订单状态
     *
     * @param orderList
     */
    @Override
    public void updateOrderState(List<Order> orderList) {
        orderMapper.updateOrderState(orderList);
    }
    /**
     * 发布需求：预约提交订单
     * @param param
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult addPublishOrder(OrderPublishParam param) {

        //根据需求id查询需求
        Publish publish = publishService.selectPublishByPublishId(param.getPublishId());
        //需求id不为空
           if(ObjectUtils.isEmpty(publish)){
               throw new ArithmeticException("需求不存在");
           }
        //判断发布状态是否为待预约
        if(!"001".equals(publish.getPublishState())){
            throw new ArithmeticException("当前需求不可预约");
        }
        //根据需求id查服务地址
       MemberAddress memberAddress = memberAddressMapper.selectMemberAddressByPublishId(param.getPublishId());
        if(ObjectUtils.isEmpty(memberAddress)){
            throw new ArithmeticException("服务地址不存在");
        }
        //根据需求id查询需求资源数据
        PublishImage publishImage = new PublishImage();
        publishImage.setPublishId(param.getPublishId());
        List<PublishImage> publishImageList = publishImageService.selectPublishImageList(publishImage);
         //根据报价id查询报价数据
        PublishQuote publishQuote = publishQuoteService.selectPublishQuoteByQuoteId(param.getQuoteId());
        if(ObjectUtils.isEmpty(publishQuote)){
            throw new ArithmeticException("报价不存在");
        }
        //查询商家数据
        Merchant merchant = merchantService.selectMerchantByMerchantId(publishQuote.getMerchantId());
        if (ObjectUtils.isEmpty(merchant)) {
            //抛出异常
            throw new ArithmeticException("商家不存在");
        }
        //商家与会员距离
        BigDecimal shortestDistance = null;
        // 计算距离
        shortestDistance = DistanceUtil.getShortestDistance( merchant.getLatitude(), merchant.getLongitude(),memberAddress.getLatitude(),
                memberAddress.getLongitude());

        BigDecimal maxDeliverDistance =null;
        if(merchant.getServiceDistance()==null){
            maxDeliverDistance = new BigDecimal(sysConfigMapper.checkConfigKeyUnique("home.server.distance").getConfigValue());

        }else {
            maxDeliverDistance  = new BigDecimal(String.valueOf(merchant.getServiceDistance()));
        }

        //验证坐标是否超出范围
        if(shortestDistance.compareTo(maxDeliverDistance)>0){
            //超出配送范围
            throw new ArithmeticException("下单失败订单地址超出服务范围");
        }

        //服务总时长为  total_time.getTotalTime
        BigDecimal multiply=publishQuote.getTotalTime();

        // 记录预约信息
        LocalDateTime appointmentEndTime = this.recordAppointmentInfo(param.getAppointmentStartTime(), multiply, publishQuote.getServerUserId(), merchant.getAllowCompose());

        //查询服务人员预约参数
        OrderParam orderParam = new OrderParam();
        orderParam.setAppointmentEndTime(param.getAppointmentEndTime());
        orderParam.setAppointmentStartTime(appointmentEndTime);
        orderParam.setServerId(publishQuote.getServerUserId());

        //创建商品
        Goods goods= new Goods();
        //店铺id为服务人员店铺id
        goods.setMerchantId(publishQuote.getMerchantId());
        //分类id为发布需求分类id
        goods.setCateId(publish.getCateId());
        goods.setName(publish.getName());
        //服务内容为商品描述
        goods.setGoodsIndex(GoodsIndexGenerate.getGoodsIndex());
        goods.setServiceDesc(publish.getPublishDesc());
        goods.setGoodsUnit(publishQuote.getQuoteUnit());
        goods.setOtherUnit(publishQuote.getOtherUnit());
        goods.setSingleTime(publishQuote.getSingleTime());
        //是否上架 0未上架 1已上架 2已售完
        goods.setIsSale(2);
        goods.setOneOff(1);
        goods.setCreateTime(LocalDateTime.now());
       if(goodsMapper.insertGoods(goods)<1){
           throw new ArithmeticException("创建商品失败");
       }
       //判断需求资源是否为空
       if(!ObjectUtils.isEmpty(publishImageList) && publishImageList.size()>0){
           List<GoodsImage> goodsImages = new ArrayList<>();

           publishImageList.forEach( image -> {
               //只存储图片资源
               if("001".equals(image.getType())) {
                   GoodsImage goodsImage = new GoodsImage();
                   BeanUtils.copyProperties(image, goodsImage);
                   goodsImage.setGoodsId(String.valueOf(goods.getGoodsId()));
                   goodsImages.add(goodsImage);
               }
           });
           //批量添加数据
           if (goodsImages.size() > 0) {
               goodsImageService.insertBatch(goodsImages);
           }

       }

       //添加商品服务人员信息数据
        GoodsServer goodsServer = new GoodsServer();
       goodsServer.setGoodsId(goods.getGoodsId());
       goodsServer.setServerId(publishQuote.getServerUserId());
       goodsServer.setGoodsServerPrice(publishQuote.getSinglePrice());
       goodsServer.setCreateTime(LocalDateTime.now());
       if(goodsServerService.insertGoodsServer(goodsServer)<1){
           throw new ArithmeticException("创建商品服务人员信息失败");
       }

        Order order = new Order();
        BeanUtils.copyProperties(param, order);
        //用户
        order.setMemberId(publish.getMemberId());
        order.setMerchantId(merchant.getMerchantId());
        order.setMerchantName(merchant.getMerchantName());
        order.setCreateTime(LocalDateTime.now());
        //订单状态
        order.setOrderState("000");
        //评价状态
        order.setCommentState("001");
        //订单类型
        //根据分类id查询
        Category category = categoryMapper.selectCategoryByCategoryId(publish.getCateId());
        if(ObjectUtils.isEmpty(category)){
            throw new ArithmeticException("分类不存在");
        }
        if(category.getBizType() == 1){
            order.setOrderType("001");
        }
        if(category.getBizType() == 2){
            order.setOrderType("002");
        }
        calculateShopAmount(order);
        order.setAppointmentEndTime(param.getAppointmentStartTime().plusMinutes((long)(multiply.doubleValue() * 60)));
        if (orderMapper.addOrder(order) < 1) {
            throw new ArithmeticException("添加订单失败");
        }
        //生成订单编号
        String index = OrderIndexGenerate.getIndexByOrderId(order.getOrderId());
        //更新数据
        order.setOrderIndex(index);
        order.setUpdateTime(LocalDateTime.now());
        if (orderMapper.updateOrderCustom(order) < 1) {
            throw new ArithmeticException("更新订单编号失败");
        }

        //订单服务地址表
        OrderAddress orderAddress = new OrderAddress();
        BeanUtils.copyProperties(memberAddress, orderAddress);
        orderAddress.setCreateTime(LocalDateTime.now());
        orderAddress.setUpdateTime(LocalDateTime.now());
        orderAddress.setOrderId(order.getOrderId());
        orderAddress.setAddressLongitude(memberAddress.getLongitude());
        orderAddress.setAddressLatitude(memberAddress.getLatitude());
        if (orderAddressMapper.insertOrderAddress(orderAddress) < 1) {
            throw new ArithmeticException("添加订单服务地址表失败");
        }

        //order_goods 订单商品添加数据
        OrderGoods orderGoods = new OrderGoods();
        BeanUtils.copyProperties(goods, orderGoods);
        orderGoods.setOrderId(order.getOrderId());
        orderGoods.setServerId(publishQuote.getServerUserId());
        orderGoods.setGoodsCounts(publishQuote.getQuoteCounts());
        orderGoods.setPrice(publishQuote.getSinglePrice());
        orderGoods.setCreateTime(LocalDateTime.now());
        orderGoods.setUpdateTime(LocalDateTime.now());
        orderGoods.setPublishId(param.getPublishId());
        if (orderGoodsMapper.insertOrderGoods(orderGoods) < 1) {
            throw new ArithmeticException("添加订单商品失败");
        }

        //查询服务人员数据
        ServerUser serverUser = serverUserService.selectServerUserByServerId(publishQuote.getServerUserId());
        if (ObjectUtils.isEmpty(serverUser)) {
            throw new ArithmeticException("服务人员不存在");
        }
        //order_goodes_server 订单服务人员添加数据
        OrderGoodsServer orderGoodsServer = new OrderGoodsServer();
        //订单id
        orderGoodsServer.setOrderId(order.getOrderId());
        //服务人员id
        orderGoodsServer.setServerId(publishQuote.getServerUserId());
        //单次服务标准时长
        orderGoodsServer.setSingleTime(publishQuote.getSingleTime());
        //数量
        orderGoodsServer.setGoodsCounts(publishQuote.getQuoteCounts());
        //商品id
        orderGoodsServer.setGoodsId(goods.getGoodsId());
        //商品名称
        orderGoodsServer.setGoodsName(publish.getName());
        //商品服务人员单价
        orderGoodsServer.setGoodsServerPrice(publishQuote.getSinglePrice());
        //商品单位
        orderGoodsServer.setGoodsUnit(publishQuote.getQuoteUnit());
        //服务人员姓名
        orderGoodsServer.setServerName(serverUser.getNikeName());
        //服务人员性别
        orderGoodsServer.setServerSex(serverUser.getSex());
        //工龄
        orderGoodsServer.setServerAge(serverUser.getAge());
        //服务人员头像
        orderGoodsServer.setServerAvatar(serverUser.getAvatar());
        //所属商铺
        orderGoodsServer.setMerchantId(serverUser.getMerchantId().toString());
        //创建时间
        orderGoodsServer.setCreateTime(LocalDateTime.now());
        orderGoodsServer.setUpdateTime(LocalDateTime.now());
        if (orderGoodsServerService.insertOrderGoodsServer(orderGoodsServer) < 1) {
            throw new ArithmeticException("添加订单服务人员关联数据失败");
        }

        //order_record 添加订单记录
        OrderRecord orderRecord = new OrderRecord();
        orderRecord.setOrderId(order.getOrderId());
        orderRecord.setPreState("000");
        orderRecord.setNowState("000");
        orderRecord.setCreateTime(LocalDateTime.now());
        orderRecord.setUpdateTime(LocalDateTime.now());
        orderRecord.setOperateInfo(sysCodeService.getDecodeValue("003","000"));
        if (orderRecordService.insertOrderRecord(orderRecord) < 1) {
            throw new ArithmeticException("添加订单记录失败");
        }

        //发布需求表进行变更
        //发布状态
        publish.setPublishState("002");
        publish.setBidMerchantId(publishQuote.getMerchantId());
        publish.setBidServerUserId(publishQuote.getServerUserId());
        publish.setUpdateTime(LocalDateTime.now());
        if(publishService.updatePublish(publish)<1){
            throw new ArithmeticException("发布需求状态更改失败");
        }

        if(param.getGoodsCoin()!=null) {
            if(param.getGoodsCoin()>500){
                throw new ArithmeticException("优金豆使用不得超过500");
            }
            //如果使用优金豆或者优惠券，调用远程接口减少用户优金豆数量
            if (param.getGoodsCoin() > 0) {
                FamilyParam familyParam = new FamilyParam();
                familyParam.setNum(BigDecimal.valueOf(-param.getGoodsCoin()));
                familyParam.setPhone(param.getPhone());
                String jsonCode = coinService.increasePoints(familyParam);
                if (!jsonCode.equals("200")) {
                    throw new ArithmeticException("预约失败，优金豆扣除失败");
                }
            }
        }
        log.info("创建订单：未支付：" + order.getOrderId());
        rabbitTemplate.convertAndSend(AmqpDelayedConfig.EXCHANGE_NAME, AmqpDelayedConfig.QUEUE_NAME, PREFIX_NO_PAY_ORDER + order.getOrderId(), message -> {
            message.getMessageProperties().setHeader("x-delay", EXPIRE_TIME_MINUTES * 60 * 1000);
            log.info("创建订单：创建延迟消息：" + AmqpDelayedConfig.QUEUE_NAME);
            return message;
        });

        return AjaxResult.success(order);

    }

    @Override
    public OrderVo selectPublishInfo(Long orderId) {
        return orderMapper.selectPublishInfo(orderId);
    }

    /**
     * 收取维修配件费
     * @param param
     * @return
     */
    @Override
    @Transactional
    public AjaxResult maintenanceServer(OrderParam param) {
        //根据订单id查询订单数据
        Order order = orderMapper.selectOrderByOrderId(param.getOrderId());
        if(ObjectUtils.isEmpty(order)){
            throw new ArithmeticException("订单不存在");
        }
        if(!"002".equals(order.getOrderType())){
            throw new ArithmeticException("订单非维修订单，不可进行收取维修配件费用");
        }
        if(order.getMaintenanceAmount() != null){
            throw new ArithmeticException("不可重复进行收取维修配件费用");
        }
        order.setUpdateTime(LocalDateTime.now());
        order.setMaintenanceRemark(param.getMaintenanceRemark());
        order.setAddPayStatus(0);
        // 重新计算各项费用
        BigDecimal exsitMaintenceAmount = order.getMaintenanceAmount();
        if (exsitMaintenceAmount.compareTo(ZERO) > 0){
            order.setOrderAmount(order.getOrderAmount().subtract(exsitMaintenceAmount));
            order.setTotalAmount(order.getTotalAmount().subtract(exsitMaintenceAmount));
        }
        BigDecimal newMaintenceAmount = param.getMaintenanceAmount();
        if (newMaintenceAmount.compareTo(ZERO) <= 0){
            throw new ServiceException("维修配件费必须大于0");
        }
        order.setOrderAmount(order.getOrderAmount().add(newMaintenceAmount));
        order.setTotalAmount(order.getTotalAmount().add(newMaintenceAmount));
        order.setMaintenanceAmount(newMaintenceAmount);
        calculateShopAmount(order);

       if(orderMapper.updateOrderCustom(order)<1){
           throw new ArithmeticException("收取维修配件费失败");
       }

        //订单变更记录
        //根据订单id查询最近一条订单记录数据
        OrderRecord orderRecord = orderRecordService.selectRefunfd(order.getOrderId());
        OrderRecord record = new OrderRecord();
        if(!ObjectUtils.isEmpty(orderRecord)){
            record.setPreState(orderRecord.getNowState());
            record.setNowState(orderRecord.getNowState());
        }
        record.setOrderId(order.getOrderId());
        record.setOperateInfo("收取维修/配件费");
        if(orderRecordService.insertOrderRecord(record)<1){
            throw new ArithmeticException("添加订单追踪信息失败");
        }
        return AjaxResult.success();
    }

    /**
     * 取消收取维修配件费
     * @param param
     * @return
     */
    @Override
    public AjaxResult cancelMaintenanceServer(OrderParam param) {
        //根据订单id查询数据
        Order order = orderMapper.selectOrderByOrderId(param.getOrderId());
        if(ObjectUtils.isEmpty(order)){
            return AjaxResult.error("订单不存在");
        }
        if(!"002".equals(order.getOrderType())){
            return AjaxResult.error("非维修订单，无配件费");
        }
        if(ObjectUtils.isEmpty(order.getAddPayStatus()) || order.getAddPayStatus()== 0) {

            //更新order数据
            order.setUpdateTime(LocalDateTime.now());
            if (orderMapper.cancelMaintenanceServer(order) < 1) {
                throw new ArithmeticException("取消收费失败");
            }
            //查询最新订单变更记录
            //订单变更记录
            //根据订单id查询最近一条订单记录数据
            OrderRecord orderRecord = orderRecordService.selectRefunfd(order.getOrderId());
            OrderRecord record = new OrderRecord();
            if (!ObjectUtils.isEmpty(orderRecord)) {
                record.setPreState(orderRecord.getNowState());
                record.setNowState(orderRecord.getNowState());
            }
            record.setOrderId(order.getOrderId());
            record.setOperateInfo("取消收取维修/配件费");
            if (orderRecordService.insertOrderRecord(record) < 1) {
                throw new ArithmeticException("添加订单追踪信息失败");
            }
            return AjaxResult.success();
        }
        return AjaxResult.error("维修配件费已经付款，不可取消");


    }

    /**
     * 查询个体户结算订单信息
     *
     * @param settleStartDate
     * @param settleEndDate
     * @return
     */
    @Override
    public Map<Long, List<Order>> listPersonalMerchantSettleOrder(LocalDate settleStartDate, LocalDate settleEndDate) {
        List<Order> orderList = orderMapper.listPersonalMerchantSettleOrder(settleStartDate, settleEndDate);
        if (CollectionUtils.isNotEmpty(orderList)) {
            return orderList.stream().collect(Collectors.groupingBy(Order::getMerchantId));
        }
        return null;
    }

    /**
     * 根据服务id查询是否有订单非已取消与已退款状态
     *
     * @param goodsId
     * @return
     */
    @Override
    public List<Order> adminDeleteGoods(Long goodsId) {
        return orderMapper.adminDeleteGoods(goodsId);
    }

    /**
     * 根据服务人员id查询服务人员是否有未完成的订单
     *
     * @param serverIds
     * @return
     */
    @Override
    public List<Order> merchanServerUserId(Long[] serverIds) {
        return orderMapper.merchanServerUserId(serverIds);
    }

    /**
     * 团购服务：预约提交订单
     *
     * @param param
     * @return
     */
    @Override
    @Transactional
    public AjaxResult addGroupOrder(OrderGroupParam param) {

        Order order = new Order();
        BeanUtils.copyProperties(param, order);
        order.setCouponAmount(new BigDecimal(0));
        /**
         * 查询验证服务数据
         */
        Goods goods = goodsMapper.selectGoodsByGoodsId(param.getGoodsId());
        if (ObjectUtils.isEmpty(goods)) {
            throw new ArithmeticException("商品不存在");
        }
        if (goods.getIsSale() == 2) {
            throw new ArithmeticException("商品已售空");
        }
        if (goods.getIsSale() == 0) {
            throw new ArithmeticException("商品未上架");
        }
        Merchant merchant = merchantService.selectMerchantByMerchantId(param.getMerchantId());
        if (ObjectUtils.isEmpty(merchant)) {
            //抛出异常
            throw new ArithmeticException("商家不存在");
        }
        //根据地址id查询地址数据
        MemberAddress memberAddress = memberAddressMapper.selectMemberAddressByAddressId(param.getAddressId());
        if (ObjectUtils.isEmpty(memberAddress)) {
            //抛出异常
            throw new ArithmeticException("没有此会员地址");
        }
        //商家与会员距离
        BigDecimal shortestDistance = null;
        // 计算距离
        shortestDistance = DistanceUtil.getShortestDistance(merchant.getLatitude(), merchant.getLongitude(), memberAddress.getLatitude(),
                memberAddress.getLongitude());

        //平台抽成比例
        BigDecimal maxDeliverDistance = null;
        if (merchant.getServiceDistance() == null) {
            maxDeliverDistance = new BigDecimal(sysConfigMapper.checkConfigKeyUnique("home.server.distance").getConfigValue());

        } else {
            maxDeliverDistance = new BigDecimal(String.valueOf(merchant.getServiceDistance()));
        }
        //验证坐标是否超出范围
        if (shortestDistance.compareTo(maxDeliverDistance) > 0) {
            //超出配送范围
            throw new ArithmeticException("下单失败订单地址超出服务范围");
        }

        /**
         * 查询服务规格信息
         */
        GoodsSpecification goodsSpecification = iGoodsSpecificationService.selectGoodsSpecificationByGoodsSpecificationId(param.getGoodsSpecificationId());
        if (ObjectUtils.isEmpty(goodsSpecification)) {
            throw new ArithmeticException("服务规格不存在，请重新下单");
        }
        if (!param.getGoodsId().equals(goodsSpecification.getGoodsId())) {
            throw new ArithmeticException("服务规格不存在，请重新下单");
        }

        if (param.getBeanAmount() != null) {
            if (param.getBeanAmount() > 500) {
                throw new ArithmeticException("优金豆使用不得超过500");
            }
            //如果使用优金豆或者优惠券，调用远程接口减少用户优金豆数量
            if (param.getBeanAmount() > 0) {
                FamilyParam familyParam = new FamilyParam();
                familyParam.setNum(BigDecimal.valueOf(-param.getBeanAmount()));
                familyParam.setPhone(param.getPhone());
                String jsonCode = coinService.increasePoints(familyParam);
                if (!jsonCode.equals("200")) {
                    throw new ArithmeticException("预约失败，优金豆扣除失败");
                }
            }
            //优惠金额
            BigDecimal coupoAmount = new BigDecimal(param.getBeanAmount()).divide(new BigDecimal(100));
            order.setCouponAmount(coupoAmount);
        }
        //插入数据
        order.setMerchantName(merchant.getMerchantName());

        order.setOrderType("003");
        order.setOrderState("000");
        order.setOrderAmount(goodsSpecification.getCurrentPrice());
        order.setTotalAmount(order.getOrderAmount().subtract(order.getCouponAmount()));
        //有效期（当前时间加上有效期天+1）
        if(goods.getExpirationDateValue()>0) {
            order.setVerificationCodeEffectiveDate(LocalDateTime.now().plusDays(goods.getExpirationDateValue()));
        }
        /**
         * 生成订单核销码
         * order_verification_code
         */
        order.setOrderVerificationCode(RandomCodeGenerate.getOrderVerificationCode());

        order.setGroupTimes(goodsSpecification.getTimes());
        order.setGroupRemainingTimes(goodsSpecification.getTimes());
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());
        //分账数据计算
        this.calculateShopAmount(order);

        if (orderMapper.insertOrder(order) < 1) {
            throw new ArithmeticException("创建订单失败");
        }
        //生成订单编号
        String index = OrderIndexGenerate.getIndexByOrderId(order.getOrderId());
        //更新数据
        order.setOrderIndex(index);
        order.setUpdateTime(LocalDateTime.now());
        if (orderMapper.updateOrderCustom(order) < 1) {
            throw new ArithmeticException("更新订单编号失败");
        }
        /**
         *订单服务地址表
         */
        //订单服务地址表
        OrderAddress orderAddress = new OrderAddress();
        BeanUtils.copyProperties(memberAddress, orderAddress);
        orderAddress.setCreateTime(LocalDateTime.now());
        orderAddress.setUpdateTime(LocalDateTime.now());
        orderAddress.setOrderId(order.getOrderId());
        orderAddress.setAddressLongitude(memberAddress.getLongitude());
        orderAddress.setAddressLatitude(memberAddress.getLatitude());
        if (orderAddressMapper.insertOrderAddress(orderAddress) < 1) {
            throw new ArithmeticException("添加订单服务地址表失败");
        }
        /**
         * 订单商品表
         */
        //order_goods 订单商品添加数据
        OrderGoods orderGoods = new OrderGoods();
        BeanUtils.copyProperties(goods, orderGoods);
        orderGoods.setOrderId(order.getOrderId());
        orderGoods.setServerId(param.getServerId());
        orderGoods.setGoodsCounts(1);
        orderGoods.setPrice(goodsSpecification.getCurrentPrice());
        orderGoods.setGoodsSpecificationId(param.getGoodsSpecificationId());
        orderGoods.setCreateTime(LocalDateTime.now());
        orderGoods.setUpdateTime(LocalDateTime.now());
        if (orderGoodsMapper.insertOrderGoods(orderGoods) < 1) {
            throw new ArithmeticException("添加订单商品失败");
        }

        //order_record 添加订单记录
        OrderRecord orderRecord = new OrderRecord();
        orderRecord.setOrderId(order.getOrderId());
        orderRecord.setPreState("000");
        orderRecord.setNowState("000");
        orderRecord.setCreateTime(LocalDateTime.now());
        orderRecord.setUpdateTime(LocalDateTime.now());
        orderRecord.setOperateInfo(sysCodeService.getDecodeValue("003", "000"));
        if (orderRecordService.insertOrderRecord(orderRecord) < 1) {
            throw new ArithmeticException("添加订单记录失败");
        }
        log.info("创建订单：未支付：" + order.getOrderId());
        rabbitTemplate.convertAndSend(AmqpDelayedConfig.EXCHANGE_NAME, AmqpDelayedConfig.QUEUE_NAME, PREFIX_NO_PAY_ORDER + order.getOrderId(), message -> {
            message.getMessageProperties().setHeader("x-delay", EXPIRE_TIME_MINUTES * 60 * 1000);
            log.info("创建订单：创建延迟消息：" + AmqpDelayedConfig.QUEUE_NAME);
            return message;
        });
        return AjaxResult.success(order);

    }

    /**
     * 查询会员团购订单详情
     *
     * @param orderId
     * @return
     */
    @Override
    @Transactional
    public MemberOrderDetailVo getMemberGroupOrderByOrderId(Long orderId) {
        MemberOrderDetailVo memberOrderDetailVo = this.getMemberOrderByOrderId(orderId);

        /**
         * 查询核销记录
         */
        OrderVerificationRecord orderVerificationRecord = new OrderVerificationRecord();
        orderVerificationRecord.setOrderId(orderId);
        orderVerificationRecord.setAppointmentStatus("001");
        List<OrderVerificationRecord> orderVerificationRecordList = orderVerificationRecordService.selectOrderVerificationRecordList(orderVerificationRecord);
        if (orderVerificationRecordList.size() > 0) {
            //预约时间
            memberOrderDetailVo.setAppointmentTime(orderVerificationRecordList.get(0).getAppointmentTime());
            memberOrderDetailVo.setAppointmentStatus("001");
        } else {
            memberOrderDetailVo.setAppointmentStatus("002");
        }

            //判断核销记录是否为空
        if(!ObjectUtils.isEmpty(memberOrderDetailVo.getOrderVerificationRecordList())) {
            //当核销记录不为空的时候判断当前核销码是否使用过
            for (OrderVerificationRecord ovr:memberOrderDetailVo.getOrderVerificationRecordList()) {
                if(memberOrderDetailVo.getOrderVerificationCode().equals(ovr.getOrderVerificationCode())){
                    Order order = new Order();
                    order.setOrderId(memberOrderDetailVo.getOrderId());
                    order.setOrderVerificationCode(RandomCodeGenerate.getOrderVerificationCode());
                    if(orderMapper.updateOrderCustom(order)<1){
                        throw new ArithmeticException("更新核销码失败");
                    }
                    memberOrderDetailVo.setOrderVerificationCode(order.getOrderVerificationCode());
                }
            }
        }
        return memberOrderDetailVo;

    }


    /**
     * 查询今日订单数据
     *
     * @return
     */
    @Override
    public TodayOrderVO getTodayOrderData() {
        return orderMapper.getTodayOrderData();
    }

    /**
     * 查询本周Top5商家订单数据
     *
     * @return
     */
    @Override
    public List<MerchantOrderOfWeekVO> getTopFiveMerchantOrderData() {
        return orderMapper.getTopFiveMerchantOrderData();
    }

    /**
     * 查询近30天订单数据
     *
     * @return
     */
    @Override
    public List<OrderStatisticsVO> getOrderDataByMonth() {
        return orderMapper.getOrderDataByMonth();
    }

    /**
     * 获取微信OpenID
     *
     * @param code 微信授权code
     */
    private String getOpenId(String code) {
        if (StringUtils.isBlank(code)){
            throw new ServiceException("微信授权code不存在，获取openid失败");
        }
        //微信的接口url地址
        String url = xcxOpenIdUrl + "?appid=" + xcxAppId +
                "&secret=" + xcxAppSecret + "&js_code=" + code + "&grant_type=authorization_code";
        RestTemplate restTemplate = new RestTemplate();
        //进行网络请求,访问url接口
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
        if (responseEntity.getStatusCode() == org.springframework.http.HttpStatus.OK) {
            String sessionData = responseEntity.getBody();
            //下面是把拿到的json字符串转成 json对象
            com.alibaba.fastjson.JSONObject jsStr = com.alibaba.fastjson.JSONObject.parseObject(sessionData);
            //解析从微信服务器获得的openid和session_key;获取用户的唯一标识
            return jsStr.getString("openid");
        }
        log.error("获取OpenId失败, code：" + code + "，\n 返回："  + JSON.toJSONString(responseEntity));
        throw new ServiceException("获取OpenId失败");
    }

}
