package org.jeecg.modules.app.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.DictAnnotationUtil;
import org.jeecg.modules.app.dto.AppOrderInfoDTO;
import org.jeecg.modules.app.form.CreateOrderForm;
import org.jeecg.modules.app.form.InsureOrderInfoForm;
import org.jeecg.modules.app.form.PageOrdersForm;
import org.jeecg.modules.app.form.UserPayForm;
import org.jeecg.modules.app.service.IOrderService;
import org.jeecg.modules.app.service.WeChatPayService;
import org.jeecg.modules.app.vo.AppGameScheduleVO;
import org.jeecg.modules.app.vo.OrderVO;
import org.jeecg.modules.app.vo.PageOrdersVO;
import org.jeecg.modules.app.vo.QueryOrderVerifyRecordsVO;
import org.jeecg.modules.pay.config.WechatConstants;
import org.jeecg.modules.pay.config.WechatUrlConstants;
import org.jeecg.modules.pay.vo.NotifyRequest;
import org.jeecg.modules.pay.vo.NotifyResponse;
import org.jeecg.modules.redission.RedissonDelayQueue;
import org.jeecg.modules.system.app.dto.receiptPaymentDetails.ReceiptPaymentDetailsInfoVo;
import org.jeecg.modules.system.app.entity.*;
import org.jeecg.modules.system.app.mapper.*;
import org.jeecg.modules.system.app.service.IReceiptPaymentDetailsInfoService;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.mapper.SysDepartMapper;
import org.jeecg.modules.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static org.jeecg.modules.hikiot.HikiotTool.addFace;
import static org.jeecg.modules.hikiot.HikiotTool.addUser;

@Service
@Log4j2
public class OrderServiceImpl implements IOrderService {
    @Resource
    private AppSitePlaceMapper appSitePlaceMapper;
    @Resource
    private AppSitePriceRulesMapper appSitePriceRulesMapper;
    @Resource
    private AppCoursesMapper appCoursesMapper;
    @Resource
    private AppOrderMapper appOrderMapper;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private AppSiteMapper appSiteMapper;
    @Resource
    private AppIsinMapper appIsinMapper;
    @Resource
    private FamilyMembersMapper familyMembersMapper;
    @Resource
    private AppTeachingTimeMapper appTeachingTimeMapper;
    @Resource
    private InsureOrderInfoMapper insureOrderInfoMapper;
    @Resource
    private AppInsureMapper appInsureMapper;
    @Resource
    private AppOrderProInfoMapper appOrderProInfoMapper;
    @Resource
    private AppContractInfoMapper appContractInfoMapper;
    @Resource
    private AppGamePriceRulesMapper appGamePriceRulesMapper;
    @Resource
    private AppGameMapper appGameMapper;
    @Resource
    private AppGameScheduleMapper appGameScheduleMapper;
    @Resource
    private InsurePriceMapper insurePriceMapper;
    @Resource
    private AppCoursesPriceRulesMapper appCoursesPriceRulesMapper;
    @Resource
    private AppCoursesVerificationRecordMapper appCoursesVerificationRecordMapper;
    @Resource
    private AppContractSignMapper appContractSignMapper;
    @Resource
    private RedissonDelayQueue redissonDelayQueue;
    @Resource
    private AppDeviceMapper appDeviceMapper;
    @Resource
    private WeChatPayService weChatPayService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    IReceiptPaymentDetailsInfoService iReceiptPaymentDetailsInfoService;

    @Autowired
    SysDepartMapper sysDepartMapper;
    @Autowired
    SeparateAccountsMapper separateAccountsMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderVO.createOrderPlaceSchool createOrderPlaceSchool(String rulesId, String userIds) {
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        List<String> list = Arrays.asList(rulesId.split(","));
        AppOrder order = createOrder(list, 0, user.getId(), userIds);
        if (null == order) throw new JeecgBootException("创建订单失败!");
        AppSitePriceRules appSitePriceRules = appSitePriceRulesMapper.selectById(list.get(0));
        AppSitePlace appSitePlace = appSitePlaceMapper.selectById(appSitePriceRules.getSitePlaceId());
        AppSite appSite = appSiteMapper.selectById(appSitePlace.getSiteId());
        OrderVO.createOrderPlaceSchool result = new OrderVO.createOrderPlaceSchool();
        List<OrderVO.couponNumberInformation> couponNumberInformation = new ArrayList<>();
        List<AppIsin> appIsins = appIsinMapper.selectList(Wrappers.<AppIsin>lambdaQuery().eq(AppIsin::getOrderId, order.getId()));
        appIsins.forEach(appIsin -> {
            OrderVO.couponNumberInformation information = new OrderVO.couponNumberInformation();
            information.setId(appIsin.getId())
                    .setCouponCode(appIsin.getTicketNo())
                    .setCouponStatus(appIsin.getIsinStatus())
                    .setExpireTime(appIsin.getExpireTime())
                    .setUserName(familyMembersMapper.selectById(appIsin.getFamilyId()).getFullName());
            couponNumberInformation.add(information);
        });
        result.setId(order.getId())
                .setOrderStatus(order.getOrderStatus())
                .setPlaceName(appSitePlace.getName())
                .setDate(appSitePriceRules.getDateOfSale())
                .setUserName(user.getRealname())
                .setAddress(appSite.getAddress())
                .setLongitude(appSite.getLongitude())
                .setLatitude(appSite.getLatitude())
                .setReminder(appSitePlace.getReminder())
                .setOrderCode(order.getOrderCode())
                .setMobile(user.getPhone())
                .setCreateTime(order.getCreateTime())
                .setPayTime(order.getPayTime())
                .setCouponNumberInformation(couponNumberInformation);
        return result;
    }

    @Override
    public boolean checkCourseLimitNum(String courseId, int limitNum) {
        return appCoursesMapper.selectById(courseId).getLimitNum() >= limitNum;
    }

    private List<OrderVO.TimeSlotData> parseTimeSlotData(String timeSlot) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode teachingDays = objectMapper.readTree(timeSlot);
            List<OrderVO.TimeSlotData> teachingList = new ArrayList<>();
            for (JsonNode node : teachingDays.get("data")) {
                OrderVO.TimeSlotData data = objectMapper.treeToValue(node, OrderVO.TimeSlotData.class);
                teachingList.add(data);
            }
            return teachingList;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public OrderVO.PreviewOrderPlaceSchool previewOrderPlaceSchool(String placeId, Date startTime) {
        LocalDate localDate = startTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        Date dateOnly = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
        OrderVO.PreviewOrderPlaceSchool previewOrderPlaceSchool = new OrderVO.PreviewOrderPlaceSchool();
        AppSite appSite = appSiteMapper.selectOne(Wrappers.<AppSite>lambdaQuery().eq(AppSite::getId, appSitePlaceMapper.selectById(placeId).getSiteId()));
        List<OrderVO.PreviewOrderPlaceSchoolChild> timeSlot = appSitePriceRulesMapper.timeSlot(placeId, dateOnly);
        // 解析教学日和非教学日数据
        List<OrderVO.TimeSlotData> teachingList = parseTimeSlotData(appSite.getTeachingDay());
        List<OrderVO.TimeSlotData> nonTeachingList = parseTimeSlotData(appSite.getNoTeachingDay());

        timeSlot.forEach(a -> {
            LocalTime slotStart = LocalTime.parse(DateUtil.format(a.getStartTime(), "HH:mm"));
            LocalTime slotEnd = LocalTime.parse(DateUtil.format(a.getEndTime(), "HH:mm"));
            boolean isTeaching = a.getIsTeaching() == 0;

            List<OrderVO.TimeSlotData> targetList = isTeaching ? teachingList : nonTeachingList;

            Optional<OrderVO.TimeSlotData> matchedSlot = targetList.stream()
                    .filter(t -> {
                        LocalTime invStart = LocalTime.parse(t.getStartTime());
                        LocalTime invEnd = LocalTime.parse(t.getEndTime());
                        return !slotStart.isAfter(invEnd) && !slotEnd.isBefore(invStart);
                    })
                    .findFirst();

            matchedSlot.ifPresent(timeSlotData -> {
                int totalInventory = Integer.parseInt(timeSlotData.getTicketNum());
                int bookedCount = appOrderMapper.queryBookedCount(
                        placeId,
                        DateUtil.format(startTime, "yyyy-MM-dd"),
                        timeSlotData.getStartTime(),
                        timeSlotData.getEndTime()
                );
                int availableInventory = totalInventory - bookedCount;
                a.setInventory(availableInventory);
            });
        });
        AppSitePlace appSitePlace = appSitePlaceMapper.selectById(placeId);
        previewOrderPlaceSchool.setName(appSite.getName())
                .setId(appSitePlace.getId())
                .setTimeSlot(timeSlot);
        if (StringUtils.isNotEmpty(appSitePlace.getInsureIds())) {
            List<String> aptitudesList = new ArrayList<>();
            if (appSitePlace.getInsureIds().indexOf(",") > 0) {
                aptitudesList = Arrays.asList(appSitePlace.getInsureIds().split(","));
            } else {
                aptitudesList.add(appSitePlace.getInsureIds());
            }
            LambdaQueryWrapper<AppInsure> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(AppInsure::getId, aptitudesList)
                    .eq(AppInsure::getStatus, 0)
                    .eq(AppInsure::getDelFlag, 0);  // 方法引用 + 集合
            List<AppInsure> appInsureList = appInsureMapper.selectList(wrapper);
            DictAnnotationUtil.translateDictList(appInsureList);
            for (AppInsure appInsure : appInsureList) {
                List<InsurePrice> insurePrices = insurePriceMapper.selectList(new QueryWrapper<InsurePrice>().lambda().eq(InsurePrice::getInsureId, appInsure.getId()).eq(InsurePrice::getDelFlag, 0).orderByAsc(InsurePrice::getInsureDay));
                appInsure.setPriceDataList(insurePrices);
            }
            previewOrderPlaceSchool.setInsureIdList(appInsureList);
        }
        return previewOrderPlaceSchool;
    }

