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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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.DateUtils;
import org.jeecg.common.util.DictAnnotationUtil;
import org.jeecg.modules.app.dto.AppOrderInfoDTO;
import org.jeecg.modules.app.form.*;
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.RatiosUtil;
import org.jeecg.modules.pay.config.WechatConstants;
import org.jeecg.modules.pay.config.WechatUrlConstants;
import org.jeecg.modules.rabbitmq.DelayedMessageService;
import org.jeecg.modules.system.app.dto.ClassGroupingDTO;
import org.jeecg.modules.system.app.dto.receiptPaymentDetails.ReceiptPaymentDetailsInfoVo;
import org.jeecg.modules.system.app.entity.*;
import org.jeecg.modules.system.app.form.PriceChangeForm;
import org.jeecg.modules.system.app.mapper.*;
import org.jeecg.modules.system.app.vo.AppOrderProInfoVO;
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.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;
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 extends ServiceImpl<AppOrderMapper, AppOrder> 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;
    //    @Resource
//    private WechatPayV3Utils wechatPayV3Utils;
    @Resource
    private EvaluateMapper evaluateMapper;
    @Resource
    private SysDepartMapper sysDepartMapper;
    @Resource
    private SeparateAccountsMapper separateAccountsMapper;
    @Resource
    private DelayedMessageService delayedMessageService;
    @Resource
    private ShopMoneyMapper shopMoneyMapper;

    @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());
        
        log.info("[previewOrderPlaceSchool] placeId={}, startTime={}, teachingList={}, nonTeachingList={}", 
                placeId, DateUtil.format(startTime, "yyyy-MM-dd"), appSite.getTeachingDay(), appSite.getNoTeachingDay());

        timeSlot.forEach(a -> {
            // is_teaching: 0=是(教学日), 1=否(非教学日)
            boolean isTeaching = a.getIsTeaching() == 0;
            List<OrderVO.TimeSlotData> targetList = isTeaching ? teachingList : nonTeachingList;
            log.info("[previewOrderPlaceSchool] 原始timeSlot: is_teaching={}, 使用配置={}, startTime={}, endTime={}", 
                    a.getIsTeaching(), isTeaching ? "教学日" : "非教学日", a.getStartTime(), a.getEndTime());
            
            // 根据 is_teaching 动态替换时间段配置
            if (!targetList.isEmpty()) {
                OrderVO.TimeSlotData timeSlotData = targetList.get(0);
                try {
                    // 更新时间段
                    LocalTime newStartTime = LocalTime.parse(timeSlotData.getStartTime(), DateTimeFormatter.ofPattern("HH:mm"));
                    LocalTime newEndTime = LocalTime.parse(timeSlotData.getEndTime(), DateTimeFormatter.ofPattern("HH:mm"));
                    a.setStartTime(java.sql.Time.valueOf(newStartTime));
                    a.setEndTime(java.sql.Time.valueOf(newEndTime));
                    a.setName(timeSlotData.getStartTime() + "-" + timeSlotData.getEndTime());
                    
                    // 计算库存
                    int totalInventory = Integer.parseInt(timeSlotData.getTicketNum());
                    int bookedCount = appOrderMapper.queryBookedCount(
                            placeId,
                            DateUtil.format(startTime, "yyyy-MM-dd"),
                            timeSlotData.getStartTime(),
                            timeSlotData.getEndTime()
                    );
                    a.setInventory(totalInventory - bookedCount);
                    log.info("[previewOrderPlaceSchool] 更新后timeSlot: startTime={}, endTime={}, inventory={}", 
                            a.getStartTime(), a.getEndTime(), a.getInventory());
                } catch (Exception e) {
                    log.error("[previewOrderPlaceSchool] 解析时间段失败: {}", e.getMessage());
                }
            }
        });
        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);
            if (null == appSitePriceRule.getSellingPrice()) {
                appSitePriceRule.setSellingPrice(BigDecimal.ZERO);
            }
            priceRules.add(appSitePriceRule);
        });
        BigDecimal totalPrice = BigDecimal.ZERO;
        if (!priceRules.isEmpty()) {
            totalPrice = priceRules.stream()
                    .map(AppSitePriceRules::getSellingPrice)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }

        // 格式化 totalPrice 和 subtotal 为两位小数
        totalPrice = totalPrice.setScale(2, BigDecimal.ROUND_DOWN);
        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) {
        AppSitePlace sitePlace = appSitePlaceMapper.selectById(placeId);
        String orgCode = sitePlace.getOrgCode();
        log.info("[previewOrderPlaceSchoolTime] placeId={}, orgCode={}, siteId={}", placeId, orgCode, sitePlace.getSiteId());
        
        // 直接查询 nm_teaching_time 表的原始数据，确认数据库中的配置
        List<AppTeachingTime> rawTeachingTimes = appTeachingTimeMapper.selectList(
                Wrappers.<AppTeachingTime>lambdaQuery()
                        .eq(AppTeachingTime::getOrgCode, orgCode)
                        .ge(AppTeachingTime::getDay, cn.hutool.core.date.DateUtil.beginOfDay(new java.util.Date()))
                        .le(AppTeachingTime::getDay, cn.hutool.core.date.DateUtil.offsetDay(new java.util.Date(), 6))
                        .eq(AppTeachingTime::getDelFlag, 0)
        );
        log.info("[previewOrderPlaceSchoolTime] 原始数据库查询 nm_teaching_time 表，找到{}条记录:", rawTeachingTimes.size());
        rawTeachingTimes.forEach(t -> log.info("  -> day={}, is_teaching={}", t.getDay(), t.getIsTeaching()));
        
        List<OrderVO.PreviewOrderPlaceSchoolTime> previewOrderPlaceSchoolTimes = appTeachingTimeMapper.previewOrderPlaceSchoolTime(orgCode);
        AppSite appSite = appSiteMapper.selectOne(Wrappers.<AppSite>lambdaQuery().eq(AppSite::getId, sitePlace.getSiteId()));
        
        log.info("[previewOrderPlaceSchoolTime] Mapper查询到{}条教学时间记录", previewOrderPlaceSchoolTimes.size());
        previewOrderPlaceSchoolTimes.forEach(t -> log.info("[previewOrderPlaceSchoolTime] day={}, is_teaching={}, namedDay={}", t.getDay(), t.getIsTeaching(), t.getNamedDay()));
        
        // 解析教学日和非教学日数据
        List<OrderVO.TimeSlotData> teachingList = parseTimeSlotData(appSite.getTeachingDay());
        List<OrderVO.TimeSlotData> nonTeachingList = parseTimeSlotData(appSite.getNoTeachingDay());
        
        log.info("[previewOrderPlaceSchoolTime] teachingList size={}, nonTeachingList size={}", teachingList.size(), nonTeachingList.size());
        log.info("[previewOrderPlaceSchoolTime] 教学日原始配置 teachingDay={}", appSite.getTeachingDay());
        log.info("[previewOrderPlaceSchoolTime] 非教学日原始配置 noTeachingDay={}", appSite.getNoTeachingDay());
        if (!teachingList.isEmpty()) {
            log.info("[previewOrderPlaceSchoolTime] teachingList[0]: startTime={}, endTime={}, ticketNum={}", 
                    teachingList.get(0).getStartTime(), teachingList.get(0).getEndTime(), teachingList.get(0).getTicketNum());
        }
        if (!nonTeachingList.isEmpty()) {
            log.info("[previewOrderPlaceSchoolTime] nonTeachingList[0]: startTime={}, endTime={}, ticketNum={}", 
                    nonTeachingList.get(0).getStartTime(), nonTeachingList.get(0).getEndTime(), nonTeachingList.get(0).getTicketNum());
        }
        
        previewOrderPlaceSchoolTimes.forEach(previewOrderPlaceSchoolTime -> {
            // is_teaching: 0=是(教学日), 1=否(非教学日)
            boolean isTeaching = previewOrderPlaceSchoolTime.getIsTeaching() == 0;
            log.info("[previewOrderPlaceSchoolTime] day={}, is_teaching={}, 使用配置={}", 
                    previewOrderPlaceSchoolTime.getDay(), 
                    previewOrderPlaceSchoolTime.getIsTeaching(), 
                    isTeaching ? "教学日(teachingList)" : "非教学日(nonTeachingList)");
            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("系统正忙，请稍后再试");
//    }


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

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

        String userOpenId = sysUser.getOpenid();

        String orderCode = generateOrderNumber(0);

        //创建订单
        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())
                .setOrderExtraField(createOrderForm.getProductIds())
        ;
        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();

                    //判断是否已下单
                    List<String> familyIds = Arrays.stream(createOrderForm.getFamilyIds().split(",")).collect(Collectors.toList());
                    AppOrderProInfo proInfo = appOrderProInfoMapper.selectOne(Wrappers.<AppOrderProInfo>lambdaQuery()
                            .eq(AppOrderProInfo::getProductId, productId)
                            .ne(AppOrderProInfo::getOrderStatus, 4)
                            .in(AppOrderProInfo::getFamilyUserId, familyIds)
                            .last("limit 1")
                    );
                    if (ObjectUtil.isNotEmpty(proInfo)) {
                        String userName = proInfo.getUserName();
                        throw new JeecgBootException(userName + "已预约过该场地的同一日期和时段，无需重复预约，请直接进场。");
                    }

                    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);
                    //使用人
                    List<String> ids = Arrays.stream(createOrderForm.getFamilyIds().split(",")).collect(Collectors.toList());
                    log.info("学校场地预约商品库存数量：{}", stock);
                    // 缓存没有商品库存，查询数据库
                    if (stock == null || stock == 0 || stock < ids.size()) {
                        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 < ids.size()) {
                        throw new JeecgBootException("订单提交失败，库存不足");
                    }
                    // 更新数据库中的库存数据
                    log.info("更新学校场地数据库中的库存数据：{}", stock - ids.size());
                    int row = appSitePriceRulesMapper.update(null, Wrappers.<AppSitePriceRules>lambdaUpdate()
                            .eq(AppSitePriceRules::getId, productId)
                            .set(AppSitePriceRules::getTicketNum, (stock - ids.size())));
                    if (row > 0) {
                        // 更新Redis中缓存的商品库存数据
                        redisTemplate.opsForValue().decrement(stockKey, ids.size());
                    }
                    // 库存扣减完，创建订单
                    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())
                            .setOrProfitSharing(0)
                            .setCreateTime(new Date())
                            .setUpdateTime(new Date())
                            .setCreateBy(user.getId())
                            .setUpdateBy(user.getId())
                            .setStatus(CommonConstant.STATUS_NORMAL)
                            .setDelFlag(CommonConstant.DEL_FLAG_0);

                    for (String id : ids) {
                        FamilyMembers familyMembers = familyMembersMapper.selectById(id);
                        if (Objects.isNull(familyMembers)) {
                            throw new JeecgBootException("订单提交失败，用户不存在");
                        }
                        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;
                        if (priceRule.getEndTime() != null) {
                            expireTime = date + " " + endTime;
                        } else {
                            expireTime = date;
                        }
                        if (startTime == null) {
                            startTime = DateUtil.format(new Date(), "yyyy-MM-dd");
                        }
                        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)
                                .setSiteId(appOrder.getAddressSiteId())
                                .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 = BigDecimal.ZERO;

                    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");
                        String endTime = DateUtil.format(priceRule.getEndTime(), "HH:mm");
                        String expireTime = date + " " + endTime;

                        AppOrderProInfo appOrderProInfo = new AppOrderProInfo();
                        appOrderProInfo.setProductId(list.get(i).split("\\|")[0]);
                        appOrderProInfo.setProductName(date.substring(5) + " " + startTime + "-" + endTime + "|" + appSitePlace.getName());
                        appOrderProInfo.setProductImage(appSitePlace.getCover());
                        appOrderProInfo.setExpireTime(expireTime);
                        appOrderProInfo.setUseDateStr(date.substring(5));
                        appOrderProInfo.setAddress(appSite.getName());
                        appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_1);
                        appOrderProInfo.setProductImage(appSite.getCover());
                        appOrderProInfo.setOriginalPrice(priceRule.getSellingPrice());
                        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(appOrderProInfo.getPrice());
                    }

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

                    List<String> collect = list.stream().map(e -> e.split("\\|")[0]).collect(Collectors.toList());
                    String ids = String.join(",", collect);
                    appOrder
                            .setProductIds(ids)
                            .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 = BigDecimal.ZERO;
                    //团购优惠
                    BigDecimal tDiscounts = BigDecimal.ZERO;

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

                        //门店的营业时间
                        Integer indate = appSitePlace.getIndate();
                        String date = DateUtil.format(Date.from(LocalDate.now().plusDays(indate).atStartOfDay(ZoneId.systemDefault()).toInstant()), "yyyy-MM-dd");
                        String startTime = DateUtil.format(appSite.getStartTime(), "HH:mm");
                        String endTime = DateUtil.format(appSite.getEndTime(), "HH:mm");
                        if (ObjectUtil.isEmpty(appSite.getStartTime())) {
                            startTime = "00:00";
                        }
                        if (ObjectUtil.isEmpty(appSite.getEndTime())) {
                            endTime = "23:59";
                        }
                        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:
                //个人赛
                if (Objects.equals(createOrderForm.getOrderType(), CommonConstant.ORDER_PRO_INFO_TYPE_3)) {
                    AppGamePriceRules appGamePriceRules = appGamePriceRulesMapper.selectById(createOrderForm.getProductIds());
                    AppGame appGame = appGameMapper.findByPriceRules(appGamePriceRules.getId());
                    AppGameSchedule appGameSchedule = appGameScheduleMapper.selectOne(Wrappers.<AppGameSchedule>lambdaQuery().eq(AppGameSchedule::getGameId, appGame.getId()).last("limit 1"));

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

                    String startTime = DateUtil.format(appGame.getStartTime(), "HH:mm");
                    String endTime = DateUtil.format(appGame.getEndTime(), "HH:mm");

                    //订单总价（商品的售价总和）
                    BigDecimal sumPrice = BigDecimal.ZERO;

                    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());
                        if (appGame.getSiteType() == 1) {
                            appOrderProInfo.setAddress(appGameMapper.selectById(appGame.getId()).getAddress());
                        } else {
                            appOrderProInfo.setAddress(appSiteMapper.selectById(appGame.getSiteId()).getAddress());
                        }
                        appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_3);
                        appOrderProInfo.setFrameTimeStr(startTime + "-" + endTime);
                        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)
                            .setOriginalPrice(sumPrice)
                            .setCreateTime(new Date())
                            .setUpdateTime(new Date())
                            .setCreateBy(user.getId())
                            .setUpdateBy(user.getId())
                            .setStatus(CommonConstant.STATUS_NORMAL)
                            .setDelFlag(CommonConstant.DEL_FLAG_0);
                    if (ObjectUtil.isNotEmpty(appGame.getSiteId())) {
                        appOrder.setAddressSiteId(appGame.getSiteId());
                    }
                    if (StrUtil.isNotBlank(createOrderForm.getGameCertificationForm())) {
                        appOrder.setGameCertification(createOrderForm.getGameCertificationForm());
                    }
                }
                if (Objects.equals(createOrderForm.getOrderType(), CommonConstant.ORDER_PRO_INFO_TYPE_4)) {
                    AppGamePriceRules appGamePriceRules = appGamePriceRulesMapper.selectById(createOrderForm.getProductIds());
                    AppGame appGame = appGameMapper.findByPriceRules(appGamePriceRules.getId());
                    AppGameSchedule appGameSchedule = appGameScheduleMapper.selectOne(Wrappers.<AppGameSchedule>lambdaQuery().eq(AppGameSchedule::getGameId, appGame.getId()).last("limit 1"));


                    String startTime = DateUtil.format(appGame.getStartTime(), "HH:mm:ss");
                    String endTime = DateUtil.format(appGame.getEndTime(), "HH:mm:ss");

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

                    //订单总价（商品的售价总和）
                    BigDecimal sumPrice = appGamePriceRules.getSellingPrice();

                    List<String> familyIds = Arrays.stream(createOrderForm.getFamilyIds().split(",")).collect(Collectors.toList());
                    String ticketNo = RandomUtil.randomNumbers(10);
                    for (String familyId : familyIds) {
                        FamilyMembers familyMembers = familyMembersMapper.selectById(familyId);
                        AppOrderProInfo appOrderProInfo = new AppOrderProInfo();
                        appOrderProInfo.setProductId(createOrderForm.getProductIds());
                        appOrderProInfo.setProductName(appGame.getName());
                        if (appGame.getSiteType() == 1) {
                            appOrderProInfo.setAddress(appGameMapper.selectById(appGame.getId()).getAddress());
                        } else {
                            appOrderProInfo.setAddress(appSiteMapper.selectById(appGame.getSiteId()).getAddress());
                        }
                        appOrderProInfo.setTicketNo(ticketNo);
                        appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_4);
                        appOrderProInfo.setFrameTimeStr(startTime + "-" + endTime);
                        appOrderProInfo.setExpireTime(DateUtil.format(appGameSchedule.getEndTime(), "yyyy-MM-dd HH:mm:ss"));
                        appOrderProInfo.setOriginalPrice(appGamePriceRules.getSellingPrice());
                        appOrderProInfo.setPrice(BigDecimal.ZERO);
                        appOrderProInfo.setProductImage(appGame.getCover());
                        appOrderProInfo.setOrderStatus(0);
                        appOrderProInfo.setQuantity(1);
                        appOrderProInfo.setFamilyUserId(familyId);
                        appOrderProInfo.setUserName(familyMembers.getFullName());
                        appOrderProInfo.setUserPhone(familyMembers.getPhone());
                        appOrderProInfo.setStatus(CommonConstant.STATUS_0_INT);
                        appOrderProInfo.setDelFlag(CommonConstant.DEL_FLAG_0);

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

                    appOrder
                            .setType(CommonConstant.ORDER_TYPE_1)
                            .setOriginalPrice(sumPrice)
                            .setCreateTime(new Date())
                            .setUpdateTime(new Date())
                            .setCreateBy(user.getId())
                            .setUpdateBy(user.getId())
                            .setStatus(CommonConstant.STATUS_NORMAL)
                            .setDelFlag(CommonConstant.DEL_FLAG_0);
                    if (ObjectUtil.isNotEmpty(appGame.getSiteId())) {
                        appOrder.setAddressSiteId(appGame.getSiteId());
                    }
                    if (StrUtil.isNotBlank(createOrderForm.getGameCertificationForm())) {
                        appOrder.setGameCertification(createOrderForm.getGameCertificationForm());
                    }
                }
                break;
            //课程
            case 2:
                //课程
                AppCourses appCourse = appCoursesMapper.selectById(appOrder.getProductIds());
                if (ObjectUtil.isEmpty(appCourse)) {
                    log.error("当前课程不存在！");
                    throw new JeecgBootException("当前课程已下架！");
                }
                List<AppCoursesPriceRules> priceRulesList = appCoursesPriceRulesMapper.selectList(Wrappers.<AppCoursesPriceRules>lambdaQuery().eq(AppCoursesPriceRules::getCoursesId, appCourse.getId()));
                AppSite appSite = appSiteMapper.selectById(appCourse.getAddressSiteId());
                appOrder.setOrderOrFree(createOrderForm.getOrFreeOrder());
                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 = BigDecimal.ZERO;

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

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

                    String familyUserId = createOrderForm.getFamilyIds().split(",")[i - 1];
                    FamilyMembers familyMembers = familyMembersMapper.selectById(familyUserId);

                    //判断当前课程是否已下过单
                    List<AppOrderProInfo> infos = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery()
                            .eq(AppOrderProInfo::getProductId, appCourse.getId())
                            .eq(AppOrderProInfo::getFamilyUserId, familyUserId)
                    );
                    List<AppOrderProInfo> infoList = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery()
                            .eq(AppOrderProInfo::getProductId, appCourse.getId())
                            .eq(AppOrderProInfo::getFamilyUserId, familyUserId)
                            .eq(AppOrderProInfo::getOrFreePro, CommonConstant.STATUS_0_INT)
                            .notIn(AppOrderProInfo::getOrderStatus, CommonConstant.ORDER_STATUS_4, CommonConstant.ORDER_STATUS_5, CommonConstant.ORDER_STATUS_6)
                    );

                    if (ObjectUtil.isNotEmpty(infoList)) {
                        throw new JeecgBootException("当前课程已下过单，请勿重复下单");
                    }
                    if (Objects.equals(createOrderForm.getOrFreeOrder(), CommonConstant.STATUS_1_INT)) {
                        List<AppOrderProInfo> freeProList = infos.stream()
                                .filter(info -> Objects.equals(info.getOrFreePro(), CommonConstant.STATUS_0_INT) && !Objects.equals(info.getOrderStatus(), CommonConstant.ORDER_PRO_INFO_TYPE_4))
                                .collect(Collectors.toList());
                        if (ObjectUtil.isNotEmpty(freeProList)) {
                            throw new JeecgBootException("当前试听课课程已下过单，请勿重复下单");
                        }
                    }
                    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.setUseDateStr(DateUtil.format(appCourse.getStartTime(), "yyyy-MM-dd"));
                    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)) {

                        if (Objects.equals(appOrder.getOrderOrFree(), CommonConstant.STATUS_0_INT)) {
                            //非试听课
                            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 (Objects.equals(appOrder.getOrderOrFree(), CommonConstant.STATUS_1_INT)) {
                            priceRulesList.sort(Comparator.comparing(AppCoursesPriceRules::getSort));
                            AppCoursesPriceRules appCoursesPriceRules = priceRulesList.get(0);
                            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.getOriginalPrice());
                            appOrderProInfo.setOrFreePro(CommonConstant.STATUS_1_INT);
                            appOrderProInfo.setOrderStatus(1);
                            appOrderProInfo.setOriginalPrice(appCourse.getOriginalPrice());
                            appOrderProInfo.setPrice(BigDecimal.ZERO);
                            appOrder.setContractNo(null);
                            appOrder.setOrderStatus(1);
                            //试听优惠
                            appOrder.setSDiscounts(sDiscounts);
                            appOrder.setOrderOrFree(CommonConstant.STATUS_1_INT);
                            appOrder.setOrProfitSharing(0);
                        }
                    }
                    proInfoList.add(appOrderProInfo);

                    tDiscounts = tDiscounts.add(appCourse.getOriginalPrice().subtract(appCourse.getSellingPrice()));
                    if (createOrderForm.getOrFreeOrder() == 1) {
                        tDiscounts = BigDecimal.ZERO;
                    }
                    sumCoursePrice = sumCoursePrice.add(appCourse.getSellingPrice());
                    if (createOrderForm.getOrFreeOrder() == 1) {
                        sumCoursePrice = BigDecimal.ZERO;
                    }
                }

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

                //团购优惠
                appOrder.setTDiscounts(tDiscounts);
                if (createOrderForm.getOrFreeOrder() == 1) {
                    //团购优惠
                    appOrder.setTDiscounts(BigDecimal.ZERO);
                }
                //使用人IDs
                appOrder.setFamilyIds(createOrderForm.getFamilyIds());

                appOrder.setAddressSiteId(appCourse.getAddressSiteId());
                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.setOriginalPrice(totalPrice);
        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());
            List<CreateOrderForm.AddGradeLevelInformation> addGradeLevelInformation1 = createOrderForm.getAddGradeLevelInformation();
            if(null != addGradeLevelInformation1){
                addGradeLevelInformation1.forEach(addGradeLevelInformation -> {
                    if(appOrderProInfo.getFamilyUserId().equals(addGradeLevelInformation.getFamilyId())){
                        appOrderProInfo.setLevelInfo(addGradeLevelInformation.getLevelInfo());
                    }
                });
            }
            if (!Objects.equals(appOrderProInfo.getType(), CommonConstant.ORDER_PRO_INFO_TYPE_4)) {
                appOrderProInfo.setTicketNo(RandomUtil.randomNumbers(10));
            }
            if (appOrderProInfoMapper.insert(appOrderProInfo) > 0) {
                if (appOrderProInfo.getType() == 5) {
                    AppSite appSite = appSiteMapper.selectById(appCoursesMapper.selectById(appOrderProInfo.getProductId()).getAddressSiteId());
                    if (null != appSite &&
                            appSite.getType() == 0) {
                        // 查询该用户所有待使用的课程订单，合并时间范围
                        List<AppOrderProInfo> allCourseOrders = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery()
                                .eq(AppOrderProInfo::getFamilyUserId, appOrderProInfo.getFamilyUserId())
                                .eq(AppOrderProInfo::getOrderStatus, 1)
                                .eq(AppOrderProInfo::getType, 5)
                                .isNotNull(AppOrderProInfo::getFrameTimeStr));
                        
                        FamilyMembers familyMembers = familyMembersMapper.selectById(appOrderProInfo.getFamilyUserId());
                        
                        if (CollUtil.isNotEmpty(allCourseOrders)) {
                            // 解析所有订单的frameTimeStr，找出最早和最晚的日期
                            LocalDate earliestStartDate = null;
                            LocalDate latestEndDate = null;
                            
                            for (AppOrderProInfo courseOrder : allCourseOrders) {
                                String frameTimeStr = courseOrder.getFrameTimeStr();
                                if (frameTimeStr != null && !frameTimeStr.isEmpty()) {
                                    try {
                                        // 解析 "yyyy-MM-dd-MM-dd" 格式
                                        String[] parts = frameTimeStr.split("-");
                                        if (parts.length == 5) {
                                            String startDateStr = parts[0] + "-" + parts[1] + "-" + parts[2];
                                            String endDateStr = parts[0] + "-" + parts[3] + "-" + parts[4];
                                            
                                            LocalDate startDate = LocalDate.parse(startDateStr);
                                            LocalDate endDate = LocalDate.parse(endDateStr);
                                            
                                            // 找出最早的开始日期
                                            if (earliestStartDate == null || startDate.isBefore(earliestStartDate)) {
                                                earliestStartDate = startDate;
                                            }
                                            // 找出最晚的结束日期
                                            if (latestEndDate == null || endDate.isAfter(latestEndDate)) {
                                                latestEndDate = endDate;
                                            }
                                        }
                                    } catch (Exception e) {
                                        // 解析失败，跳过该订单
                                        log.error("解析课程订单frameTimeStr失败: {}", frameTimeStr, e);
                                    }
                                }
                            }
                            
                            // 如果找到了有效的日期范围，合并为一个frameTimeStr
                            if (earliestStartDate != null && latestEndDate != null) {
                                // 构造合并后的frameTimeStr: "yyyy-MM-dd-MM-dd"
                                String mergedFrameTimeStr = earliestStartDate.getYear() + "-" +
                                        String.format("%02d", earliestStartDate.getMonthValue()) + "-" +
                                        String.format("%02d", earliestStartDate.getDayOfMonth()) + "-" +
                                        String.format("%02d", latestEndDate.getMonthValue()) + "-" +
                                        String.format("%02d", latestEndDate.getDayOfMonth());
                                
                                // 使用合并后的时间范围更新门禁权限
                                for (AppDevice appDevice : appDeviceMapper.selectList(Wrappers.<AppDevice>lambdaQuery().eq(AppDevice::getSiteId, appSite.getId()))) {
                                    if (null != appDevice) {
                                        JsonObject addUserJson = JsonParser.parseString(addUser(
                                                new Date(),  // inputDate可以传任意值，会被frameTimeStr覆盖
                                                appDevice.getDeviceSerial(),
                                                appOrderProInfo.getUserName(),
                                                familyMembers.getId(),
                                                null,  // endDate会被frameTimeStr覆盖
                                                mergedFrameTimeStr)).getAsJsonObject();
                                        JsonObject addFaceJson = JsonParser.parseString(addFace(
                                                appDevice.getDeviceSerial(),
                                                familyMembers.getId(),
                                                familyMembers.getRealNameImg())).getAsJsonObject();
                                        if (addUserJson.get("code").getAsInt() != 0 && addFaceJson.get("code").getAsInt() != 0) {
                                            throw new JeecgBootException("设备录入用户信息失败！请联系管理员");
                                        }
                                    }
                                }
                            }
                        } else if (null != appOrderProInfo.getFrameTimeStr()) {
                            // 如果只有当前订单，直接使用当前订单的frameTimeStr
                            for (AppDevice appDevice : appDeviceMapper.selectList(Wrappers.<AppDevice>lambdaQuery().eq(AppDevice::getSiteId, appSite.getId()))) {
                                if (null != appDevice) {
                                    JsonObject addUserJson = JsonParser.parseString(addUser(
                                            new Date(),
                                            appDevice.getDeviceSerial(),
                                            appOrderProInfo.getUserName(),
                                            familyMembers.getId(),
                                            null,
                                            appOrderProInfo.getFrameTimeStr())).getAsJsonObject();
                                    JsonObject addFaceJson = JsonParser.parseString(addFace(
                                            appDevice.getDeviceSerial(),
                                            familyMembers.getId(),
                                            familyMembers.getRealNameImg())).getAsJsonObject();
                                    if (addUserJson.get("code").getAsInt() != 0 && addFaceJson.get("code").getAsInt() != 0) {
                                        throw new JeecgBootException("设备录入用户信息失败！请联系管理员");
                                    }
                                }
                            }
                        }
                    }
                }
            }
            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())
                        //过期时间
                        .setExpireTime(appOrderProInfo.getExpireTime())
                        //生成10位随机券号
                        .setTicketNo(appOrderProInfo.getTicketNo())
                        .setIsinStatus(CommonConstant.ISIN_STATUS_0);
                if (appOrder.getType() == 0) {
                    String s = createOrderForm.getProductIds().split(",")[0];
                    String priceRuleId = s.split("\\|")[0];
                    AppSitePriceRules priceRule = appSitePriceRulesMapper.selectById(priceRuleId);
                    AppSitePlace appSitePlace = appSitePlaceMapper.selectById(priceRule.getSitePlaceId());
                    AppSite appSite = appSiteMapper.selectById(appSitePlace.getSiteId());
                    appIsin.setUseAddress(appSite.getName());
                }
                if (appOrder.getType() == 1) {
                    AppGamePriceRules appGamePriceRules = appGamePriceRulesMapper.selectById(createOrderForm.getProductIds());
                    AppGame appGame = appGameMapper.findByPriceRules(appGamePriceRules.getId());
                    appIsin.setUseAddress(sysDepartMapper.selectOne(Wrappers.<SysDepart>lambdaQuery().eq(SysDepart::getOrgCode, appGame.getOrgCode())).getDepartName());
                }
                if (appOrder.getType() == 2) {
                    AppSite appSite = appSiteMapper.selectById(appCoursesMapper.selectById(appOrderProInfo.getProductId()).getAddressSiteId());
                    appIsin.setUseAddress(appSite.getName());

                    //判断当前课程是否是在学校上课
                    if (appSite.getType() == 0) {
                        //查询当前课程的课时
                        AppCourses appCourses = appCoursesMapper.selectById(appOrderProInfo.getProductId());
                        List<AppCoursesPriceRules> appCoursesPriceRules = appCoursesPriceRulesMapper.selectList(Wrappers.<AppCoursesPriceRules>lambdaQuery().eq(AppCoursesPriceRules::getCoursesId,
                                appCourses.getId()));
                        for (AppCoursesPriceRules appCoursesPriceRule : appCoursesPriceRules) {
                            AppIsin appIsinInfo = new AppIsin();
                            appIsinInfo
                                    .setOrderId(appOrder.getId())
                                    .setOrgCode(appOrder.getOrgCode())
                                    .setOrderCode(appOrder.getOrderCode())
                                    .setOrderProInfoId(appOrderProInfo.getId())
                                    .setCoursePriceRuleId(appCoursesPriceRule.getId())
                                    .setFamilyId(appOrderProInfo.getFamilyUserId())
                                    .setFamilyUserName(appOrderProInfo.getUserName())
                                    .setTicketNo(appOrderProInfo.getTicketNo())
                                    .setIsinStatus(CommonConstant.ISIN_STATUS_0);
                            appIsinMapper.insert(appIsinInfo);
                        }
                    }
                }
                appIsinMapper.insert(appIsin);
            }
            if (Objects.equals(appOrderProInfo.getType(), CommonConstant.ORDER_PRO_INFO_TYPE_0)) {
                log.info("========== 场地订单门禁设置开始 ==========");
                log.info("订单ID: {}, 用户: {}, useDateStr: {}, frameTimeStr: {}", 
                        appOrderProInfo.getId(), appOrderProInfo.getUserName(), 
                        appOrderProInfo.getUseDateStr(), appOrderProInfo.getFrameTimeStr());
                
                FamilyMembers familyMembers = familyMembersMapper.selectById(appOrderProInfo.getFamilyUserId());
                // 查询该用户所有待使用的场地订单，找出最早和最晚的使用日期
                List<AppOrderProInfo> allFieldOrders = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery()
                        .eq(AppOrderProInfo::getFamilyUserId, appOrderProInfo.getFamilyUserId())
                        .eq(AppOrderProInfo::getOrderStatus, 1)
                        .eq(AppOrderProInfo::getType, 0)
                        .isNotNull(AppOrderProInfo::getUseDateStr));
                
                log.info("查询到用户 {} 的场地订单数量: {}", familyMembers.getFullName(), allFieldOrders.size());
                
                if (CollUtil.isNotEmpty(allFieldOrders)) {
                    // 解析所有订单的useDateStr，找出最早和最晚的日期
                    LocalDate earliestDate = null;
                    LocalDate latestDate = null;
                    
                    for (AppOrderProInfo fieldOrder : allFieldOrders) {
                        String useDateStr = fieldOrder.getUseDateStr();
                        if (useDateStr != null && !useDateStr.isEmpty()) {
                            try {
                                // 解析日期 "yyyy-MM-dd"
                                LocalDate useDate = LocalDate.parse(useDateStr);
                                log.info("  订单 {} 的useDateStr: {} -> 解析为: {}", 
                                        fieldOrder.getId(), useDateStr, useDate);
                                
                                // 找出最早的日期
                                if (earliestDate == null || useDate.isBefore(earliestDate)) {
                                    earliestDate = useDate;
                                }
                                // 找出最晚的日期
                                if (latestDate == null || useDate.isAfter(latestDate)) {
                                    latestDate = useDate;
                                }
                            } catch (Exception e) {
                                // 解析失败，跳过该订单
                                log.error("解析场地订单useDateStr失败: {}", useDateStr, e);
                            }
                        }
                    }
                    
                    log.info("日期范围统计 - 最早: {}, 最晚: {}", earliestDate, latestDate);
                    
                    // 使用解析到的日期范围更新门禁权限
                    if (earliestDate != null && latestDate != null) {
                        for (AppDevice appDevice : appDeviceMapper.selectList(Wrappers.<AppDevice>lambdaQuery().eq(AppDevice::getOrgCode, appOrder.getOrgCode()))) {
                            if (null != appDevice) {
                                // 将LocalDate转换为Date类型，使用正午12:00避免时区问题
                                Date startDate = Date.from(earliestDate.atTime(12, 0).atZone(ZoneId.systemDefault()).toInstant());
                                Date endDate = Date.from(latestDate.atTime(12, 0).atZone(ZoneId.systemDefault()).toInstant());
                                
                                log.info("转换为Date - startDate: {}, endDate: {}", startDate, endDate);
                                log.info("准备调用addUser - deviceSerial: {}, employeeNo: {}, frameTimeStr: {}",
                                        appDevice.getDeviceSerial(), familyMembers.getId(), appOrderProInfo.getFrameTimeStr());
                                
                                String addUser = addUser(
                                        startDate,  // 使用最早的使用日期
                                        appDevice.getDeviceSerial(),
                                        appOrderProInfo.getUserName(),
                                        familyMembers.getId(),
                                        endDate,  // 使用最晚的使用日期
                                        appOrderProInfo.getFrameTimeStr());  // 传入时间段
                                
                                log.info("addUser返回结果: {}", addUser);
                                
                                String addFace = addFace(appDevice.getDeviceSerial(), familyMembers.getId(),
                                        familyMembers.getRealNameImg());
                                
                                log.info("addFace返回结果: {}", addFace);
                                
                                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("设备录入用户信息失败！请联系管理员");
                            }
                        }
                    }
                }
                log.info("========== 场地订单门禁设置结束 ==========");
            }
        }

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

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

        //判断是否试听课（试听课不走订单）
        if ((ObjectUtil.isNotEmpty(appOrder.getOrderOrFree()) && appOrder.getOrderOrFree() == 1) || appOrder.getPrice().compareTo(BigDecimal.ZERO) == 0) {
            payForm.setOrPayOrder(0);
        } else {
            //分账能否成功，判断是否可以下单
            List<AppOrderProInfo> orderProInfoList =
                    proInfoList.stream().filter(appOrderProInfo -> Objects.equals(appOrderProInfo.getType(), CommonConstant.ORDER_PRO_INFO_TYPE_6)).collect(Collectors.toList());
            BigDecimal insurePrice = BigDecimal.ZERO;
            if (CollUtil.isNotEmpty(orderProInfoList)) {
                BigDecimal reduce = orderProInfoList.stream().map(AppOrderProInfo::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                insurePrice = insurePrice.add(reduce);
            }
            //创建预分账详情
            String orgCode = appOrder.getOrgCode();
            SysDepart depart = sysDepartMapper.selectOne(Wrappers.lambdaQuery(SysDepart.class).eq(SysDepart::getOrgCode, orgCode).last("limit 1"));
            String deptId = depart.getId();
            if (depart.getSystemType() == 2) {
                deptId = depart.getParentId();
            }
            if (depart.getSystemType() != 0) {
                SeparateAccounts separateAccounts = separateAccountsMapper.selectOne(Wrappers.lambdaQuery(SeparateAccounts.class).eq(SeparateAccounts::getDeptId, deptId));
                if (ObjectUtil.isEmpty(separateAccounts)) {
                    throw new JeecgBootException("商户信息未配置！请联系管理员");
                }
                //获取分账比例
                BigDecimal PT = separateAccounts.getPtSeparateAccounts();
                BigDecimal SH = separateAccounts.getShSeparateAccounts();
                BigDecimal MD = separateAccounts.getMdSeparateAccounts();
                //分账金额(支付金额-保险金额)
                BigDecimal price = appOrder.getPrice().subtract(insurePrice);
                //微信手续费,不足1分按1分算(当计算值小于0.01时强制提升至0.01)
//                BigDecimal FEE = calculate(price, new BigDecimal("0.006"));

//                price = price.subtract(FEE);

                //商户（分账给平台）
                if (depart.getSystemType() == 1) {
                    BigDecimal[] allocate = RatiosUtil.allocate(price, new BigDecimal[]{SH, PT});
                    if (appOrder.getPrice().multiply(BigDecimal.valueOf(0.3)).compareTo(allocate[1].add(insurePrice)) < 0) {
                        throw new JeecgBootException("订单金额不支持分账,无法下单！");
                    }
                }
                //门店（分账给平台及商户）
                if (depart.getSystemType() == 2) {
                    BigDecimal[] allocate = RatiosUtil.allocate(price, MD, SH, PT);
                    if (appOrder.getPrice().multiply(BigDecimal.valueOf(0.3)).compareTo(allocate[1].add(allocate[2]).add(insurePrice)) < 0) {
                        throw new JeecgBootException("订单金额不支持分账,无法下单！");
                    }
                }
            }

            Map<String, String> result = payment(appOrder.getId(),userOpenId);
            payForm.setParams(result);

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

            //发送延迟消息
            delayedMessageService.sendOrderMessage(appOrder.getOrderCode());
        }
        return payForm;
    }

    /**
     * 订单价格修改
     * @param priceChangeForm
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public UserPayForm orderChangePrice(PriceChangeForm priceChangeForm){
        AppOrder order = appOrderMapper.selectById(priceChangeForm.getOrderId());
        String userOpenId = order.getUserOpenId();
        if (ObjectUtil.isEmpty(order)){
            throw new JeecgBootException("订单不存在！");
        }
        String orderCode = generateOrderNumber(0);
        BigDecimal tDiscounts = BigDecimal.ZERO;
        //修改订单价格
        order.setPrice(priceChangeForm.getPrice());
        //修改订单状态
        order.setOrderStatus(CommonConstant.ORDER_STATUS_0);
        order.setPayStatus(CommonConstant.ORDER_STATUS_0);
        //修改订单创建时间
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());
        //修改订单编号
        order.setOrderCode(orderCode);
        //修改试听优惠


        //修改子订单
        List<AppOrderProInfo> orderProInfoList = appOrderProInfoMapper.selectList(Wrappers.lambdaQuery(AppOrderProInfo.class).eq(AppOrderProInfo::getOrderId, order.getId()));
        List<AppOrderProInfo> newOrderProInfoList = new ArrayList<>();
        List<PriceChangeForm.OrderItemForm> orderItemList = priceChangeForm.getOrderItemList();
        for (PriceChangeForm.OrderItemForm orderItemForm : orderItemList) {
            orderProInfoList.forEach(appOrderProInfo -> {
                if (appOrderProInfo.getId().equals(orderItemForm.getOrderProInfoId())) {
                    appOrderProInfo.setOrderCode(orderCode);
                    appOrderProInfo.setPrice(orderItemForm.getOriginalPrice());
                    appOrderProInfo.setOrderStatus(CommonConstant.ORDER_STATUS_0);
                    appOrderProInfo.setCreateTime(new Date());
                    appOrderProInfo.setUpdateTime(new Date());
                    newOrderProInfoList.add(appOrderProInfo);
                }
            });
        }
        for (AppOrderProInfo appOrderProInfo : newOrderProInfoList) {
            appOrderProInfoMapper.updateById(appOrderProInfo);
        }
        //修改团购优惠
        if (Objects.equals(order.getOrderType(), CommonConstant.ORDER_PRO_INFO_TYPE_2)
                || Objects.equals(order.getOrderType(), CommonConstant.ORDER_PRO_INFO_TYPE_5)){
            List<AppOrderProInfo> proInfoList = appOrderProInfoMapper.selectList(Wrappers.lambdaQuery(AppOrderProInfo.class).eq(AppOrderProInfo::getOrderId,
                    order.getId()));
            for (AppOrderProInfo appOrderProInfo : proInfoList) {
                if (!Objects.equals(appOrderProInfo.getType(), CommonConstant.ORDER_PRO_INFO_TYPE_6)){
                    tDiscounts = tDiscounts.add(appOrderProInfo.getOriginalPrice().subtract(appOrderProInfo.getPrice()));
                }
            }
            order.setTDiscounts(tDiscounts);
        }
        //修改试听优惠
        if (Objects.equals(order.getOrderType(), CommonConstant.ORDER_PRO_INFO_TYPE_5) && Objects.equals(order.getOrderOrFree(), CommonConstant.NUMBER_1)){
            order.setSDiscounts(order.getOriginalPrice());
        }
        appOrderMapper.updateById(order);
        //修改签署记录
        List<AppContractSign> appContractSigns = appContractSignMapper.selectList(Wrappers.lambdaQuery(AppContractSign.class).eq(AppContractSign::getOrderId, order.getId()));
        for (AppContractSign appContractSign : appContractSigns) {
            appContractSign.setOrderId(order.getId());
            appContractSign.setUpdateTime(new Date());
            appContractSignMapper.updateById(appContractSign);
        }
        //修改保单
        List<InsureOrderInfo> insureOrderInfoList = insureOrderInfoMapper.selectList(Wrappers.lambdaQuery(InsureOrderInfo.class).eq(InsureOrderInfo::getOrderId, order.getId()));
        for (InsureOrderInfo insureOrderInfo : insureOrderInfoList) {
            insureOrderInfo.setOrderId(order.getId());
            insureOrderInfo.setUpdateTime(new Date());
            insureOrderInfoMapper.updateById(insureOrderInfo);
        }
        //修改券号记录
        List<AppIsin> appIsins = appIsinMapper.selectList(Wrappers.lambdaQuery(AppIsin.class).eq(AppIsin::getOrderId, order.getId()));
        for (AppIsin appIsin : appIsins) {
            appIsin.setOrderId(order.getId());
            appIsin.setOrderCode(orderCode);
            appIsin.setUpdateTime(new Date());
            appIsinMapper.updateById(appIsin);
        }
        //修改核销记录
        List<AppCoursesVerificationRecord> appCoursesVerificationRecords = appCoursesVerificationRecordMapper.selectList(Wrappers.lambdaQuery(AppCoursesVerificationRecord.class).eq(AppCoursesVerificationRecord::getOrderId, order.getId()));
        for (AppCoursesVerificationRecord appCoursesVerificationRecord : appCoursesVerificationRecords) {
            appCoursesVerificationRecord.setOrderId(order.getId());
            appCoursesVerificationRecord.setOrderCode(orderCode);
            appCoursesVerificationRecord.setCreateTime(new Date());
            appCoursesVerificationRecord.setUpdateTime(new Date());
            appCoursesVerificationRecordMapper.updateById(appCoursesVerificationRecord);
        }
        //构建支付表单返回给前端支撑JsApi支付调用
        UserPayForm payForm = new UserPayForm();
        payForm.setOrderId(order.getId()).setOrderCode(orderCode);
        //判断是否试听课（试听课不走订单）
        if ((ObjectUtil.isNotEmpty(order.getOrderOrFree()) && order.getOrderOrFree() == 1) || order.getPrice().compareTo(BigDecimal.ZERO) == 0) {
            payForm.setOrPayOrder(0);
        } else {
            //分账能否成功，判断是否可以下单
            List<AppOrderProInfo> proList =
                    orderProInfoList.stream().filter(appOrderProInfo -> Objects.equals(appOrderProInfo.getType(), CommonConstant.ORDER_PRO_INFO_TYPE_6)).collect(Collectors.toList());
            BigDecimal insurePrice = BigDecimal.ZERO;
            if (CollUtil.isNotEmpty(proList)) {
                BigDecimal reduce = proList.stream().map(AppOrderProInfo::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                insurePrice = insurePrice.add(reduce);
            }
            //创建预分账详情
            String orgCode = order.getOrgCode();
            SysDepart depart = sysDepartMapper.selectOne(Wrappers.lambdaQuery(SysDepart.class).eq(SysDepart::getOrgCode, orgCode).last("limit 1"));
            String deptId = depart.getId();
            if (depart.getSystemType() == 2) {
                deptId = depart.getParentId();
            }
            if (depart.getSystemType() != 0) {
                SeparateAccounts separateAccounts = separateAccountsMapper.selectOne(Wrappers.lambdaQuery(SeparateAccounts.class).eq(SeparateAccounts::getDeptId, deptId));
                if (ObjectUtil.isEmpty(separateAccounts)) {
                    throw new JeecgBootException("商户信息未配置！请联系管理员");
                }
                //获取分账比例
                BigDecimal PT = separateAccounts.getPtSeparateAccounts();
                BigDecimal SH = separateAccounts.getShSeparateAccounts();
                BigDecimal MD = separateAccounts.getMdSeparateAccounts();
                //分账金额(支付金额-保险金额)
                BigDecimal price = order.getPrice().subtract(insurePrice);

                //商户（分账给平台）
                if (depart.getSystemType() == 1) {
                    BigDecimal[] allocate = RatiosUtil.allocate(price, new BigDecimal[]{SH, PT});
                    if (order.getPrice().multiply(BigDecimal.valueOf(0.3)).compareTo(allocate[1].add(insurePrice)) < 0) {
                        throw new JeecgBootException("订单金额不支持分账,无法下单！");
                    }
                }
                //门店（分账给平台及商户）
                if (depart.getSystemType() == 2) {
                    BigDecimal[] allocate = RatiosUtil.allocate(price, MD, SH, PT);
                    if (order.getPrice().multiply(BigDecimal.valueOf(0.3)).compareTo(allocate[1].add(allocate[2]).add(insurePrice)) < 0) {
                        throw new JeecgBootException("订单金额不支持分账,无法下单！");
                    }
                }
            }
            Map<String, String> result = payment(order.getId(),userOpenId);
            payForm.setParams(result);
            //发送延迟消息
            delayedMessageService.sendOrderMessage(order.getOrderCode());
        }
        return payForm;
    }

    private static final BigDecimal MIN_THRESHOLD = new BigDecimal("0.01"); // 最小阈值

    /**
     * 计算千分之6并处理临界值
     *
     * @param input 输入金额（单位：元）
     * @return 计算结果（保留两位小数，不足0.01按0.01计算）
     * @throws IllegalArgumentException 输入为null或负数时抛出
     */
    public static BigDecimal calculate(BigDecimal input, BigDecimal multiplier) {
        if (input == null) {
            throw new IllegalArgumentException("输入金额不能为null");
        }
        if (input.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalArgumentException("输入金额不能为负数");
        }

        // 精确乘法运算（保留4位中间精度）
        BigDecimal product = input.multiply(multiplier)
                .setScale(4, RoundingMode.HALF_UP);

        // 临界值判断与补偿
        return product.compareTo(MIN_THRESHOLD) < 0
                ? MIN_THRESHOLD
                : product.setScale(2, RoundingMode.DOWN);
    }

    public Map<String, String> payment(String appOrderId,String userOpenId) {
        AppOrder appOrder = appOrderMapper.selectById(appOrderId);
        //查询商户信息
        String orgCode = appOrder.getOrgCode();
        SysDepart depart = sysDepartMapper.selectOne(Wrappers.lambdaQuery(SysDepart.class).eq(SysDepart::getOrgCode, orgCode).last("limit 1"));
        String subMchId = depart.getMchId();
        if(StrUtil.isBlank(subMchId)){
            throw new JeecgBootException("商户未进行支付配置！请联系管理员");
        }
        if (Objects.equals(appOrder.getOrderStatus(), CommonConstant.ORDER_STATUS_4)) {
            throw new JeecgBootException("当前订单已过期，请重新下单！");
        }

        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("sp_appid", WechatConstants.WECHAT_SP_APPID); //服务商appid
        params.put("sp_mchid", WechatConstants.WECHAT_SP_MCH_ID);//服务商商户号
        params.put("sub_appid", WechatConstants.WECHAT_SUB_APPID); //小程序appid
        params.put("sub_mchid", subMchId); //特约商户商户号

        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); //支付结果异步通知接口
        //分账必传参数
        if (appOrder.getOrderType() != 0) {
            JSONObject settleInfo = new JSONObject();
            settleInfo.put("profit_sharing", Boolean.TRUE);
            params.put("settle_info", settleInfo);
        }
        //电子发票入口
        params.put("support_fapiao", Boolean.TRUE);

        //订单金额信息
        JSONObject amount_json = new JSONObject();
        //支付金额 单位：分
        amount_json.put("total", Integer.parseInt(amount_fee(appOrder.getPrice())));