    @Override
    public OrderVO.PreviewOrderCourse previewOrderCourse(String courseId) {
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        OrderVO.PreviewOrderCourse previousOrderCourse = new OrderVO.PreviewOrderCourse();
        AppCourses appCourses = appCoursesMapper.selectById(courseId);
        if (appCourses == null || StringUtils.isEmpty(appCourses.getCover())) {
            throw new JeecgBootException("未查询到课程数据");
        }
        List<String> list = Arrays.asList(appCourses.getCover().split(","));
        boolean checkCourseDiscount = checkCourseDiscount(appCourses.getCategoryId(), user.getId());
        previousOrderCourse.setId(appCourses.getId())
                .setCover(list.get(0).split(",")[0])
                .setName(appCourses.getName())
                .setSellingPrice(appCourses.getOriginalPrice())
                .setReminder(appCourses.getReminder())
                .setHasDiscount(checkCourseDiscount);
        if (checkCourseDiscount) {
            previousOrderCourse.setDiscountPrice(appCourses.getOriginalPrice());
            previousOrderCourse.setTotalDiscount(appCourses.getOriginalPrice());
            previousOrderCourse.setSubtotal(appCourses.getSellingPrice().subtract(appCourses.getSellingPrice()));
            previousOrderCourse.setTotalPrice(appCourses.getSellingPrice());
        } else {
            previousOrderCourse.setDiscountPrice(BigDecimal.ZERO);
            previousOrderCourse.setTotalDiscount(BigDecimal.ZERO);
            previousOrderCourse.setSubtotal(appCourses.getSellingPrice());
            previousOrderCourse.setTotalPrice(appCourses.getSellingPrice());
        }

        if (StringUtils.isNotEmpty(appCourses.getInsureIds())) {
            List<String> aptitudesList = new ArrayList<>();
            if (appCourses.getInsureIds().indexOf(",") > 0) {
                aptitudesList = Arrays.asList(appCourses.getInsureIds().split(","));
            } else {
                aptitudesList.add(appCourses.getInsureIds());
            }
            LambdaQueryWrapper<AppInsure> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(AppInsure::getId, aptitudesList)
                    .eq(AppInsure::getStatus, 0)
                    .eq(AppInsure::getDelFlag, 0);  // 方法引用 + 集合
            List<AppInsure> appInsureList = appInsureMapper.selectList(wrapper);
            DictAnnotationUtil.translateDictList(appInsureList);
            for (AppInsure appInsure : appInsureList) {
                List<InsurePrice> insurePrices = insurePriceMapper.selectList(new QueryWrapper<InsurePrice>().lambda().eq(InsurePrice::getInsureId, appInsure.getId()).eq(InsurePrice::getDelFlag, 0).orderByAsc(InsurePrice::getInsureDay));
                appInsure.setPriceDataList(insurePrices);
            }
            previousOrderCourse.setInsureIdList(appInsureList);
        }
        return previousOrderCourse;
    }

    @Override
    public OrderVO.PreviewOrderPlaceGymnasiumChartered previewOrderPlaceGymnasiumChartered(String rulesId) {
        List<String> list = Arrays.asList(rulesId.split(","));
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        OrderVO.PreviewOrderPlaceGymnasiumChartered result = new OrderVO.PreviewOrderPlaceGymnasiumChartered();
        List<AppSitePriceRules> priceRules = new ArrayList<>();
        list.forEach(priceRule -> {
            AppSitePriceRules appSitePriceRule = appSitePriceRulesMapper.selectById(priceRule);
            priceRules.add(appSitePriceRule);
        });
        BigDecimal totalPrice = priceRules.stream()
                .map(AppSitePriceRules::getSellingPrice)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        // 格式化 totalPrice 和 subtotal 为两位小数
        totalPrice = totalPrice.setScale(2, BigDecimal.ROUND_HALF_UP);
        String formattedTotalPrice = totalPrice.toString(); // 直接使用 toString() 保留两位小数
        String formattedSubtotal = totalPrice.toString();   // 小计与总价相同
        result.setTotalPrice(new BigDecimal(formattedTotalPrice)); // 设置格式化后的 totalPrice
        result.setSubtotal(new BigDecimal(formattedSubtotal));
        if (priceRules.isEmpty()) {
            throw new IllegalArgumentException("未找到对应的价格规则");
        }
        AppSitePlace sitePlace = appSitePlaceMapper.selectById(priceRules.get(0).getSitePlaceId());
        if (sitePlace == null) {
            throw new IllegalStateException("关联场地不存在");
        }
        List<OrderVO.PreviewOrderTimePeriod> timePeriod = appSitePriceRulesMapper.previewOrderPlaceGymnasiumChartered(list);
        AppSite appSite = appSiteMapper.selectOne(Wrappers.<AppSite>lambdaQuery()
                .eq(AppSite::getOrgCode, sitePlace.getOrgCode()));
        return result.setTimePeriod(timePeriod)
                .setEarlyRefundTime(sitePlace.getEarlyRefundTime())
                .setPlaceId(sitePlace.getId())
                .setPlaceName(sitePlace.getName())
                .setReminder(sitePlace.getReminder())
                .setRefundRule(sitePlace.getEarlyRefundTime())
                .setMobile(user.getPhone())
                .setTotalPrice(totalPrice)  // 总价即为所有价格之和
                .setSubtotal(totalPrice)    // 小计与总价相同
                .setStoreName(appSite != null ? appSite.getName() : "未知门店");
    }

    @Override
    public List<OrderVO.PreviewOrderPlaceSchoolTime> previewOrderPlaceSchoolTime(String placeId) {
        List<OrderVO.PreviewOrderPlaceSchoolTime> previewOrderPlaceSchoolTimes = appTeachingTimeMapper.previewOrderPlaceSchoolTime(appSitePlaceMapper.selectById(placeId).getOrgCode());
        AppSite appSite = appSiteMapper.selectOne(Wrappers.<AppSite>lambdaQuery().eq(AppSite::getId, appSitePlaceMapper.selectById(placeId).getSiteId()));
        // 解析教学日和非教学日数据
        List<OrderVO.TimeSlotData> teachingList = parseTimeSlotData(appSite.getTeachingDay());
        List<OrderVO.TimeSlotData> nonTeachingList = parseTimeSlotData(appSite.getNoTeachingDay());
        previewOrderPlaceSchoolTimes.forEach(previewOrderPlaceSchoolTime -> {
            boolean isTeaching = previewOrderPlaceSchoolTime.getIsTeaching() == 0;
            List<OrderVO.TimeSlotData> targetList = isTeaching ? teachingList : nonTeachingList;
            if (!targetList.isEmpty()) {
                // 找到最早开始时间
                Optional<OrderVO.TimeSlotData> earliest = targetList.stream()
                        .min(Comparator.comparing(t -> LocalTime.parse(t.getStartTime(), DateTimeFormatter.ofPattern("HH:mm"))));

                // 找到最晚结束时间
                Optional<OrderVO.TimeSlotData> latest = targetList.stream()
                        .max(Comparator.comparing(t -> LocalTime.parse(t.getEndTime(), DateTimeFormatter.ofPattern("HH:mm"))));

                String earliestStart = earliest.map(OrderVO.TimeSlotData::getStartTime).orElse("未知");
                String latestEnd = latest.map(OrderVO.TimeSlotData::getEndTime).orElse("未知");

                int bookedCount = appOrderMapper.queryBookedCount(
                        placeId,
                        DateUtil.format(previewOrderPlaceSchoolTime.getDay(), "yyyy-MM-dd"),
                        earliestStart,
                        latestEnd
                );
                int totalTicketNum = targetList.stream()
                        .mapToInt(t -> {
                            try {
                                return Integer.parseInt(t.getTicketNum());
                            } catch (NumberFormatException e) {
                                return 0; // 默认值，或抛出异常
                            }
                        })
                        .sum();
                previewOrderPlaceSchoolTime.setInventory(totalTicketNum - bookedCount);
            }

        });

        return previewOrderPlaceSchoolTimes;
    }

    /**
     * 提交订单
     * @param productId 商品id
     * @param count 购买数量
     * @return
     */
//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public Result<String> submitOrder(String productId, long count) {
//        String productKey = PRODUCT + productId; // PRODUCT_N001
//        String stockKey = PRODUCT_STOCK + productId; // PRODUCT_STOCK_N001
//        String stockLockKey = PRODUCT_STOCK_LOCK +productId; // PRODUCT_STOCK_LOCK_N001
//
//        // 获取库存锁，不会自动续期，最多等待3秒，超过则放弃获取锁，20秒后锁自动释放
////        boolean res = RedisLockUtils.tryLock(stockLockKey, TimeUnit.SECONDS, 3, 20);
//        // 获取库存锁，自动续期
//        boolean res = RedisLockUtils.tryLock(stockLockKey);
//        if (!res) {
//            // 超过等待时间，放弃获取锁
//            log.info("线程{} 获取锁失败", stockLockKey);
//            return ResponseData.error("系统正忙，请稍后再试");
//        }
//        log.info("线程{} 获取锁成功", stockLockKey);
//        try {
//            // 查询库存
//            Integer stock = (Integer) redisTemplate.opsForValue().get(stockKey);
//            // 缓存没有商品库存，查询数据库
//            if (stock == null) {
//                Product product = productMapper.getById(productId);
//                if (Objects.isNull(product)) {
//                    return ResponseData.error("订单提交失败，商品已下架");
//                }
//                redisTemplate.opsForValue().set(productKey, JSON.toJSONString(product));
//                // 数据库的库存信息要根据实际业务来获取，如果商品有规格信息，库存应该根据规格来获取
//                stock = product.getStack();
//                redisTemplate.opsForValue().set(stockKey, stock);
//
//                return ResponseData.error("订单提交失败，库存不足");
//            }
//
//            // 检查库存是否足够
//            if (stock < count) {
//                return ResponseData.error("订单提交失败，库存不足");
//            }
//
//            // 更新数据库中的库存数据
//            int row = productMapper.updateStock(productId, stock - count);
//            if (row > 0) {
//                // 更新Redis中缓存的商品库存数据
//                redisTemplate.opsForValue().decrement(stockKey, count);
//            }
//            // 库存扣减完，创建订单
//            Order order = Order.builder()
//                    .id(IdUtil.simpleUUID()).count(count).productId(productId).status(1)
//                    .build();
//            String orderId = orderService.createOrder(order);
//
//            return ResponseData.success(orderId, "订单创建成功");
//
//        } catch (OptimisticLockingFailureException e) {
//            // 如果出现乐观锁异常，则释放 Redis 锁并返回错误信息
//            log.error("更新库存失败，商品 {} 可能已被更新", productId);
//        } catch (Exception e) {
//            log.error("系统开小差了~");
//        } finally {
//            RedisLockUtils.unlock(stockLockKey);
//            log.info("线程{} 释放锁", stockLockKey);
//        }
//        return ResponseData.error("系统正忙，请稍后再试");
//    }


    /**
     * 创建订单
     *
     * @param createOrderForm
     * @return 支付订单对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserPayForm createOrder(CreateOrderForm createOrderForm) throws IOException {
        //获取登录用户
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        SysUser sysUser = sysUserMapper.selectById(user.getId());

        String orderCode = generateOrderNumber(0);

        Integer count = createOrderForm.getAmount();

        //创建订单
        AppOrder appOrder = new AppOrder();
        appOrder
                .setOrderType(createOrderForm.getOrderType())
                .setOrderCode(orderCode)
                .setUserId(user.getId())
                .setUserOpenId(sysUser.getOpenid())
                .setUserPhone(user.getPhone())
                .setOrderStatus(0)
                .setProductIds(createOrderForm.getProductIds())
                .setAmount(createOrderForm.getAmount())
        ;
        BigDecimal totalPrice = BigDecimal.ZERO;

        List<AppOrderProInfo> proInfoList = new ArrayList<>();

        List<InsureOrderInfo> insureOrderInfoList = new ArrayList<>();

        List<AppCoursesVerificationRecord> appCoursesVerificationRecordList = new ArrayList<>();

        String productKey = ""; // ORDER_TYPE_1_PRODUCT_N001
        String stockKey = ""; // ORDER_TYPE_1_PRODUCT_STOCK_N001

        //订单内容
        switch (createOrderForm.getType()) {
            //场地(学校，包场，无固定场)
            case 0:
                //学校
                if (createOrderForm.getOrderType() == 0) {
                    AppSitePriceRules priceRule = appSitePriceRulesMapper.selectById(createOrderForm.getProductIds());
                    AppSitePlace appSitePlace = appSitePlaceMapper.selectById(priceRule.getSitePlaceId());
                    AppSite appSite = appSiteMapper.selectById(appSitePlace.getSiteId());

                    String productId = createOrderForm.getProductIds();

                    productKey = "ORDER_TYPE_1_PRODUCT_" + productId; // ORDER_TYPE_1_PRODUCT_N001
                    stockKey = "ORDER_TYPE_1_PRODUCT_STOCK_" + productId; // ORDER_TYPE_1_PRODUCT_STOCK_N001

                    // 查询库存
                    Integer stock = (Integer) redisTemplate.opsForValue().get(stockKey);
                    // 缓存没有商品库存，查询数据库
                    if (stock == null) {
                        AppSitePriceRules product = appSitePriceRulesMapper.selectById(productId);
                        if (Objects.isNull(product)) {
                            throw new JeecgBootException("订单提交失败，商品已下架");
                        }
                        redisTemplate.opsForValue().set(productKey, JSON.toJSONString(product), 60 * 60 * 24, TimeUnit.SECONDS);
                        // 数据库的库存信息要根据实际业务来获取，如果商品有规格信息，库存应该根据规格来获取
                        if (product.getTicketNum() == null){
                            throw new JeecgBootException("订单提交失败，当前商品库存为空");
                        }
                        stock = product.getTicketNum();
                        redisTemplate.opsForValue().set(stockKey, stock, 60 * 60 * 24, TimeUnit.SECONDS);
                    }

                    // 检查库存是否足够
                    if (stock < count) {
                        throw new JeecgBootException("订单提交失败，库存不足");
                    }

                    // 更新数据库中的库存数据
                    int row = appSitePriceRulesMapper.update(null, Wrappers.<AppSitePriceRules>lambdaUpdate()
                            .eq(AppSitePriceRules::getId, productId)
                            .set(AppSitePriceRules::getTicketNum, stock - count));
                    if (row > 0) {
                        // 更新Redis中缓存的商品库存数据
                        redisTemplate.opsForValue().decrement(stockKey, count);
                    }
                    // 库存扣减完，创建订单
                    appOrder
                            .setPayType(3)
                            .setOrderStatus(1)
                            .setOrgCode(appSite.getOrgCode())
                            .setTenantId(appSite.getTenantId())
                            .setType(CommonConstant.ORDER_TYPE_0)
                            //使用人IDs
                            .setFamilyIds(createOrderForm.getFamilyIds())
                            .setOriginalPrice(priceRule.getSellingPrice())
                            .setAddressSiteId(appSite.getId())
                            .setPrice(totalPrice)
                            .setCreateTime(new Date())
                            .setUpdateTime(new Date())
                            .setCreateBy(user.getId())
                            .setUpdateBy(user.getId())
                            .setStatus(CommonConstant.STATUS_NORMAL)
                            .setDelFlag(CommonConstant.DEL_FLAG_0);
                    //使用人
                    List<String> ids = Arrays.stream(createOrderForm.getFamilyIds().split(",")).collect(Collectors.toList());
                    for (String id : ids) {
                        FamilyMembers familyMembers = familyMembersMapper.selectById(id);
                        if (Objects.isNull(familyMembers)) {

                        }

                        String date = DateUtil.format(priceRule.getDateOfSale(), "yyyy-MM-dd");
                        String startTime = DateUtil.format(priceRule.getStartTime(), "HH:mm:ss");
                        String endTime = DateUtil.format(priceRule.getEndTime(), "HH:mm:ss");
                        String expireTime = date + " " + endTime;
                        AppOrderProInfo appOrderProInfo = new AppOrderProInfo();
                        appOrderProInfo
                                .setProductId(priceRule.getId())
                                .setProductName("学校场地预约")
                                .setType(CommonConstant.ORDER_PRO_INFO_TYPE_0)
                                .setUseDateStr(date)
                                .setFrameTimeStr(startTime + "-" + endTime)
                                .setExpireTime(expireTime)
                                .setOriginalPrice(priceRule.getOriginalPrice())
                                .setProductImage(appSitePlace.getCover())
                                .setAddress(appSite.getAddress())
                                .setPrice(priceRule.getSellingPrice())
                                .setOrderStatus(1)
                                .setQuantity(1)
                                .setFamilyUserId(id)
                                .setUserName(familyMembers.getFullName())
                                .setUserPhone(familyMembers.getPhone())
                                .setStatus(CommonConstant.STATUS_0_INT)
                                .setDelFlag(CommonConstant.DEL_FLAG_0);

                        proInfoList.add(appOrderProInfo);
                    }
                }

                //包场
                if (createOrderForm.getOrderType() == 1) {

                    List<String> list = Arrays.stream(createOrderForm.getProductIds().split(",")).collect(Collectors.toList());

                    //订单总价（商品的售价总和）
                    BigDecimal sumPrice = new BigDecimal(0);

                    for (int i = 0; i < list.size(); i++) {
                        AppSitePriceRules priceRule = appSitePriceRulesMapper.selectById(list.get(i).split("\\|")[0]);
                        AppSitePlace appSitePlace = appSitePlaceMapper.selectById(priceRule.getSitePlaceId());
                        AppSite appSite = appSiteMapper.selectById(appSitePlace.getSiteId());

                        appOrder.setOrgCode(appSite.getOrgCode());

                        String date = list.get(i).split("\\|")[1];
                        String startTime = DateUtil.format(priceRule.getStartTime(), "HH:mm:ss");
                        String endTime = DateUtil.format(priceRule.getEndTime(), "HH:mm:ss");
                        String expireTime = date + " " + endTime;

                        AppOrderProInfo appOrderProInfo = new AppOrderProInfo();
                        appOrderProInfo.setProductId(list.get(i).split("\\|")[0]);
                        appOrderProInfo.setProductName(date + " " + startTime + "-" + endTime + "|" + appSitePlace.getName());
                        appOrderProInfo.setProductImage(appSitePlace.getCover());
                        appOrderProInfo.setExpireTime(expireTime);
                        appOrderProInfo.setAddress(appSite.getAddress());
                        appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_1);
                        appOrderProInfo.setOriginalPrice(priceRule.getOriginalPrice());
                        appOrderProInfo.setPrice(priceRule.getSellingPrice());
                        appOrderProInfo.setOrderStatus(0);
                        appOrderProInfo.setQuantity(1);
                        appOrderProInfo.setStatus(CommonConstant.STATUS_0_INT);
                        appOrderProInfo.setDelFlag(CommonConstant.DEL_FLAG_0);

                        proInfoList.add(appOrderProInfo);
                        appOrder.setOrgCode(appSitePlace.getOrgCode())
                                .setTenantId(appSitePlace.getTenantId()).setAddressSiteId(appSite.getId());

                        sumPrice = sumPrice.add(priceRule.getSellingPrice());
                    }

                    //计算订单总价
                    totalPrice = totalPrice.add(sumPrice);

                    appOrder
                            .setType(CommonConstant.ORDER_TYPE_0)
                            .setOriginalPrice(sumPrice)
                            .setCreateTime(new Date())
                            .setUpdateTime(new Date())
                            .setCreateBy(user.getId())
                            .setUpdateBy(user.getId())
                            .setStatus(CommonConstant.STATUS_NORMAL)
                            .setDelFlag(CommonConstant.DEL_FLAG_0);
                }

                //无固定场
                if (createOrderForm.getOrderType() == 2) {
                    AppSitePriceRules priceRule = appSitePriceRulesMapper.selectById(createOrderForm.getProductIds());
                    AppSitePlace appSitePlace = appSitePlaceMapper.selectById(priceRule.getSitePlaceId());
                    AppSite appSite = appSiteMapper.selectById(appSitePlace.getSiteId());

                    //订单总价（商品的售价总和）
                    BigDecimal sumPrice = new BigDecimal(0);
                    //团购优惠
                    BigDecimal tDiscounts = new BigDecimal(0);

                    for (int i = 1; i <= createOrderForm.getAmount(); i++) {

                        String date = DateUtil.format(priceRule.getDateOfSale(), "yyyy-MM-dd");
                        String startTime = DateUtil.format(priceRule.getStartTime(), "HH:mm:ss");
                        String endTime = DateUtil.format(priceRule.getEndTime(), "HH:mm:ss");
                        String expireTime = date + " " + endTime;

                        AppOrderProInfo appOrderProInfo = new AppOrderProInfo();
                        appOrderProInfo.setProductId(createOrderForm.getProductIds());
                        appOrderProInfo.setProductName(appSitePlace.getName());
                        appOrderProInfo.setProductImage(appSitePlace.getCover());
                        appOrderProInfo.setAddress(appSite.getAddress());
                        appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_2);
                        appOrderProInfo.setFrameTimeStr(startTime + "-" + endTime);
                        appOrderProInfo.setExpireTime(expireTime);
                        appOrderProInfo.setOriginalPrice(priceRule.getOriginalPrice());
                        appOrderProInfo.setPrice(priceRule.getSellingPrice());
                        appOrderProInfo.setOrderStatus(0);
                        appOrderProInfo.setQuantity(1);
                        appOrderProInfo.setStatus(CommonConstant.STATUS_0_INT);
                        appOrderProInfo.setDelFlag(CommonConstant.DEL_FLAG_0);

                        proInfoList.add(appOrderProInfo);
                        tDiscounts = tDiscounts.add(priceRule.getOriginalPrice().subtract(priceRule.getSellingPrice()));
                        sumPrice = sumPrice.add(priceRule.getSellingPrice());
                    }

                    //计算订单总价
                    totalPrice = totalPrice.add(sumPrice);

                    appOrder
                            .setOrgCode(appSite.getOrgCode())
                            .setTenantId(appSite.getTenantId())
                            .setType(CommonConstant.ORDER_TYPE_0)
                            .setTDiscounts(tDiscounts)
                            .setOriginalPrice(sumPrice)
                            .setAddressSiteId(appSite.getId())
                            .setCreateTime(new Date())
                            .setUpdateTime(new Date())
                            .setCreateBy(user.getId())
                            .setUpdateBy(user.getId())
                            .setStatus(CommonConstant.STATUS_NORMAL)
                            .setDelFlag(CommonConstant.DEL_FLAG_0);
                }
                break;
            //赛事
            case 1:
                //个人赛
                AppGamePriceRules appGamePriceRules = appGamePriceRulesMapper.selectById(createOrderForm.getProductIds());
                AppGame appGame = appGameMapper.selectById(appGamePriceRules.getGameId());
                AppGameSchedule appGameSchedule = appGameScheduleMapper.selectOne(Wrappers.<AppGameSchedule>lambdaQuery().eq(AppGameSchedule::getGameId, appGame.getId()).last("limit 1"));


                appOrder.setOrgCode(appGamePriceRules.getOrgCode());
                appOrder.setTenantId(appGamePriceRules.getTenantId());

                //订单总价（商品的售价总和）
                BigDecimal sumPrice = new BigDecimal(0);

                for (int i = 1; i <= createOrderForm.getAmount(); i++) {

                    String familyUserId = createOrderForm.getFamilyIds().split(",")[i - 1];
                    FamilyMembers familyMembers = familyMembersMapper.selectById(familyUserId);
                    AppOrderProInfo appOrderProInfo = new AppOrderProInfo();
                    appOrderProInfo.setProductId(createOrderForm.getProductIds());
                    appOrderProInfo.setProductName(appGame.getName());
                    appOrderProInfo.setAddress(appGame.getAddress());
                    if (createOrderForm.getOrderType() == 3) {
                        appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_3);
                    }
                    if (createOrderForm.getOrderType() == 4) {
                        appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_4);
                    }
                    appOrderProInfo.setFrameTimeStr(appGame.getStartTime() + "-" + appGame.getEndTime());
                    appOrderProInfo.setExpireTime(DateUtil.format(appGameSchedule.getEndTime(), "yyyy-MM-dd HH:mm:ss"));
                    appOrderProInfo.setOriginalPrice(appGamePriceRules.getSellingPrice());
                    appOrderProInfo.setPrice(appGamePriceRules.getSellingPrice());
                    appOrderProInfo.setProductImage(appGame.getCover());
                    appOrderProInfo.setOrderStatus(0);
                    appOrderProInfo.setQuantity(1);
                    appOrderProInfo.setFamilyUserId(familyUserId);
                    appOrderProInfo.setUserName(familyMembers.getFullName());
                    appOrderProInfo.setUserPhone(familyMembers.getPhone());
                    appOrderProInfo.setStatus(CommonConstant.STATUS_0_INT);
                    appOrderProInfo.setDelFlag(CommonConstant.DEL_FLAG_0);

                    proInfoList.add(appOrderProInfo);

                    sumPrice = sumPrice.add(appGamePriceRules.getSellingPrice());
                }
                //计算订单总价
                totalPrice = totalPrice.add(sumPrice);

                appOrder
                        .setType(CommonConstant.ORDER_TYPE_1)
                        .setAddressSiteId(appGame.getSiteId())
                        .setOriginalPrice(sumPrice)
                        .setCreateTime(new Date())
                        .setUpdateTime(new Date())
                        .setCreateBy(user.getId())
                        .setUpdateBy(user.getId())
                        .setStatus(CommonConstant.STATUS_NORMAL)
                        .setDelFlag(CommonConstant.DEL_FLAG_0);
                if (StrUtil.isNotBlank(createOrderForm.getGameCertificationForm())) {
                    appOrder.setGameCertification(createOrderForm.getGameCertificationForm());
                }
                break;
            //课程
            case 2:
                //课程
                AppCourses appCourse = appCoursesMapper.selectById(appOrder.getProductIds());
                List<AppCoursesPriceRules> priceRulesList = appCoursesPriceRulesMapper.selectList(Wrappers.<AppCoursesPriceRules>lambdaQuery().eq(AppCoursesPriceRules::getCoursesId, appCourse.getId()));
                AppSite appSite = appSiteMapper.selectById(appCourse.getAddressSiteId());
                appOrder.setOrderOrFree(appCourse.getPriceType());
                appOrder.setType(CommonConstant.ORDER_TYPE_2);
                appOrder.setOrgCode(appCourse.getOrgCode());
                appOrder.setTenantId(appCourse.getTenantId());

                //合同编号
                AppContractInfo appContractInfo = appContractInfoMapper.selectOne(Wrappers.<AppContractInfo>lambdaQuery()
                        .eq(AppContractInfo::getOrgCode, appOrder.getOrgCode()).eq(AppContractInfo::getDelFlag, 0));
                if (ObjectUtil.isNotEmpty(appContractInfo)) {
                    appOrder.setContractNo(appContractInfo.getId());
                }

                //订单总价（商品的售价总和）
                BigDecimal sumCoursePrice = new BigDecimal(0);

                //优惠金额，如果当前课程商品类目是第一次购买，触发免费政策
                BigDecimal sDiscounts = new BigDecimal(0);
                BigDecimal tDiscounts = new BigDecimal(0);

                for (int i = 1; i <= createOrderForm.getAmount(); i++) {

                    String familyUserId = createOrderForm.getFamilyIds().split(",")[i - 1];
                    FamilyMembers familyMembers = familyMembersMapper.selectById(familyUserId);
                    AppOrderProInfo appOrderProInfo = new AppOrderProInfo();
                    appOrderProInfo.setProductId(createOrderForm.getProductIds());
                    appOrderProInfo.setProductName(appCourse.getName());
                    appOrderProInfo.setAddress(appSite.getAddress());
                    appOrderProInfo.setProductImage(appCourse.getCover());
                    appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_5);
                    appOrderProInfo.setFrameTimeStr(DateUtil.format(appCourse.getStartTime(), "yyyy-MM-dd") + "-" + DateUtil.format(appCourse.getEndTime(), "MM-dd"));
                    appOrderProInfo.setExpireTime(DateUtil.format(appCourse.getEndTime(), "yyyy-MM-dd"));
                    appOrderProInfo.setOriginalPrice(appCourse.getOriginalPrice());
                    appOrderProInfo.setPrice(appCourse.getSellingPrice());
                    appOrderProInfo.setOrderStatus(0);
                    appOrderProInfo.setQuantity(1);
                    appOrderProInfo.setFamilyUserId(familyUserId);
                    appOrderProInfo.setUserName(familyMembers.getFullName());
                    appOrderProInfo.setUserPhone(familyMembers.getPhone());
                    appOrderProInfo.setStatus(CommonConstant.STATUS_0_INT);
                    appOrderProInfo.setDelFlag(CommonConstant.DEL_FLAG_0);

                    //创建核销记录
                    if (CollUtil.isNotEmpty(priceRulesList)) {
                        for (AppCoursesPriceRules appCoursesPriceRules : priceRulesList) {
                            AppCoursesVerificationRecord appCoursesVerificationRecord = new AppCoursesVerificationRecord();
                            appCoursesVerificationRecord.setCoursesId(appCourse.getId());
                            appCoursesVerificationRecord.setCoursesPriceRuleId(appCoursesPriceRules.getId());
                            appCoursesVerificationRecord.setCoursesName(appCoursesPriceRules.getName());
                            appCoursesVerificationRecord.setCoursesStartTime(appCoursesPriceRules.getStartTime());
                            appCoursesVerificationRecord.setCoursesEndTime(appCoursesPriceRules.getEndTime());
                            appCoursesVerificationRecord.setUseUserId(familyUserId);
                            appCoursesVerificationRecord.setUseUserName(familyMembers.getFullName());
                            appCoursesVerificationRecord.setUseUserPhone(familyMembers.getPhone());
                            appCoursesVerificationRecord.setUseUserImage(familyMembers.getRealNameImg());
                            appCoursesVerificationRecord.setUseUserName(familyMembers.getFullName());
                            appCoursesVerificationRecord.setVerifyStatus(0);
                            appCoursesVerificationRecord.setOrPostpone(0);
                            appCoursesVerificationRecord.setCoursesType(appCoursesPriceRules.getCoursesType());
                            appCoursesVerificationRecordList.add(appCoursesVerificationRecord);
                        }
                    }

                    if (createOrderForm.getOrFreeOrder() == 1) {
                        Boolean flag = checkOrderOrFree(user.getId(), appCourse.getCategoryId());
                        if (flag && i == 1) {
                            //订单中的多个商品中的第一个商品触发免费，将金额设置为优惠金额
                            sDiscounts = sDiscounts.add(appCourse.getSellingPrice());
                            appOrderProInfo.setOrFreePro(CommonConstant.STATUS_1_INT);
                            appOrderProInfo.setOrderStatus(1);
                            appOrder.setContractNo(null);
                            //试听优惠
                            appOrder.setSDiscounts(sDiscounts);
                            appOrder.setOrderOrFree(CommonConstant.STATUS_1_INT);
                        }
                    }

                    proInfoList.add(appOrderProInfo);

                    tDiscounts = tDiscounts.add(appCourse.getOriginalPrice().subtract(appCourse.getSellingPrice()));
                    sumCoursePrice = sumCoursePrice.add(appCourse.getSellingPrice().subtract(sDiscounts));
                }

                //计算订单总价
                totalPrice = totalPrice.add(sumCoursePrice);

                //团购优惠
                appOrder.setTDiscounts(tDiscounts);
                //原订单总价
                appOrder.setOriginalPrice(sumCoursePrice);
                //使用人IDs
                appOrder.setFamilyIds(createOrderForm.getFamilyIds());

                appOrder.setAddressSiteId(appSite.getId());
                break;
        }


        //构建保单内容
        InsureOrderInfoForm insureOrderInfoForm = createOrderForm.getInsureOrderInfoForm();
        if (ObjectUtils.isNotEmpty(insureOrderInfoForm)) {
            List<String> ids = Arrays.stream(insureOrderInfoForm.getFamilyMembersIds().split(",")).collect(Collectors.toList());
            AppInsure appInsure = appInsureMapper.selectById(insureOrderInfoForm.getInsureId());
            DictAnnotationUtil.translateDict(appInsure);
            //保单总价
            BigDecimal sumPrice = new BigDecimal(0);
            for (String id : ids) {

                //查询保单价格
                InsurePrice insurePrice = insurePriceMapper.selectById(insureOrderInfoForm.getInsurePriceId());
                FamilyMembers members = familyMembersMapper.selectById(id);

                //创建保单
                InsureOrderInfo insureOrderInfo = new InsureOrderInfo();
                insureOrderInfo
                        .setOrderId(appOrder.getId())
                        .setBdOrderNo(generateOrderNumber(2))
                        .setInsureName(appInsure.getName())
                        .setCoverImg(appInsure.getCoverImg())
                        .setInsureCompany(appInsure.getInsuranceName_dictText())
                        .setInsureId(appInsure.getId())
                        .setMoney(insurePrice.getInsurePrice())
                        .setFamilyMembersId(id)
                        .setFamilyUserName(members.getFullName())
                        .setAssertStartTime(insureOrderInfoForm.getAssertStartTime())
                        .setAssertEndTime(insureOrderInfoForm.getAssertEndTime())
                        .setIsEnterSystem(CommonConstant.STATUS_0_INT)
                ;
                insureOrderInfoList.add(insureOrderInfo);

                sumPrice = sumPrice.add(insurePrice.getInsurePrice());
            }
            //计算总价 = 订单金额 + 保单金额
            totalPrice = totalPrice.add(sumPrice);
        }
        appOrder.setPrice(totalPrice);
        appOrderMapper.insert(appOrder);
        if(appOrder.getOrderType()== 5 && appOrder.getOrderOrFree()==0){
            saveSignFlowRecord(appOrder);
        }
        if (!insureOrderInfoList.isEmpty()) {
            //保存保险
            for (InsureOrderInfo insureOrderInfo : insureOrderInfoList) {
                insureOrderInfo.setOrderId(appOrder.getId());
                insureOrderInfoMapper.insert(insureOrderInfo);

                AppOrderProInfo appOrderProInfo = new AppOrderProInfo();
                appOrderProInfo.setProductId(insureOrderInfo.getId());
                appOrderProInfo.setProductName(insureOrderInfo.getInsureName());
                appOrderProInfo.setProductImage(insureOrderInfo.getCoverImg());
                appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_6);

                appOrderProInfo.setPrice(insureOrderInfo.getMoney());
                appOrderProInfo.setOriginalPrice(insureOrderInfo.getMoney());
                appOrderProInfo.setQuantity(1);
                FamilyMembers familyMembers = familyMembersMapper.selectById(insureOrderInfo.getFamilyMembersId());
                appOrderProInfo.setFamilyUserId(familyMembers.getId());
                appOrderProInfo.setUserName(familyMembers.getFullName());
                appOrderProInfo.setUserPhone(familyMembers.getPhone());
                appOrderProInfo.setStatus(CommonConstant.STATUS_0_INT);
                appOrderProInfo.setDelFlag(CommonConstant.DEL_FLAG_0);

                proInfoList.add(appOrderProInfo);
            }
        }

        for (AppOrderProInfo appOrderProInfo : proInfoList) {
            appOrderProInfo
                    .setOrderId(appOrder.getId())
                    .setOrderCode(appOrder.getOrderCode())
                    //生成10位随机券号
                    .setTicketNo(RandomUtil.randomNumbers(10))
            ;
            appOrderProInfoMapper.insert(appOrderProInfo);
            if (!Objects.equals(appOrderProInfo.getType(), CommonConstant.ORDER_PRO_INFO_TYPE_6)) {
                //订单券号记录
                AppIsin appIsin = new AppIsin();
                appIsin
                        .setOrderId(appOrder.getId())
                        .setOrgCode(appOrder.getOrgCode())
                        .setOrderCode(appOrder.getOrderCode())
                        .setOrderProInfoId(appOrderProInfo.getId())
                        .setFamilyId(appOrderProInfo.getFamilyUserId())
                        .setFamilyUserName(appOrderProInfo.getUserName())
                        .setUserPhone(appOrderProInfo.getUserPhone())
                        .setUseAddress(StrUtil.isBlank(appOrderProInfo.getAddress()) ? null : appOrderProInfo.getAddress())
                        //过期时间
                        .setExpireTime(appOrderProInfo.getExpireTime())
                        //生成10位随机券号
                        .setTicketNo(appOrderProInfo.getTicketNo())
                        .setIsinStatus(CommonConstant.ISIN_STATUS_1);
                appIsinMapper.insert(appIsin);
            }
            if (Objects.equals(appOrderProInfo.getType(), CommonConstant.ORDER_PRO_INFO_TYPE_0)) {
                for (AppDevice appDevice : appDeviceMapper.selectList(Wrappers.<AppDevice>lambdaQuery().eq(AppDevice::getOrgCode, appOrder.getOrgCode()))) {
                    String addUser = addUser(appSitePriceRulesMapper.selectById(appOrderProInfo.getProductId()).getDateOfSale(),
                            appDevice.getDeviceSerial(),
                            appOrderProInfo.getUserName(),
                            appOrderProInfo.getId());
                    String addFace = addFace(appDevice.getDeviceSerial(), appOrderProInfo.getId(),
                            familyMembersMapper.selectById(appOrderProInfo.getFamilyUserId()).getRealNameImg());
                    JsonObject addUserJson = JsonParser.parseString(addUser).getAsJsonObject();
                    JsonObject addFaceJson = JsonParser.parseString(addFace).getAsJsonObject();
                    if (addUserJson.get("code").getAsInt() != 0 && addFaceJson.get("code").getAsInt() != 0) throw new JeecgBootException("设备录入用户信息失败！请联系管理员");
                }

            }
        }

        //保存核销记录
        if (CollUtil.isNotEmpty(appCoursesVerificationRecordList)) {
            for (AppCoursesVerificationRecord appCoursesVerificationRecord : appCoursesVerificationRecordList) {
                appCoursesVerificationRecord.setOrderId(appOrder.getId());
                appCoursesVerificationRecord.setOrderCode(appOrder.getOrderCode());
                appCoursesVerificationRecordMapper.insert(appCoursesVerificationRecord);
            }
        }

        //构建支付表单返回给前端支撑JsApi支付调用
        UserPayForm payForm = new UserPayForm();
        payForm
                .setOrderId(appOrder.getId())
                .setOrderCode(orderCode)
        ;

        //判断是否试听课（试听课不走订单）
        if (ObjectUtil.isNotEmpty(appOrder.getOrderOrFree()) && appOrder.getOrderOrFree() == 1) {
            payForm.setOrPayOrder(0);
        }
        else if (appOrder.getOrderType() == 0){
            payForm.setOrPayOrder(0);
        }else {
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) + 15);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");

            //构建微信支付参数
            JSONObject params = new JSONObject();
            params.put("appid", WechatConstants.WECHAT_MP_APPID); //小程序appid
//        params.put("sub_appid", WechatConstants.WECHAT_MP_APPID); //小程序appid
            params.put("mchid", WechatConstants.WECHAT_MCH_ID); //商户号
            params.put("description", "全龄运动"); //商品描述
            params.put("out_trade_no", appOrder.getOrderCode()); //商户订单号
            params.put("time_expire", sdf.format(calendar.getTime())); //交易结束时间 选填 时间到了之后将不能再支付 遵循rfc3339标准格式
            params.put("attach", appOrder.getOrderCode()); //附加数据 选填
            // 在查询API和支付通知中原样返回 可作为自定义参数使用
            params.put("notify_url", WechatUrlConstants.PAY_V3_NOTIFY); //支付结果异步通知接口
            params.put("trade_type", WechatConstants.WECHAT_MP_TRADE_TYPE);//JSAPI
            //分账必传参数
            JSONObject settleInfo = new JSONObject();
            settleInfo.put("profit_sharing", Boolean.TRUE);
            params.put("settle_info", settleInfo);

            //订单金额信息
            JSONObject amount_json = new JSONObject();
            //支付金额 单位：分
            amount_json.put("total", Integer.parseInt(amount_fee(new BigDecimal("0.01"))));//测试0.01元
//        amount_json.put("total", Integer.parseInt(amount_fee(appOrder.getPrice())));
            params.put("amount", amount_json);

            //支付者信息
            JSONObject payer = new JSONObject();
            //用户在小程序侧的openid
            payer.put("openid", sysUser.getOpenid());
            params.put("payer", payer);

            //拉起支付-返回JSAPI参数
//        Map<String, String> result = weChatPayService.wechatPay(params);
//        payForm.setParams(result);

            //发布任务到redission延迟队列
            String task = CommonConstant.ORDER_TIME_OUT_TASK_PREFIX + appOrder.getId();
            redissonDelayQueue.offerTask(task, 60 * 15);
        }

        return payForm;

    }

    /**
     * 金额元转分字符串
     *
     * @param cny 元
     * @return
     */
    public String amount_fee(BigDecimal cny) {
        BigDecimal b2 = new BigDecimal("100");
        return cny.multiply(b2).setScale(0, RoundingMode.DOWN).toString();
    }