//        amount_json.put("total", Integer.parseInt(amount_fee(new BigDecimal("0.01"))));//测试0.01元
        amount_json.put("currency", "CNY");//固定传：CNY，代表人民币
        params.put("amount", amount_json);

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

        //拉起支付-返回JSAPI参数
        return weChatPayService.wechatPay(params);
    }

    /**
     * 金额元转分字符串
     *
     * @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) {
        OrderVO.PreviewOrderPlaceGymnasiumNoFixation previewOrderPlaceGymnasiumNoFixation = appSitePlaceMapper.previewOrderPlaceGymnasiumNoFixation(placeId);
        previewOrderPlaceGymnasiumNoFixation.setDownTime(List.of(previewOrderPlaceGymnasiumNoFixation.getDownTimes().split(",")));
        return previewOrderPlaceGymnasiumNoFixation;
    }

    @Resource
    private AppClassGroupingMapper appClassGroupingMapper;

    @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.setOrderType(appOrder.getOrderType());
        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<Evaluate> evaluateList =
                evaluateMapper.selectList(Wrappers.<Evaluate>lambdaQuery().eq(Evaluate::getOrderId, appOrder.getId()));
        if (CollUtil.isNotEmpty(evaluateList)) {
            appOrderInfoDTO.setOrEvaluate(1);
        } else {
            appOrderInfoDTO.setOrEvaluate(0);
        }

        //子订单
        List<AppOrderProInfo> proInfoList = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery().eq(AppOrderProInfo::getOrderId, orderId));
        List<AppOrderProInfoVO> appOrderProInfoVOList = new ArrayList<>();
        for (AppOrderProInfo appOrderProInfo : proInfoList) {
            AppOrderProInfoVO appOrderProInfoVO = new AppOrderProInfoVO();
            BeanUtil.copyProperties(appOrderProInfo, appOrderProInfoVO);
            //课程
            if (appOrderProInfo.getType().equals(CommonConstant.ORDER_PRO_INFO_TYPE_5)){
                //根据当前用户和课程获取班级名称
                ClassGroupingDTO classGroupingDTO = appClassGroupingMapper.queryByUserId(appOrderProInfo.getFamilyUserId(), appOrderProInfo.getProductId());
                //班级、教练名称
                if (ObjectUtil.isNotEmpty(classGroupingDTO)){
                    appOrderProInfoVO.setClassGroupingName(classGroupingDTO.getClassName()).setCoachName(classGroupingDTO.getCoachUserName());
                }
            }
            appOrderProInfoVOList.add(appOrderProInfoVO);
        }
        appOrderInfoDTO.setProInfoList(appOrderProInfoVOList);

        //学校
        if (appOrder.getType().equals(CommonConstant.ORDER_TYPE_0)) {
            if (appOrder.getOrderType() == 0) {
                //商品信息
                String productIds = appOrder.getProductIds();
                AppSitePriceRules appSitePriceRules = appSitePriceRulesMapper.selectAllById(productIds);
                if (ObjectUtil.isEmpty(appSitePriceRules)) {
                    log.info("当前学校场地预约商品已下架！{}", productIds);
                    throw new JeecgBootException("当前商品已下架！");
                }
                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.selectAllById(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.setRefundType(appSitePlace.getRefundType());
                appOrderInfoDTO.setEarlyRefundTime(appSitePlace.getEarlyRefundTime());
                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.selectAllById(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.setOrSubscribe(appSitePlace.getOrSubscribe());
                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.getType().equals(CommonConstant.ORDER_TYPE_1)) {
            //商品信息
            String productIds = appOrder.getProductIds();
            AppGame appGame = appGameMapper.findByPriceRules(productIds);
            //退改规则、
            appOrderInfoDTO.setReminder(appGame.getReminder());
            //开始时间
            appOrderInfoDTO.setGameStartTime(appGame.getStartTime());
            //结束时间
            appOrderInfoDTO.setGameEndTime(appGame.getEndTime());
            //赛程安排
            List<AppGameScheduleVO> appGameScheduleVOList = appGameScheduleMapper.getListVo(appGame.getId());
            appOrderInfoDTO.setAppGameScheduleVOList(appGameScheduleVOList);
            //赛程数
            appOrderInfoDTO.setGameScheduleNum(appGameScheduleVOList.size());
            AppSite site = appSiteMapper.selectById(appGame.getSiteId());
            //地址信息
            appOrderInfoDTO.setGameAddress(appGame.getAddress());
            appOrderInfoDTO.setLatitude(appGame.getLatitude());
            appOrderInfoDTO.setLongitude(appGame.getLongitude());
            if (appGame.getSiteType().equals(CommonConstant.STATUS_1_INT)) {
                if (ObjectUtils.isNotEmpty(site)) {
                    appOrderInfoDTO.setPhone(site.getPhone());
                    appOrderInfoDTO.setAddressSiteId(site.getId());
                }
            }
        }

        //课程
        if (appOrder.getType().equals(CommonConstant.ORDER_TYPE_2)) {
            //商品信息
            String productIds = appOrder.getProductIds();
            AppCourses appCourses = appCoursesMapper.selectAllById(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());
            appOrderInfoDTO.setStartTime(site.getStartTime());
            appOrderInfoDTO.setEndTime(site.getEndTime());
            //上课地点（经纬度）
            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);
        }
        if (null == appOrderInfoDTO.getGameAddress()) {
            appOrderInfoDTO.setGameAddress(appOrderInfoDTO.getProInfoList().get(0).getAddress());
        }
        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));

        if (null == proInfo) {
            return list;
        }

        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) {
        //订单类型；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 String orderQuery(String orderCode) {

        //查询订单
        AppOrder appOrder = appOrderMapper.selectOne(Wrappers.<AppOrder>lambdaQuery().eq(AppOrder::getOrderCode, orderCode).last("limit 1"));

        if (ObjectUtil.isEmpty(appOrder)) {
            throw new RuntimeException("当前订单不存在");
        }

        if (appOrder.getOrderOrFree() == 1) {
            return "100001";//支付成功
        }
        //查询订单子商户号
        String orgCode = appOrder.getOrgCode();
        SysDepart depart = sysDepartMapper.selectOne(Wrappers.lambdaQuery(SysDepart.class).eq(SysDepart::getOrgCode, orgCode).last("limit 1"));

        if (ObjectUtil.isEmpty(depart)) {
            throw new RuntimeException("当前商品所属商户不存在");
        }

        //null代表查询失败 SUCCESS-成功 USERPAYING和ACCEPT为中间态 其他为支付失败
        JSONObject res = weChatPayService.orderQueryByOutTradeNo(orderCode, depart.getMchId());
        String s = res == null ? null : res.getString("trade_state");
//        String s = "SUCCESS";
        if ("SUCCESS".equals(s) || appOrder.getOriginalPrice().compareTo(BigDecimal.ZERO) == 0) {
            ShopMoney shopMoney = shopMoneyMapper.selectOne(Wrappers.<ShopMoney>lambdaQuery()
                    .eq(ShopMoney::getOrgCode, appOrder.getOrgCode())
                    .last("limit 1")
                    .orderByDesc(ShopMoney::getCreateTime));
            if(null == shopMoney){
                shopMoney = new ShopMoney()
                        .setBeforeChange(BigDecimal.ZERO)
                        .setAfterChange(BigDecimal.ZERO);
            }
            shopMoneyMapper.insert(new ShopMoney()
                    .setOrgCode(appOrder.getOrgCode())
                    .setIncomeType(2)
                    .setMoneyType(2)
                    .setOrderCode(appOrder.getOrderCode())
                    .setBeforeChange(shopMoney.getAfterChange())
                    .setAfterChange(shopMoney.getAfterChange().add(appOrder.getPrice()))
                    .setMoneyChange(appOrder.getPrice())
                    .setChangeInfo(1)
                    .setCreateTime(new Date()));
            if (ObjectUtil.isNotEmpty(appOrder) && Objects.equals(appOrder.getOrderStatus(), CommonConstant.ORDER_STATUS_0)) {
                appOrder.setOrderStatus(1);
                appOrder.setPayTime(new Date());
                appOrder.setPayStatus(1);
                appOrder.setTransactionId(res.getString("transaction_id"));
                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);
                    }
                }
                if (appOrder.getOrProfitSharing() == 1) {
                    weChatPayService.addProfitSharingInfos(appOrder);
                }
            }
            if (ObjectUtil.isEmpty(appOrder.getTransactionId())) {
                appOrder.setTransactionId(res.getString("transaction_id"));
                appOrderMapper.updateById(appOrder);
            }
            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(4);
                    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.getPageNo(), 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<Evaluate> evaluateList = evaluateMapper.selectList(Wrappers.<Evaluate>lambdaQuery().eq(Evaluate::getOrderId, record.getOrderId()));
            if (CollUtil.isNotEmpty(evaluateList)) {
                record.setOrEvaluate(1);
            } else {
                record.setOrEvaluate(0);
            }

            if (record.getOrderType() == 1) {
                String appSiteRulesId = record.getProductIds().split(",")[0];
                AppSitePriceRules appSitePriceRules = appSitePriceRulesMapper.selectById(appSiteRulesId);
                if (ObjectUtil.isNotEmpty(appSitePriceRules)) {
                    AppSitePlace appSitePlace = appSitePlaceMapper.selectOne(Wrappers.<AppSitePlace>lambdaQuery()
                            .eq(AppSitePlace::getId, appSitePriceRules.getSitePlaceId()));
                    if (null != appSitePlace) {
                        record.setEarlyRefundTime(appSitePlace.getEarlyRefundTime());
                    } else {
                        record.setEarlyRefundTime(60);
                    }
                }
            }

            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());
                infoList.forEach(a -> {
                    if (null != record.getAddressSiteId()) {
                        a.setAddress(appSiteMapper.selectById(record.getAddressSiteId()).getName());
                    } else {
                        a.setAddress(sysDepartMapper.selectOne(Wrappers.<SysDepart>lambdaQuery()
                                .eq(SysDepart::getOrgCode, "A01").last("limit 1")).getDepartName());
                    }

                });
                record.setOrderProInfoList(infoList);
                record.setOrderInsureList(insureList);
            }
        });
        return pageOrders;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String refundOrder(RefundOrderForm refundOrderForm) throws ParseException {
        AppOrder appOrder = appOrderMapper.selectOne(Wrappers.<AppOrder>lambdaQuery().eq(AppOrder::getOrderCode, refundOrderForm.getOrderCode()).last("limit 1"));
        //退款金额
        BigDecimal refundAmount = BigDecimal.ZERO;
        List<String> refundOrderProInfoIds = new ArrayList<>(Arrays.asList(refundOrderForm.getOrderProInfoIds().split(",")));
        List<AppOrderProInfo> appOrderProInfoList = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(appOrder)) {
            if (appOrder.getProfitSharingStatus() > CommonConstant.NUMBER_0) {
                throw new JeecgBootException("当前订单无法进行退款,请联系客服处理！");
            }
            if (!Objects.equals(appOrder.getOrderType(), CommonConstant.ORDER_PRO_INFO_TYPE_1) && !appOrder.getOrderType().equals(CommonConstant.ORDER_PRO_INFO_TYPE_2) && !appOrder.getOrderType().equals(CommonConstant.ORDER_PRO_INFO_TYPE_5)) {
                throw new JeecgBootException("当前订单类型不支持退款！");
            }
            if (Objects.equals(appOrder.getOrderStatus(), CommonConstant.ORDER_STATUS_2)) {
                throw new JeecgBootException("订单商品已使用,无法进行退款！");
            }
//            if (Objects.equals(appOrder.getOrderType(), CommonConstant.ORDER_PRO_INFO_TYPE_5)) {
//                AppCourses appCourses = appCoursesMapper.selectById(appOrder.getProductIds());
//                Date startTime = appCourses.getStartTime();
//                Date now = new Date();
//                if(startTime.before(now)){
//                    log.info("当前课程已开始,判断是否已使用");
//                }
//            }
            if (Objects.equals(appOrder.getOrderType(), CommonConstant.ORDER_PRO_INFO_TYPE_1) || appOrder.getOrderType().equals(CommonConstant.ORDER_PRO_INFO_TYPE_2)){
                //通过订单查询门店退款规则，判断是否可以进行退款
                String s = appOrder.getProductIds().split(",")[0];
                String priceRuleId = s.split("\\|")[0];
                AppSitePriceRules appSitePriceRules =
                        appSitePriceRulesMapper.selectOne(Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getId, priceRuleId).last("limit 1"));
                String sitePlaceId = appSitePriceRules.getSitePlaceId();
                AppSitePlace appSitePlace = appSitePlaceMapper.selectById(sitePlaceId);
                if (Objects.equals(appOrder.getOrderType(), CommonConstant.ORDER_PRO_INFO_TYPE_2) && Objects.equals(appSitePlace.getRefundType(),
                        CommonConstant.NUMBER_2)) {
                    throw new JeecgBootException("当前门店不支持退款！");
                }
                if (Objects.equals(appSitePlace.getRefundType(), CommonConstant.NUMBER_1)) {

                    for (String refundOrderProInfoId : refundOrderProInfoIds) {
                        AppOrderProInfo appOrderProInfo = appOrderProInfoMapper.selectById(refundOrderProInfoId);
                        String productId = appOrderProInfo.getProductId();
                        AppSitePriceRules sitePriceRules = appSitePriceRulesMapper.selectById(productId);
                        if(ObjectUtil.isNotEmpty(sitePriceRules)){
                            if(Objects.equals(sitePriceRules.getType(), CommonConstant.ORDER_PRO_INFO_TYPE_1)){
                                String timeStr = appOrderProInfo.getProductName().split("-")[0] + "-" + appOrderProInfo.getProductName().split("-")[1];
                                int year = LocalDate.now().getYear();
                                Instant originalInstant = DateUtils.parseDate(year+"-"+timeStr, "yyyy-MM-dd HH:mm").toInstant();
                                Instant time = originalInstant.minusSeconds(appSitePlace.getEarlyRefundTime() * 60);
                                Instant now = Instant.now();
                                if (!now.isBefore(time)) {
                                    throw new JeecgBootException("商品:" + appOrderProInfo.getProductName() + " 已超过可退时间，无法进行退款！");
                                }
                            }
                        }
                    }
                }
            }

            //退款金额统计（不为保险的子订单）
            for (String refundOrderProInfoId : refundOrderProInfoIds) {
                AppOrderProInfo appOrderProInfo = appOrderProInfoMapper.selectById(refundOrderProInfoId);
                refundAmount = refundAmount.add(appOrderProInfo.getPrice());
                appOrderProInfoList.add(appOrderProInfo);
            }
        }
        //调用退款逻辑
        weChatPayService.refundOrder(appOrder, appOrderProInfoList, refundAmount, refundOrderForm.getReason(), refundOrderForm.getType());

        return "申请成功，预计在3个工作日内处理！";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String gameRefundOrder(String orderCode, String reason) {
        AppOrder appOrder = appOrderMapper.selectOne(Wrappers.<AppOrder>lambdaQuery().eq(AppOrder::getOrderCode, orderCode).last("limit 1"));

        //保险支付金额
        BigDecimal payAmount = BigDecimal.ZERO;
        //退款金额
        BigDecimal refundAmount = BigDecimal.ZERO;

        List<AppOrderProInfo> appOrderProInfoList = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery()
                .eq(AppOrderProInfo::getOrderId, appOrder.getId())
                .eq(AppOrderProInfo::getType, CommonConstant.ORDER_PRO_INFO_TYPE_6)
        );

        if (ObjectUtil.isNotEmpty(appOrder)) {
            if (appOrder.getProfitSharingStatus() > CommonConstant.NUMBER_0) {
                throw new JeecgBootException("当前订单无法进行退款,请联系客服处理！");
            }

            //不进行退款金额统计（保险的子订单）
            for (AppOrderProInfo appOrderProInfo : appOrderProInfoList) {
                payAmount = payAmount.add(appOrderProInfo.getPrice());
            }

            refundAmount = appOrder.getPrice().subtract(payAmount);
        }
        //调用退款逻辑
        weChatPayService.refundOrder(appOrder, null, refundAmount, reason, 2);

        return "申请成功，预计在3个工作日内处理！";
    }

    /**
     * 支付回调
     * @param request
     * @param response
     * @return
     */
    public Map<String, String> wechatPayNotify(HttpServletRequest request, HttpServletResponse response) {
        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;
                }
            }

        }
        return stringStringMap;
    }

    @Override
    public UserPayForm payOrder(String appOrderId) {
        UserPayForm payForm = new UserPayForm();
        AppOrder appOrder = appOrderMapper.selectById(appOrderId);
        if (ObjectUtil.isEmpty(appOrder)) {
            throw new JeecgBootException("当前订单不存在！");
        }
        if (!Objects.equals(appOrder.getOrderStatus(), CommonConstant.ORDER_STATUS_0)) {
            if (appOrder.getOrderStatus().equals(CommonConstant.ORDER_STATUS_1) || appOrder.getPayStatus().equals(CommonConstant.STATUS_1_INT)) {
                throw new JeecgBootException("当前订单已支付！");
            }
            if (appOrder.getOrderStatus().equals(CommonConstant.ORDER_STATUS_4)) {
                throw new JeecgBootException("当前订单已过期取消，请重新下单！");
            }
        }
        Map<String, String> payment = payment(appOrderId,appOrder.getUserOpenId());
        payForm.setOrderId(appOrderId)
                .setOrderCode(appOrder.getOrderCode())
                .setParams(payment)
        ;
        return payForm;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean cancelSchoolOrder(String orderId) {

        AppOrder appOrder = appOrderMapper.selectById(orderId);
        if (ObjectUtil.isEmpty(appOrder)) {
            throw new JeecgBootException("当前订单不存在！");
        }

        if (!Objects.equals(appOrder.getOrderType(), CommonConstant.ORDER_PRO_INFO_TYPE_0)){
            throw new JeecgBootException("只能主动取消学校场地预约订单！");
        }
        List<AppOrderProInfo> orderProInfoList = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery().eq(AppOrderProInfo::getOrderId, orderId));
        if (CollUtil.isNotEmpty(orderProInfoList)) {
            // 按productId分组统计需要恢复的库存数量（排除保险类型的子订单）
            Map<String, Long> productStockMap = orderProInfoList.stream()
                    .filter(info -> !Objects.equals(info.getType(), CommonConstant.ORDER_PRO_INFO_TYPE_6))
                    .collect(Collectors.groupingBy(AppOrderProInfo::getProductId, Collectors.counting()));

            // 恢复库存
            for (Map.Entry<String, Long> entry : productStockMap.entrySet()) {
                String productId = entry.getKey();
                int restoreCount = entry.getValue().intValue();

                // 恢复数据库库存
                AppSitePriceRules priceRules = appSitePriceRulesMapper.selectById(productId);
                if (ObjectUtil.isNotEmpty(priceRules)) {
                    int newTicketNum = (priceRules.getTicketNum() == null ? 0 : priceRules.getTicketNum()) + restoreCount;
                    appSitePriceRulesMapper.update(null, Wrappers.<AppSitePriceRules>lambdaUpdate()
                            .eq(AppSitePriceRules::getId, productId)
                            .set(AppSitePriceRules::getTicketNum, newTicketNum));
                    log.info("取消学校订单恢复库存，productId={}，恢复数量={}，恢复后库存={}", productId, restoreCount, newTicketNum);

                    // 恢复Redis缓存库存
                    String stockKey = "ORDER_TYPE_1_PRODUCT_STOCK_" + productId;
                    Integer cachedStock = (Integer) redisTemplate.opsForValue().get(stockKey);
                    if (cachedStock != null) {
                        redisTemplate.opsForValue().increment(stockKey, restoreCount);
                    }
                }
            }

            for (AppOrderProInfo appOrderProInfo : orderProInfoList) {
                appOrderProInfo.setOrderStatus(CommonConstant.ORDER_STATUS_4);
                appOrderProInfoMapper.updateById(appOrderProInfo);
            }
        }
        appOrder.setOrderStatus(CommonConstant.ORDER_STATUS_4);
        appOrderMapper.updateById(appOrder);
        return Boolean.TRUE;
    }


    /**
     * @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;
    }
}