    /**
     * 异步走保存下单信息
     *
     * @param appOrder
     * @param proInfoList
     * @param insureOrderInfoList
     * @param appCoursesVerificationRecordList
     */
    public void remoteSaveOrderInfo(final AppOrder appOrder,
                                    final List<AppOrderProInfo> proInfoList,
                                    final List<InsureOrderInfo> insureOrderInfoList,
                                    final List<AppCoursesVerificationRecord> appCoursesVerificationRecordList) {

        //开启线程池保存订单信息
        remoteSaveOrderInfo(appOrder, proInfoList, insureOrderInfoList, appCoursesVerificationRecordList);

        //创建一个可重用固定线程数的线程池
        ExecutorService cachedThreadPool = Executors.newFixedThreadPool(20); //固定大小的线程池

        cachedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                log.info("======>[保存订单商品信息]  线程<======");
                log.info("======>当前线程 NAME  =" + Thread.currentThread().getName());
                log.info("======>当前线程 ID    =" + Thread.currentThread().getId());
                log.info("======>当前线程 Count =" + Thread.activeCount());

                try {
                    Thread.sleep(500);//线程延迟0.5秒
                    saveSignFlowRecord(appOrder);
                    // 优化异步执行 -> 保存订单商品信息
                    for (AppOrderProInfo appOrderProInfo : proInfoList) {
                        appOrderProInfo
                                .setOrderId(appOrder.getId())
                                .setOrderCode(appOrder.getOrderCode())
                                //生成10位随机券号
                                .setTicketNo(RandomUtil.randomNumbers(10))
                        ;
                        appOrderProInfoMapper.insert(appOrderProInfo);
                        //订单券号记录
                        AppIsin appIsin = new AppIsin();
                        appIsin
                                .setOrderId(appOrder.getId())
                                .setOrderCode(appOrder.getOrderCode())
                                .setOrderProInfoId(appOrderProInfo.getId())
                                .setFamilyId(appOrderProInfo.getFamilyUserId())
                                .setFamilyUserName(appOrderProInfo.getUserName())
                                .setUserPhone(appOrderProInfo.getUserPhone())
                                .setUseAddress(StrUtil.isBlank(appOrderProInfo.getAddress()) ? null : appOrderProInfo.getAddress())
                                //过期时间
                                .setExpireTime(appOrderProInfo.getExpireTime())
                                //生成10位随机券号
                                .setTicketNo(appOrderProInfo.getTicketNo())
                                .setIsinStatus(CommonConstant.ISIN_STATUS_1);
                        appIsinMapper.insert(appIsin);
                    }

                    //保存保险
                    for (InsureOrderInfo insureOrderInfo : insureOrderInfoList) {
                        insureOrderInfo.setOrderId(appOrder.getId());
                        insureOrderInfoMapper.insert(insureOrderInfo);
                    }

                    //保存核销记录
                    for (AppCoursesVerificationRecord appCoursesVerificationRecord : appCoursesVerificationRecordList) {
                        appCoursesVerificationRecord.setOrderId(appOrder.getId());
                        appCoursesVerificationRecord.setOrderCode(appOrder.getOrderCode());
                        appCoursesVerificationRecordMapper.insert(appCoursesVerificationRecord);
                    }

                } catch (NumberFormatException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        //关闭线程池
        cachedThreadPool.shutdown();
    }

    /**
     * 保存签署流程记录
     */
    private void saveSignFlowRecord(AppOrder appOrder) {
        if (appOrder.getFamilyIds() != null && !appOrder.getFamilyIds().isEmpty()) {
            List.of(appOrder.getFamilyIds().split(",")).forEach(a -> {
                String id = UUID.randomUUID().toString().replace("-", "");
                AppContractSign record = new AppContractSign()
                        .setId(id)
                        .setOrderId(appOrder.getId())
                        .setFamilyId(a)
                        .setOrgCode(appOrder.getOrgCode())
                        .setCreateTime(new Date())
                        .setUpdateTime(new Date());
                appContractSignMapper.insert(record);
            });
        }
    }

    @Override
    public OrderVO.PreviewOrderPlaceGymnasiumNoFixation previewOrderPlaceGymnasiumNoFixation(String placeId) {
        return appSitePlaceMapper.previewOrderPlaceGymnasiumNoFixation(placeId);
    }

    @Override
    public AppOrderInfoDTO queryOrderInfo(String orderId) {

        AppOrderInfoDTO appOrderInfoDTO = new AppOrderInfoDTO();

        AppOrder appOrder = appOrderMapper.selectById(orderId);
        if (ObjectUtil.isEmpty(appOrder)) {
           throw new JeecgBootException("当前订单不存在！");
        }
        appOrderInfoDTO.setId(appOrder.getId());
        appOrderInfoDTO.setOrderCode(appOrder.getOrderCode());
        appOrderInfoDTO.setOrderStatus(appOrder.getOrderStatus());
        appOrderInfoDTO.setType(appOrder.getType());
        appOrderInfoDTO.setCreateTime(appOrder.getCreateTime());
        appOrderInfoDTO.setPayTime(appOrder.getPayTime());
        appOrderInfoDTO.setPhoneNumber(appOrder.getUserPhone());
        appOrderInfoDTO.setTotalPrice(appOrder.getOriginalPrice());
        appOrderInfoDTO.setPrice(appOrder.getPrice());
        appOrderInfoDTO.setGameCertification(appOrder.getGameCertification());
        if (appOrder.getType().equals(CommonConstant.ORDER_TYPE_2)) {
            appOrderInfoDTO.setSDiscounts(appOrder.getSDiscounts());
            appOrderInfoDTO.setTDiscounts(appOrder.getTDiscounts());
        }

        //子订单
        List<AppOrderProInfo> proInfoList = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery().eq(AppOrderProInfo::getOrderId, orderId));
        appOrderInfoDTO.setProInfoList(proInfoList);

        //学校
        if (appOrder.getType().equals(CommonConstant.ORDER_TYPE_0)) {
            if (appOrder.getOrderType() == 0) {
                //商品信息
                String productIds = appOrder.getProductIds();
                AppSitePriceRules appSitePriceRules = appSitePriceRulesMapper.selectById(productIds);
                AppSitePlace appSitePlace = appSitePlaceMapper.selectById(appSitePriceRules.getSitePlaceId());
                //使用须知
                if (ObjectUtils.isNotEmpty(appSitePlace.getReminder())) {
                    appOrderInfoDTO.setReminder(appSitePlace.getReminder());
                }
                //门店信息
                AppSite site = appSiteMapper.selectById(appSitePlace.getSiteId());
                appOrderInfoDTO.setSiteName(site.getName());
                appOrderInfoDTO.setRunStatus(site.getRunStatus());
                //预定信息
                appOrderInfoDTO.setDateOfSale(appSitePriceRules.getDateOfSale());
                appOrderInfoDTO.setStartTime(appSitePriceRules.getStartTime());
                appOrderInfoDTO.setEndTime(appSitePriceRules.getEndTime());
                StringBuilder userNames = new StringBuilder();
                for (AppOrderProInfo appOrderProInfo : proInfoList) {
                    userNames.append(appOrderProInfo.getUserName()).append(" ");
                }
                appOrderInfoDTO.setUserNames(String.valueOf(userNames));
                //地址信息
                appOrderInfoDTO.setSchoolAddress(site.getAddress());
                appOrderInfoDTO.setLatitude(site.getLatitude());
                appOrderInfoDTO.setLongitude(site.getLongitude());
                appOrderInfoDTO.setPhone(site.getPhone());
                appOrderInfoDTO.setAddressSiteId(site.getId());
            }
            //包场
            if (appOrder.getOrderType() == 1) {
                //商品信息
                String productIds = appOrder.getProductIds();
                String[] split = productIds.split(",");
                AppSitePriceRules appSitePriceRules = appSitePriceRulesMapper.selectById(split[0].split("\\|")[0]);
                AppSitePlace appSitePlace = appSitePlaceMapper.selectById(appSitePriceRules.getSitePlaceId());
                //使用须知
                if (ObjectUtils.isNotEmpty(appSitePlace.getReminder())) {
                    appOrderInfoDTO.setReminder(appSitePlace.getReminder());
                }
                //场馆
                AppSite site = appSiteMapper.selectById(appSitePlace.getSiteId());
                appOrderInfoDTO.setSiteName(site.getName());
                appOrderInfoDTO.setRunStatus(site.getRunStatus());
                //退改规则、温馨提示
                appOrderInfoDTO.setReminder(appSitePlace.getReminder());
                appOrderInfoDTO.setAdvanceTime(appSitePlace.getAdvanceTime());

                //地址信息
                appOrderInfoDTO.setSchoolAddress(site.getAddress());
                appOrderInfoDTO.setLatitude(site.getLatitude());
                appOrderInfoDTO.setLongitude(site.getLongitude());
                appOrderInfoDTO.setPhone(site.getPhone());
                appOrderInfoDTO.setAddressSiteId(site.getId());
            }
            //无固定场
            if (appOrder.getOrderType() == 2) {
                //商品信息
                String productIds = appOrder.getProductIds();
                AppSitePriceRules appSitePriceRules = appSitePriceRulesMapper.selectById(productIds);
                AppSitePlace appSitePlace = appSitePlaceMapper.selectById(appSitePriceRules.getSitePlaceId());
                //使用须知
                if (ObjectUtils.isNotEmpty(appSitePlace.getReminder())) {
                    appOrderInfoDTO.setReminder(appSitePlace.getReminder());
                }
                //门店信息
                AppSite site = appSiteMapper.selectById(appSitePlace.getSiteId());
                appOrderInfoDTO.setSiteName(site.getName());
                appOrderInfoDTO.setRunStatus(site.getRunStatus());
                //预定信息
                appOrderInfoDTO.setRunType(site.getRunType());
                appOrderInfoDTO.setStartTime(site.getStartTime());
                appOrderInfoDTO.setEndTime(site.getEndTime());
                appOrderInfoDTO.setRefundType(appSitePlace.getRefundType());
                //地址信息
                appOrderInfoDTO.setSchoolAddress(site.getAddress());
                appOrderInfoDTO.setLatitude(site.getLatitude());
                appOrderInfoDTO.setLongitude(site.getLongitude());
                appOrderInfoDTO.setPhone(site.getPhone());
                appOrderInfoDTO.setAddressSiteId(site.getId());
            }
        }

        //赛事
        if (appOrder.getType().equals(CommonConstant.ORDER_TYPE_1)) {
            //商品信息
            String productIds = appOrder.getProductIds();
            AppGamePriceRules appGamePriceRules = appGamePriceRulesMapper.selectById(productIds);
            AppGame appGame = appGameMapper.selectById(appGamePriceRules.getGameId());

            //门店信息
            AppSite site = appSiteMapper.selectById(appGame.getSiteId());
            //退改规则、
            appOrderInfoDTO.setReminder(appGame.getReminder());
            //开始时间
            appOrderInfoDTO.setStartTime(appGame.getStartTime());
            //赛程安排
            List<AppGameScheduleVO> appGameScheduleVOList = appGameScheduleMapper.getListVo(appGame.getId());
            appOrderInfoDTO.setAppGameScheduleVOList(appGameScheduleVOList);
            //赛程数
            appOrderInfoDTO.setGameScheduleNum(appGameScheduleVOList.size());
            //地址信息
            appOrderInfoDTO.setSchoolAddress(site.getAddress());
            appOrderInfoDTO.setLatitude(site.getLatitude());
            appOrderInfoDTO.setLongitude(site.getLongitude());
            appOrderInfoDTO.setPhone(site.getPhone());
            appOrderInfoDTO.setAddressSiteId(site.getId());
        }

        //课程
        if (appOrder.getType().equals(CommonConstant.ORDER_TYPE_2)) {
            //商品信息
            String productIds = appOrder.getProductIds();
            AppCourses appCourses = appCoursesMapper.selectById(productIds);
            appOrderInfoDTO.setAppCourses(appCourses);
            //使用须知
            if (ObjectUtils.isNotEmpty(appCourses.getReminder())) {
                appOrderInfoDTO.setReminder(appCourses.getReminder());
            }
            //门店信息
            AppSite site = appSiteMapper.selectById(appCourses.getSiteId());
            appOrderInfoDTO.setSiteName(site.getName());
            appOrderInfoDTO.setRunStatus(site.getRunStatus());
            //上课地点（经纬度）
            AppSite courseSite = appSiteMapper.selectById(appCourses.getAddressSiteId());
            appOrderInfoDTO.setOrSchoolCourse(0);
            //学校课程
            if (courseSite.getType() == 0) {
                appOrderInfoDTO.setOrSchoolCourse(1);
            }
            appOrderInfoDTO.setCourseSiteAddress(courseSite.getAddress());
            appOrderInfoDTO.setLatitude(courseSite.getLatitude());
            appOrderInfoDTO.setLongitude(courseSite.getLongitude());
            appOrderInfoDTO.setPhone(courseSite.getPhone());
            appOrderInfoDTO.setAddressSiteId(courseSite.getId());
        }

        //保单信息
        List<InsureOrderInfo> insureOrderInfoList = insureOrderInfoMapper.selectList(Wrappers.lambdaQuery(InsureOrderInfo.class).eq(InsureOrderInfo::getOrderId, orderId));
        if (CollUtil.isNotEmpty(insureOrderInfoList)) {
            appOrderInfoDTO.setInsureOrderInfoList(insureOrderInfoList);
        }

        return appOrderInfoDTO;
    }

    @Override
    public List<QueryOrderVerifyRecordsVO> queryOrderVerifyRecords(String orderId, String ticketNo) {

        List<QueryOrderVerifyRecordsVO> list = new ArrayList<>();

        AppOrderProInfo proInfo = appOrderProInfoMapper.selectOne(Wrappers.<AppOrderProInfo>lambdaQuery().eq(AppOrderProInfo::getOrderId, orderId).eq(AppOrderProInfo::getTicketNo, ticketNo));

        String familyUserId = proInfo.getFamilyUserId();
        String appCourseId = proInfo.getProductId();

        List<AppCoursesVerificationRecord> verificationRecordList = appCoursesVerificationRecordMapper.selectList(Wrappers.<AppCoursesVerificationRecord>lambdaQuery()
                .eq(AppCoursesVerificationRecord::getOrderId, orderId)
                .eq(AppCoursesVerificationRecord::getCoursesId, appCourseId)
                .eq(AppCoursesVerificationRecord::getUseUserId, familyUserId));

        Map<Integer, List<AppCoursesVerificationRecord>> map = verificationRecordList.stream().collect(Collectors.groupingBy(AppCoursesVerificationRecord::getCoursesType));

        map.keySet().forEach(key -> {
            QueryOrderVerifyRecordsVO queryOrderVerifyRecordsVO = new QueryOrderVerifyRecordsVO();
            List<AppCoursesVerificationRecord> records = map.get(key);
            queryOrderVerifyRecordsVO.setCoursesType(key);
            queryOrderVerifyRecordsVO.setCoursesTotal(records.size());
            long verifyNum = records.stream().filter(e -> e.getVerifyStatus() == 1).count();
            queryOrderVerifyRecordsVO.setVerifyNum((int) verifyNum);
            long unVerifyNum = records.stream().filter(e -> e.getVerifyStatus() == 0).count();
            queryOrderVerifyRecordsVO.setUnVerifyNum((int) unVerifyNum);
            queryOrderVerifyRecordsVO.setRecordList(map.get(key));

            list.add(queryOrderVerifyRecordsVO);
        });

        return list;
    }

    /**
     * @return boolean
     * @Author SheepHy
     * @Description 查询用户对该类型课程是否有试听资格
     * @Date 16:45 2025/7/14
     * @Param courseId userId
     **/
    private boolean checkCourseDiscount(String categoryId, String userId) {
        boolean success = Boolean.TRUE;
        List<AppOrder> appOrders = appOrderMapper.selectList(Wrappers.<AppOrder>lambdaQuery()
                .eq(AppOrder::getUserId, userId)
                .ne(AppOrder::getOrderStatus, 6)
                .ne(AppOrder::getOrderStatus, 5)
                .eq(AppOrder::getStatus, 0)
                .eq(AppOrder::getDelFlag, 0)
                .eq(AppOrder::getType, 2));
        if (appOrders.isEmpty()) return true;
        for (AppOrder appOrder : appOrders) {
            if (!appOrder.getProductIds().contains(categoryId)) {
                success = false;
                break;
            }
        }
        return success;
    }

    /**
     * @return
     * @Author SheepHy
     * @Description 根据不同的类型生成订单及订单明细
     * @Date 15:09 2025/7/15
     * @Param id type userId
     **/
    @Transactional
    public AppOrder createOrder(List<String> id, int type, String userId, String userIds) {
        //todo 保险 闸机待接入
        //订单类型；0场地1赛事2课程
        AppOrder appOrder = new AppOrder();
        switch (type) {
            case 0:
                List<AppSitePriceRules> priceRules = appSitePriceRulesMapper.selectList(Wrappers.<AppSitePriceRules>lambdaQuery()
                        .in(AppSitePriceRules::getId, id));
                BigDecimal totalPrice = priceRules.stream()
                        .map(AppSitePriceRules::getSellingPrice)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                if (priceRules.get(0).getType() == 0) {
                    if (totalPrice.compareTo(BigDecimal.ZERO) == 0) {
                        appOrder.setPayType(3)
                                .setOrderStatus(2)
                                .setPayTime(new Date());
                    } else {
                        appOrder.setPayType(2)
                                .setOrderStatus(1);
                    }
                    String s = generateOrderNumber(0);
                    appOrder.setOrderCode(s)
                            .setOrderCode(priceRules.get(0).getOrgCode())
                            .setProductIds(priceRules.get(0).getSitePlaceId())
                            .setType(0)
                            .setUserId(userId)
                            .setOriginalPrice(totalPrice)
                            .setPrice(totalPrice)
                            .setCreateTime(new Date())
                            .setUpdateTime(new Date())
                            .setCreateBy(userId)
                            .setUpdateBy(userId);
                    createOrderCoupon(s, userIds);
                    appOrderMapper.insert(appOrder);
                }
                break;
            case 1:

                break;
            case 2:

                break;
        }
        return appOrder;
    }

    @Override
    public NotifyResponse orderNotify(NotifyRequest notifyRequestForm) {

        //查询订单
        AppOrder appOrder = appOrderMapper.selectOne(Wrappers.<AppOrder>lambdaQuery().eq(AppOrder::getOrderCode, notifyRequestForm.getOut_trade_no()).last("limit 1"));
        if (ObjectUtil.isNotEmpty(appOrder)) {
            appOrder
                    .setPayId(notifyRequestForm.getAcc_trade_no())
                    .setOrderStatus(2)
                    .setPayStatus(2)
                    .setPayTime(DateUtil.parse(notifyRequestForm.getTrade_time(), "yyyyMMddHHmmss"))
                    .setCallbackStatus(1);
        }

        NotifyResponse notifyResponse = new NotifyResponse();
        notifyResponse.setCode("SUCCESS").setMessage("执行成功");

        return notifyResponse;
    }

    @Override
    public String orderQuery(String orderCode) throws IOException {

        //null代表查询失败 SUCCESS-成功 USERPAYING和ACCEPT为中间态 其他为支付失败
//        String s = weChatPayService.orderQueryByOutTradeNo(orderCode);
        String s = "SUCCESS";
        if ("SUCCESS".equals(s)) {
            //查询订单
            AppOrder appOrder = appOrderMapper.selectOne(Wrappers.<AppOrder>lambdaQuery().eq(AppOrder::getOrderCode, orderCode).last("limit 1"));
            if (ObjectUtil.isNotEmpty(appOrder)) {
                appOrder.setOrderStatus(1);
                appOrderMapper.updateById(appOrder);
                List<AppOrderProInfo> proInfoList = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery().eq(AppOrderProInfo::getOrderId, appOrder.getId()));
                if (CollUtil.isNotEmpty(proInfoList)){
                    for (AppOrderProInfo appOrderProInfo : proInfoList) {
                        appOrderProInfo.setOrderStatus(1);
                        appOrderProInfoMapper.updateById(appOrderProInfo);
                    }
                }

                return "100001";//支付成功
            }
        }
        if (s == null) {
            //查询订单
            return "100002";//查询失败
        }
        if ("USERPAYING".equals(s) || "ACCEPT".equals(s)) {
            //查询订单
            return "100003";//查询中
        }
        return "100004";//支付失败
    }

    @Override
    public String cancelOrder(String orderId) {
        AppOrder appOrder = appOrderMapper.selectById(orderId);
        if (ObjectUtil.isNotEmpty(appOrder)) {
            if (appOrder.getOrderStatus() == 0) {
                log.info("修改订单：{},支付状态为已取消", orderId);
                appOrder.setOrderStatus(4);
                appOrderMapper.updateById(appOrder);
                List<AppOrderProInfo> appOrderProInfoList = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery().eq(AppOrderProInfo::getOrderId, orderId));
                for (AppOrderProInfo appOrderProInfo : appOrderProInfoList) {
                    appOrderProInfo.setOrderStatus(2);
                    appOrderProInfoMapper.updateById(appOrderProInfo);
                }
            }
            return "取消成功！";
        }
        return "取消失败！未查询到订单！";
    }

    @Override
    public IPage<PageOrdersVO> pageOrders(PageOrdersForm pageOrdersForm) {

        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        pageOrdersForm.setUserId(loginUser.getId());

        Page<PageOrdersVO> page = new Page<>(pageOrdersForm.getPageNum(), pageOrdersForm.getPageSize());

        IPage<PageOrdersVO> pageOrders = appOrderMapper.pageOrders(page, pageOrdersForm);

        pageOrders.getRecords().forEach(record -> {

            Date createTime = record.getCreateTime();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(createTime);
            calendar.add(Calendar.MINUTE, 15);
            Date newTime = calendar.getTime();
            //设置超时订单时间
            record.setEpxTime(newTime);

            List<AppOrderProInfo> proInfoList = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery()
                    .eq(AppOrderProInfo::getOrderId, record.getOrderId())
            );
            if (ObjectUtil.isNotEmpty(proInfoList)) {
                List<AppOrderProInfo> infoList = proInfoList.stream().filter(orderProInfo -> !Objects.equals(orderProInfo.getType(), CommonConstant.ORDER_PRO_INFO_TYPE_6)).collect(Collectors.toList());
                List<AppOrderProInfo> insureList = proInfoList.stream().filter(orderProInfo -> Objects.equals(orderProInfo.getType(), CommonConstant.ORDER_PRO_INFO_TYPE_6)).collect(Collectors.toList());
                record.setOrderProInfoList(infoList);
                record.setOrderInsureList(insureList);
            }
        });
        return pageOrders;
    }

    @Override
    public String refundOrder(String orderCode) {

        //todo 分账退款

        AppOrder appOrder = appOrderMapper.selectOne(Wrappers.<AppOrder>lambdaQuery().eq(AppOrder::getOrderCode, orderCode).last("limit 1"));
        if (ObjectUtil.isNotEmpty(appOrder)) {
            if (appOrder.getOrderStatus() == 0) {
                log.info("修改订单：{},支付状态为退款中", orderCode);
                appOrder.setOrderStatus(5);
                appOrderMapper.updateById(appOrder);
                List<AppOrderProInfo> appOrderProInfoList = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery().eq(AppOrderProInfo::getOrderId, appOrder.getId()));
                for (AppOrderProInfo appOrderProInfo : appOrderProInfoList) {
                    appOrderProInfo.setOrderStatus(3);
                    appOrderProInfo.setAfterSaleStatus(1);
                    appOrderProInfoMapper.updateById(appOrderProInfo);
                }
            }
            return "退款成功！";
        }

        return "退款失败！";
    }

    @Override
    public Map<String, String> wechatPayNotify(HttpServletRequest request) {
        Map<String, String> stringStringMap = weChatPayService.wechatPayNotify(request);
        //对订单进行封账金额统计
        if (stringStringMap!=null
                && stringStringMap.containsKey("code")
                && "SUCCESS".equals(stringStringMap.get("code"))
                && stringStringMap.containsKey("orderCode")
               ){
            String orderCode = stringStringMap.get("orderCode");
            if(StringUtils.isEmpty(orderCode)){
                log.error("微信支付成功通知成功,订单编号为空,通知失败:"+JSONObject.toJSONString(stringStringMap));
                throw new JeecgBootException("微信支付成功通知成功,订单编号为空,通知失败");
            }
            AppOrder appOrder = appOrderMapper.selectOne(Wrappers.<AppOrder>lambdaQuery().eq(AppOrder::getOrderCode, orderCode).last("limit 1"));
            if (appOrder==null){
                log.error("微信支付成功通知成功,订单未查询到,通知失败:"+JSONObject.toJSONString(stringStringMap));
                throw new JeecgBootException("微信支付成功通知成功,订单未查询到,通知失败");
            }
            log.info("支付成功消息通知,订单信息："+JSONObject.toJSONString(appOrder));
            if (StringUtils.isEmpty(appOrder.getOrgCode())){
                log.error("微信支付成功通知成功,订单属于未知机构,通知失败");
                return stringStringMap;
            }
            if (appOrder.getType()!=null&&appOrder.getType()!=2){
                BigDecimal priceSum= appOrderProInfoMapper.findByOrderId(appOrder.getId());
                if (priceSum==null||priceSum.compareTo(BigDecimal.ZERO)==0){
                    log.error("微信支付成功通知成功,订单明细订单金额为0，不进行分账，orderId:"+appOrder.getId());
                    return stringStringMap;
                }
                SysDepart sysDepart= sysDepartMapper.findByOrgCodeAndParentId(appOrder.getOrgCode());
                if (sysDepart==null){
                    log.error("微信支付成功通知成功,未查询到部门信息,该订单属于未知订单");
                    return stringStringMap;
                }
                SysDepart byOrgCode = sysDepartMapper.findByOrgCode("A01");
                if (byOrgCode==null){
                    log.error("微信支付成功通知成功,未查询到观头信息,该订单属于无法分账");
                    return stringStringMap;
                }
                SeparateAccounts separateAccounts = separateAccountsMapper.findByDeptIdAndStatus(sysDepart.getId());
                ReceiptPaymentDetailsInfoVo receiptPaymentDetailsInfoVo = new ReceiptPaymentDetailsInfoVo();
                receiptPaymentDetailsInfoVo.setMoney(priceSum);
                receiptPaymentDetailsInfoVo.setPayType(0);
                receiptPaymentDetailsInfoVo.setPurseChangeReason(0);
                receiptPaymentDetailsInfoVo.setCreateTime(new Date());
                receiptPaymentDetailsInfoVo.setUpdateTime(new Date());
                receiptPaymentDetailsInfoVo.setOrderId(appOrder.getId());
                if (separateAccounts==null){
                    //需要按照默认比例分账 -暂时未处理。
                    log.error("微信支付成功通知成功,未查询到分账信息,不进行分账");
                    return stringStringMap;
                }
                BigDecimal shBigDecimal =BigDecimal.ZERO;
                try {
                    shBigDecimal = getBigDecimal(priceSum, separateAccounts.getShSeparateAccounts());
                } catch (Exception e) {
                    log.error("百分比计算错误", e);
                }
                BigDecimal ptBigDecimal =BigDecimal.ZERO;
                try {
                    ptBigDecimal = getBigDecimal(priceSum, separateAccounts.getPtSeparateAccounts());
                } catch (Exception e) {
                    log.error("百分比计算错误", e);
                }
                BigDecimal mdBigDecimal = priceSum.subtract(shBigDecimal).subtract(ptBigDecimal).setScale(2, RoundingMode.HALF_UP);
                ReceiptPaymentDetailsInfoVo receiptPaymentDetailsInfoVoMd = getChangeMoney(receiptPaymentDetailsInfoVo, appOrder.getOrgCode(), appOrder.getTenantId(), 2, mdBigDecimal);
                ReceiptPaymentDetailsInfoVo receiptPaymentDetailsInfoVoSh = getChangeMoney(receiptPaymentDetailsInfoVo, sysDepart.getOrgCode(), sysDepart.getId(), 1, shBigDecimal);
                ReceiptPaymentDetailsInfoVo receiptPaymentDetailsInfoVoPt = getChangeMoney(receiptPaymentDetailsInfoVo, byOrgCode.getOrgCode(), byOrgCode.getId(), 0, ptBigDecimal);

                log.info("支付成功消息通知,门店添加明细："+JSONObject.toJSONString(receiptPaymentDetailsInfoVo));
                iReceiptPaymentDetailsInfoService.add(receiptPaymentDetailsInfoVo);
            }

        }
        return stringStringMap;
    }



    private ReceiptPaymentDetailsInfoVo  getChangeMoney(ReceiptPaymentDetailsInfoVo receiptPaymentDetailsInfoVo,String orgCode,String deptId,Integer deptType,BigDecimal changeMoney){
        receiptPaymentDetailsInfoVo.setDeptId(deptId);
        receiptPaymentDetailsInfoVo.setDeptType(deptType);
        receiptPaymentDetailsInfoVo.setOrgCode(orgCode);
        receiptPaymentDetailsInfoVo.setChangeMoney(changeMoney);
        return receiptPaymentDetailsInfoVo;
    }
    private BigDecimal getBigDecimal(BigDecimal priceSum,BigDecimal proportion){
        if (proportion==null){
            return BigDecimal.ZERO;
        }else {
            if (proportion.compareTo(BigDecimal.ZERO) == 0) {
                return BigDecimal.ZERO;
            } else {   // 将百分比转换为小数（例如：50% -> 0.5）
                BigDecimal divisor = proportion.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP);
                // 执行除法运算，设置精度和舍入模式
                return priceSum.divide(divisor, 2, RoundingMode.HALF_UP);
            }
        }
    }


    /**
     * @return String 订单号
     * @Author SheepHy
     * @Description 订单编号生成逻辑
     * @Date 17:18 2025/7/15
     * @params 类型：0-（D:订单） 1-（T:退单） 2-（B:保单）
     **/
    private String generateOrderNumber(int type) {
        String format = DateUtil.format(new Date(), "yyyyMMddHHmmss");
        int nextInt = ThreadLocalRandom.current().nextInt(1000, 10000);

        if (type == 0) {
            return "D" + format + nextInt;
        } else {
            return "T" + format + nextInt;
        }
    }

    /**
     * @return
     * @Author SheepHy
     * @Description 根据订单及购买人数生成对应券码
     * @Date 10:20 2025/7/16
     * @Param
     **/
    private void createOrderCoupon(String orderId, String userIds) {
        String lastFourDigits = orderId.substring(orderId.length() - 4);
        int nextInt = ThreadLocalRandom.current().nextInt(1000, 10000);
        Arrays.asList(userIds.split(",")).forEach(userId -> {
            String substring = userId.substring(orderId.length() - 2);
            AppIsin appIsin = new AppIsin();
            appIsin.setOrderId(orderId)
                    .setFamilyId(userId)
                    .setTicketNo(lastFourDigits + nextInt + substring)
                    .setIsinStatus(1)
                    .setCreateTime(new Date())
                    .setUpdateTime(new Date());
        });
    }


    /**
     * 校验是否为第一次购买当前类目的课程
     *
     * @param userId
     * @param categoryId
     * @return
     */
    private Boolean checkOrderOrFree(String userId, String categoryId) {
        //查询当前用户的所有课程订单
        List<AppOrder> appOrders = appOrderMapper.selectList(Wrappers.<AppOrder>lambdaQuery().eq(AppOrder::getUserId, userId).eq(AppOrder::getType, CommonConstant.ORDER_TYPE_2));
        if (CollUtil.isNotEmpty(appOrders)){
            for (AppOrder appOrder : appOrders) {
                AppCourses appCours = appCoursesMapper.selectById(appOrder.getProductIds());
                if (appCours.getCategoryId().equals(categoryId)) {
                    return Boolean.FALSE;
                }
            }
        }
        return Boolean.TRUE;
    }
}
