package shop.alien.store.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.geo.Point;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;
import shop.alien.entity.store.*;
import shop.alien.entity.store.dto.NearMeDto;
import shop.alien.entity.store.dto.StoreInfoDto;
import shop.alien.entity.store.excelVo.StoreInfoExcelVo;
import shop.alien.entity.store.excelVo.StoreInfoExpiredRecordsExcelVo;
import shop.alien.entity.store.excelVo.util.ExcelExporter;
import shop.alien.entity.store.excelVo.util.ExcelGenerator;
import shop.alien.entity.store.vo.*;
import shop.alien.entity.storePlatform.StoreLicenseHistory;
import shop.alien.entity.storePlatform.StoreOperationalActivity;
import shop.alien.mapper.*;
import shop.alien.mapper.storePlantform.StoreLicenseHistoryMapper;
import shop.alien.mapper.storePlantform.StoreOperationalActivityMapper;
import shop.alien.store.config.BaseRedisService;
import shop.alien.store.config.GaoDeMapUtil;
import shop.alien.store.config.WebSocketProcess;
import shop.alien.store.service.*;
import shop.alien.store.util.CommonConstant;
import shop.alien.store.util.FileUploadUtil;
import shop.alien.store.util.GroupConstant;
import shop.alien.store.util.LifeDynamicsIdentityHelper;
import shop.alien.store.util.LifeDynamicsIdentityHelper.PublisherScope;
import shop.alien.store.util.ai.AiAuthTokenUtil;
import shop.alien.util.ali.AliOSSUtil;
import shop.alien.util.common.DistanceUtil;
import shop.alien.util.common.JwtUtil;
import shop.alien.util.common.constant.CouponStatusEnum;
import shop.alien.util.common.constant.CouponTypeEnum;
import shop.alien.util.common.constant.OcrTypeEnum;
import shop.alien.util.common.constant.OrderStatusEnum;
import shop.alien.util.type.LifeCollectIdentityQuery;
import shop.alien.util.type.LifeFansIdentityQuery;
import shop.alien.util.type.LifeNoticeUtil;
import shop.alien.util.type.TypeUtil;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.SignStyle;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 二期-门店信息 服务实现类
 *
 * @author ssk
 * @since 2024-12-05
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional
public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo> implements StoreInfoService {

    private static final int DEFAULT_DISTANCE_METER = 1000;

    private final String DEFAULT_PASSWORD = "123456";

    private final StoreInfoMapper storeInfoMapper;

    private final StoreImgMapper storeImgMapper;

    private final StoreBusinessInfoMapper storeBusinessInfoMapper;

    private final StoreLabelMapper storeLabelMapper;

    private final StoreMenuMapper storeMenuMapper;

    private final StoreUserMapper storeUserMapper;

    private final FileUploadUtil fileUploadUtil;

    private final StoreDictionaryMapper storeDictionaryMapper;

    private final GaoDeMapUtil gaoDeMapUtil;

    private final BaseRedisService baseRedisService;

    private final TagStoreRelationMapper tagStoreRelationMapper;

    private final NearMeService nearMeService;

    private final WebAuditMapper webAuditMapper;

    private final EssentialCityCodeMapper essentialCityCodeMapper;

    private final LifeCouponMapper lifeCouponMapper;

    private final StoreEvaluationMapper storeEvaluationMapper;

    private final LifeUserOrderMapper lifeUserOrderMapper;

    private final LifeCollectMapper lifeCollectMapper;

    private final TypeUtil typeUtil;

    private final StoreStaffConfigMapper storeStaffConfigMapper;

    private final StoreClockInMapper storeClockInMapper;

    private final LifeUserDynamicsMapper lifeUserDynamicsMapper;

    private final LifeDynamicsIdentityHelper dynamicsIdentityHelper;

    private final StoreCommentMapper storeCommentMapper;

    private final CommonRatingMapper commonRatingMapper;

    private final StoreInfoDraftMapper storeInfoDraftMapper;

    private final LifeNoticeMapper lifeNoticeMapper;

    private final LifeNoticeUtil lifeNoticeUtil;

    private final LifeGroupBuyMainMapper lifeGroupBuyMainMapper;

    private final StoreClockInService storeClockInService;

    private final StoreCommentService storeCommentService;

    private final AliOSSUtil aliOSSUtil;

    private final WebSocketProcess webSocketProcess;

    private final LifeFansMapper lifeFansMapper;

    private final LifeBlacklistMapper lifeBlacklistMapper;

    private final OcrImageUploadMapper ocrImageUploadMapper;

    private final AiAuthTokenUtil aiAuthTokenUtil;

    private final RestTemplate restTemplate;

    private final StoreImgService storeImgService;

    private final StoreOfficialAlbumMapper storeOfficialAlbumMapper;

    /**
     * 运营活动数据访问对象
     */
    private final StoreOperationalActivityMapper storeOperationalActivityMapper;

    /**
     * 商户证照历史记录数据访问对象
     */
    private final StoreLicenseHistoryMapper licenseHistoryMapper;

    /**
     * 证照审核异步服务
     */
    private final LicenseAuditAsyncService licenseAuditAsyncService;

    private final CommonRatingService commonRatingService;

    @Resource
    private StoreIncomeDetailsRecordService storeIncomeDetailsRecordService;

    private final LifeUserViolationMapper lifeUserViolationMapper;

    private final EssentialHolidayComparisonMapper essentialHolidayComparisonMapper;

    private final StorePaymentConfigService storePaymentConfigService;
    private final PlatformShopMembershipService platformShopMembershipService;


    @Value("${spring.web.resources.excel-path}")
    private String excelPath;

    @Value("${spring.web.resources.excel-generate-path}")
    private String excelGeneratePath;

    @Value("${third-party-identification.base-url}")
    private String identificationPath;

    @Value("${third-party-applications.base-url}")
    private String applicationsPath;

    /**
     * 懒得查, 留着导出Excel
     */
    List<StoreInfoVo> toExcel = new ArrayList<>();
    private final LifeUserMapper lifeUserMapper;

    /**
     * 门店详情
     *
     * @return StoreMainInfoVo
     */
    @Override
    public StoreMainInfoVo getDetail(Integer id) {

        StoreInfo storeInfo = storeInfoMapper.selectById(id);
        if (storeInfo == null) {
            return null;
        }
        StoreMainInfoVo storeMainInfoVo = storeInfoMapper.getStoreInfo(id);

        //判断门店是否到期
        if (ObjectUtils.isNotEmpty(storeMainInfoVo.getExpirationTime())) {
            if (new Date().after(storeMainInfoVo.getExpirationTime())) {
                storeMainInfoVo.setExpirationFlag(0);
            } else {
                storeMainInfoVo.setExpirationFlag(1);
            }
        } else {
            storeMainInfoVo.setExpirationFlag(1);
        }

        //存入门店地址、
        storeMainInfoVo.setStoreAddress(storeInfo.getStoreAddress());
        //入口图
        LambdaQueryWrapper<StoreImg> inletsUrlQueryWrapper = new LambdaQueryWrapper<>();
        inletsUrlQueryWrapper.eq(StoreImg::getImgType, 1);
        inletsUrlQueryWrapper.eq(StoreImg::getStoreId, id);
        List<StoreImg> inletsUrlList = storeImgMapper.selectList(inletsUrlQueryWrapper);
        storeMainInfoVo.setInletsUrl(inletsUrlList.stream().sorted(Comparator.comparing(StoreImg::getImgSort)).map(StoreImg::getImgUrl).collect(Collectors.toList()));
        //相册
        LambdaQueryWrapper<StoreImg> albumUrlQueryWrapper = new LambdaQueryWrapper<>();
        albumUrlQueryWrapper.eq(StoreImg::getImgType, 2);
        albumUrlQueryWrapper.eq(StoreImg::getStoreId, id);
        List<StoreImg> albumUrlList = storeImgMapper.selectList(albumUrlQueryWrapper);
        storeMainInfoVo.setAlbumUrl(albumUrlList.stream().sorted(Comparator.comparing(StoreImg::getImgSort)).map(StoreImg::getImgUrl).collect(Collectors.toList()));
        //推荐菜
        storeMainInfoVo.setRecommendUrl(storeMenuMapper.getStoreMenuInfoList(id, 1, 1).stream().sorted(Comparator.comparing(StoreMenuVo::getImgSort)).collect(Collectors.toList()));
        //菜单
        storeMainInfoVo.setMenuUrl(storeMenuMapper.getStoreMenuInfoList(id, 0, 1).stream().sorted(Comparator.comparing(StoreMenuVo::getImgSort)).collect(Collectors.toList()));

        // todo 需要根据门店类型来判断
        // 推荐酒水
        storeMainInfoVo.setRecommendBeverageUrl(storeMenuMapper.getStoreMenuInfoList(id, 1, 1).stream().sorted(Comparator.comparing(StoreMenuVo::getImgSort)).collect(Collectors.toList()));
        //酒单
        storeMainInfoVo.setBeverageUrl(storeMenuMapper.getStoreMenuInfoList(id, 0, 1).stream().sorted(Comparator.comparing(StoreMenuVo::getImgSort)).collect(Collectors.toList()));

        //门店标签
        storeMainInfoVo.setStoreLabel(storeLabelMapper.selectOne(new LambdaQueryWrapper<StoreLabel>().eq(StoreLabel::getStoreId, id)));
        //营业时间（包含节假日信息，返回结构要和 storeBookingBusinessHours 一样）
        List<StoreBusinessInfoVo> storeBusinessInfoVos = this.getStoreInfoBusinessHours(id);
        storeMainInfoVo.setStoreBusinessInfo(storeBusinessInfoVos);
        //门店头像
        LambdaQueryWrapper<StoreImg> eq = new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 10).eq(StoreImg::getStoreId, id);
        StoreImg storeImg = storeImgMapper.selectOne(eq);
        storeMainInfoVo.setHeadImgUrl(storeImg != null ? storeImg.getImgUrl() : "");

        // 查询头图列表（包含is_extract字段）
        Integer imgMode = storeInfo.getImgMode();
        Integer headerImgType = null;
        if (imgMode != null && imgMode == 1) {
            // 多图模式
            headerImgType = GroupConstant.IMG_TYPE_MULTI_MODE;
        } else {
            // 单图模式（默认）
            headerImgType = GroupConstant.IMG_TYPE_SINGLE_MODE;
        }
        LambdaQueryWrapper<StoreImg> headerImgQueryWrapper = new LambdaQueryWrapper<>();
        headerImgQueryWrapper.eq(StoreImg::getImgType, headerImgType);
        headerImgQueryWrapper.eq(StoreImg::getStoreId, id);
        headerImgQueryWrapper.orderByAsc(StoreImg::getImgSort);
        List<StoreImg> headerImgList = storeImgMapper.selectList(headerImgQueryWrapper);
        storeMainInfoVo.setHeaderImgList(headerImgList);

        //门店头图（20:头图单图模式, 21:头图多图模式）
        LambdaQueryWrapper<StoreImg> headImgWrapper = new LambdaQueryWrapper<StoreImg>()
                .in(StoreImg::getImgType, 20, 21,22)
                .eq(StoreImg::getStoreId, id)
                .eq(StoreImg::getDeleteFlag, 0)
                .orderByAsc(StoreImg::getImgSort);
        List<StoreImg> headImgList = storeImgMapper.selectList(headImgWrapper);
        // 设置头图URL（取第一张图片，如果是多图模式可能有多个）
        if (headImgList != null && !headImgList.isEmpty()) {
            StoreImg firstHeadImg = headImgList.get(0);
            storeMainInfoVo.setHeadImgUrl(firstHeadImg.getImgUrl() != null ? firstHeadImg.getImgUrl() : "");
        } else {
            storeMainInfoVo.setHeadImgUrl("");
        }
        // 设置头图审核状态
        boolean hasHeadImg = false;
        if (headImgList != null && !headImgList.isEmpty()) {
            // 检查头图列表中是否有有效的图片地址
            for (StoreImg headImg : headImgList) {
                String imgUrl = headImg.getImgUrl();
                if (imgUrl != null && !imgUrl.trim().isEmpty()) {
                    hasHeadImg = true;
                    log.debug("门店头图数据检查，storeId={}, imgType={}, imgUrl={}, 判断为有头图", 
                            id, headImg.getImgType(), imgUrl);
                    break;
                }
            }
        }
        // 根据是否有头图数据确定审核状态：有数据返回1（审核通过），没有数据返回2（审核不通过）
        Integer headImgStatus = hasHeadImg ? 1 : 2;
        // 获取数据库中的head_img_status状态
        Integer headImgStatusFromDb = storeInfo.getHeadImgStatus();
        // 实时更新数据库：如果数据库中的状态与实际情况不一致，或者为null，则更新数据库
        if (headImgStatusFromDb == null || !headImgStatus.equals(headImgStatusFromDb)) {
            try {
                updateHeadImgStatus(id, headImgStatus);
                log.info("门店头图审核状态已实时更新，storeId={}, 原状态={}, 新状态={}", id, headImgStatusFromDb, headImgStatus);
            } catch (Exception e) {
                log.error("更新门店头图审核状态失败，storeId={}, error={}", id, e.getMessage(), e);
            }
        }
        // 设置返回的审核状态（以实际的头图数据为准）
        storeMainInfoVo.setHeadImgStatus(headImgStatus);
        List<StoreUser> storeUsers = storeUserMapper.selectList(new LambdaQueryWrapper<StoreUser>()
                .eq(StoreUser::getStoreId, storeInfo.getId())
                .eq(StoreUser::getDeleteFlag, 0));
        
        // 设置商家头像（优先取主账号头像，accountType=1）
        String storeUserHeadImg = null;
        for (StoreUser storeUser : storeUsers) {
            storeMainInfoVo.setLogoutFlagUser(storeUser.getLogoutFlag());
            // 优先取主账号头像
            if (storeUser.getAccountType() != null && storeUser.getAccountType() == 1 && storeUser.getHeadImg() != null) {
                storeUserHeadImg = storeUser.getHeadImg();
                break; // 找到主账号头像后直接退出
            } else if (storeUserHeadImg == null && storeUser.getHeadImg() != null) {
                // 如果没有主账号或主账号没有头像，则取第一个有头像的用户
                storeUserHeadImg = storeUser.getHeadImg();
            }
        }
        storeMainInfoVo.setStoreUserHeadImg(storeUserHeadImg);
        // 计算店铺到最近地铁站的距离
        JSONObject nearbySubway = gaoDeMapUtil.getNearbySubway(storeMainInfoVo.getStorePosition().split(",")[0], storeMainInfoVo.getStorePosition().split(",")[1]);
        // 地铁名
        String subWayName = nearbySubway.getString("name");
        storeMainInfoVo.setSubwayName(subWayName);
        // 地铁站经纬度
        String subWayJing = nearbySubway.getString("location") == null ? null : nearbySubway.getString("location").split(",")[0];
        String subWayWei = nearbySubway.getString("location") == null ? null : nearbySubway.getString("location").split(",")[1];
        if ((subWayJing != null && !subWayJing.isEmpty()) && (subWayWei != null && !subWayWei.isEmpty())) {
            double storeJing = Double.parseDouble(storeMainInfoVo.getStorePosition().split(",")[0]);
            double storeWei = Double.parseDouble(storeMainInfoVo.getStorePosition().split(",")[1]);
            double storeDistance2 = DistanceUtil.haversineCalculateDistance(Double.parseDouble(subWayJing), Double.parseDouble(subWayWei), storeJing, storeWei);
            storeMainInfoVo.setDistance2(storeDistance2);
        } else {
            storeMainInfoVo.setDistance2(0);
        }

        // 统计评价数量（common_rating 表，业务类型1=商铺评价）
        // 排除：1. 被删除的评论（delete_flag != 0）
        //       2. 审核状态为2（驳回）的评论（audit_status = 2）
        // 包含：审核状态为0（待审核）、1（通过）或null的评论
        LambdaQueryWrapper<CommonRating> ratingWrapper = new LambdaQueryWrapper<>();
        ratingWrapper.eq(CommonRating::getBusinessType, 1); // 业务类型：1-商铺评价
        ratingWrapper.eq(CommonRating::getBusinessId, id); // 门店ID
        ratingWrapper.eq(CommonRating::getDeleteFlag, 0); // 未删除
        // 只包含审核状态为0（待审核）、1（通过）或null的评论，排除审核状态为2（驳回）的评论
        ratingWrapper.and(wrapper -> wrapper.in(CommonRating::getAuditStatus, 0, 1)
                .or()
                .isNull(CommonRating::getAuditStatus));
        Integer ratingCountLong = commonRatingMapper.selectCount(ratingWrapper);
        storeMainInfoVo.setRatingCount(ratingCountLong != null ? ratingCountLong.intValue() : 0);
        storeMainInfoVo.setPlatformMembershipStatus(platformShopMembershipService.buildStatusVo(id));

        return storeMainInfoVo;
    }

    @Override
    public StoreMainInfoVo getDecorationDetail(Integer id) {
        StoreInfo storeInfo = storeInfoMapper.selectById(id);
        StoreMainInfoVo storeMainInfoVo = storeInfoMapper.getStoreInfo(id);

        if (storeInfo == null || storeMainInfoVo == null) {
            return null;
        }
        // 使用现代日期 API
        if (storeMainInfoVo.getExpirationTime() != null) {
            String expirationDate = storeMainInfoVo.getExpirationTime().toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate()
                    .format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            storeMainInfoVo.setExpirationDate(expirationDate);
        } else {
            storeMainInfoVo.setExpirationDate(null);
        }
        //审核通过给前台反显未提交
        if (storeMainInfoVo.getRenewContractStatus() == 1) {
            storeMainInfoVo.setRenewContractStatus(0);
        }
        // 处理注销状态：如果已超过7天，店铺应该已被定时任务删除，这里只处理7天内的倒计时
        if (storeMainInfoVo.getStoreStatus() == -1 && storeMainInfoVo.getLogoutTime() != null) {
            LocalDateTime localDateTime = storeMainInfoVo.getLogoutTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
            LocalDateTime future = localDateTime.plusDays(7);
            LocalDateTime now = LocalDateTime.now();
            Duration duration = Duration.between(now, future);
            long correct = duration.toMillis();
            // 如果倒计时已过期（小于0），说明已超过7天，店铺应该已被删除，不设置倒计时
            if (correct > 0) {
                storeMainInfoVo.setCountdown(correct);
            } else {
                // 超过7天，倒计时设为0，前端应该提示店铺已注销
                storeMainInfoVo.setCountdown(0);
            }
        }
        //存入门店地址
        storeMainInfoVo.setStoreAddress(storeInfo.getStoreAddress());
        // //经营种类
        // if (storeInfo.getBusinessTypes() != null) {
        //     String[] strings = storeInfo.getBusinessTypes().split(",");
        //     storeMainInfoVo.setBusinessTypesList(Arrays.stream(strings).collect(Collectors.toList()));
        // }
        //门店标签
        storeMainInfoVo.setStoreLabel(storeLabelMapper.selectOne(new LambdaQueryWrapper<StoreLabel>().eq(StoreLabel::getStoreId, id)));
        //营业时间（包含节假日信息，返回结构要和 storeBookingBusinessHours 一样）
        List<StoreBusinessInfoVo> storeBusinessInfoVos = this.getStoreInfoBusinessHours(id);
        storeMainInfoVo.setStoreBusinessInfo(storeBusinessInfoVos);
        //营业执照
        storeMainInfoVo.setBusinessLicenseList(storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 14).eq(StoreImg::getStoreId, id).eq(StoreImg::getDeleteFlag, 0)));
        //其他资质证明图片（img_type=35）
        storeMainInfoVo.setOtherQualificationImages(storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 35).eq(StoreImg::getStoreId, id).eq(StoreImg::getDeleteFlag, 0).orderByAsc(StoreImg::getImgSort)));
        // //合同照片
        // storeMainInfoVo.setContractList(storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 15).eq(StoreImg::getStoreId, id).eq(StoreImg::getDeleteFlag, 0)));
        // //经营许可证图片照片
        // storeMainInfoVo.setFoodLicenceList(storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 25).eq(StoreImg::getStoreId, id).eq(StoreImg::getDeleteFlag, 0)));
        //是否连锁
        String isChain = (storeInfo.getIsChain() == 0) ? "否" : "是";
        storeMainInfoVo.setIsChainStr(isChain);
        // //经营许可证到期时间
        // storeMainInfoVo.setFoodLicenceExpirationTime(storeInfo.getFoodLicenceExpirationTime());
        return storeMainInfoVo;
    }

    @Override
    public List<StoreBusinessInfoVo> getStoreInfoBusinessHours(Integer id) {
        // 查询营业时间（包含正常时间和特殊时间）
        List<StoreBusinessInfo> storeBusinessInfoList = storeBusinessInfoMapper.selectList(
                new LambdaQueryWrapper<StoreBusinessInfo>()
                        .eq(StoreBusinessInfo::getStoreId, id)
                        .eq(StoreBusinessInfo::getDeleteFlag, 0)
                        .orderByAsc(StoreBusinessInfo::getBusinessType) // 先按类型排序：1-正常时间，2-特殊时间
                        .orderByAsc(StoreBusinessInfo::getBusinessDate) // 再按日期排序
        );

        // 转换为 VO 并关联节假日信息
        // store_business_info 的 essential_id 关联 essential_holiday_comparison 的 id
        List<StoreBusinessInfoVo> resultList = new ArrayList<>();
        for (StoreBusinessInfo businessInfo : storeBusinessInfoList) {
            StoreBusinessInfoVo vo = new StoreBusinessInfoVo();
            // 复制基本信息
            BeanUtils.copyProperties(businessInfo, vo);

            // 如果有关联的节假日ID（essential_id），查询 essential_holiday_comparison 表的节假日信息
            if (businessInfo.getEssentialId() != null && !businessInfo.getEssentialId().trim().isEmpty()) {
                try {
                    Integer essentialId = Integer.parseInt(businessInfo.getEssentialId().trim());
                    EssentialHolidayComparison holiday = essentialHolidayComparisonMapper.selectById(essentialId);
                    if (holiday != null) {
                        vo.setHolidayInfo(holiday);
                    } else {
                        log.warn("门店营业时间关联的节假日信息不存在，storeId={}, essentialId={}", id, essentialId);
                    }
                } catch (NumberFormatException e) {
                    log.warn("门店营业时间关联的节假日ID格式错误，storeId={}, essentialId={}", id, businessInfo.getEssentialId());
                } catch (Exception e) {
                    log.error("查询节假日信息失败，storeId={}, essentialId={}", id, businessInfo.getEssentialId(), e);
                }
            }

            resultList.add(vo);
        }

        return resultList;
    }

    /**
     * 门店信息-修改后展示
     *
     * @param id 门店id
     * @return StoreMainInfoVo
     */
    @Override
    public StoreMainInfoVo getStoreInfo(Integer id) {
        StoreMainInfoVo storeMainInfoVo = storeInfoMapper.getStoreInfo(id);
        //门店标签
        storeMainInfoVo.setStoreLabel(storeLabelMapper.selectOne(new LambdaQueryWrapper<StoreLabel>().eq(StoreLabel::getStoreId, id)));
        //营业时间（包含节假日信息，返回结构要和 storeBookingBusinessHours 一样）
        List<StoreBusinessInfoVo> storeBusinessInfoVos = this.getStoreInfoBusinessHours(id);
        storeMainInfoVo.setStoreBusinessInfo(storeBusinessInfoVos);
        return storeMainInfoVo;
    }


    /**
     * web-分页查询店铺信息
     *
     * @param page         页码
     * @param size         页容
     * @param storeName    门店名称
     * @param storeContact 联系人
     * @param storePhone   门店电话
     * @param storeType    门店类型
     * @return IPage<StoreInfoVo>
     */
    @Override
    public IPage<StoreInfoVo> getStorePage(int page, int size, String storeName, String storeContact, String id, String storePhone, String storeType, String expiredState, String storeApplicationStatus, String storeStatus, String businessSection, String jingdu, String weidu, String renewContractStatus, String foodLicenceStatus, String foodLicenceWhetherExpiredStatus) {
        checkAndUpdateExpiredRecords();
        IPage<StoreInfoVo> iPage = new Page<>(page, size);
        QueryWrapper<StoreInfoVo> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(storeName != null && !storeName.isEmpty(), "a.store_name", storeName).like(storeContact != null && !storeContact.isEmpty(), "b.name", storeContact).like(storePhone != null && !storePhone.isEmpty(), "b.phone", storePhone).like(storeType != null && !storeType.isEmpty(), "a.store_type", storeType).eq(StringUtils.isNotEmpty(storeApplicationStatus), "a.store_application_status", storeApplicationStatus).eq(StringUtils.isNotEmpty(businessSection), "a.business_section", businessSection).eq(StringUtils.isNotEmpty(storeStatus), "a.store_status", storeStatus).eq(StringUtils.isNotEmpty(renewContractStatus), "a.renew_contract_status", renewContractStatus).eq(StringUtils.isNotEmpty(foodLicenceStatus), "a.food_licence_status", foodLicenceStatus).like(StringUtils.isNotEmpty(id), "a.id", id).eq("a.delete_flag", 0).eq("b.delete_flag", 0).orderByDesc("a.created_time");
        //如果查询未过期
        // 获取当前时刻
        Date currentDate = new Date();
        // 获取当前日期和时间
        Calendar calendar = Calendar.getInstance();
        // 将时间设置为 0 点
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        // 加上 30 天
        calendar.add(Calendar.DAY_OF_MONTH, 30);
        // 获取 Date 对象
        Date thirtyDaysAgo = calendar.getTime();
        if ("0".equals(expiredState)) {
            queryWrapper.ge("a.expiration_time", thirtyDaysAgo);
        } else if ("1".equals(expiredState)) {
            queryWrapper.lt("a.expiration_time", thirtyDaysAgo);
            queryWrapper.ge("a.expiration_time", currentDate);
        } else if ("2".equals(expiredState)) {
            queryWrapper.lt("a.expiration_time", currentDate);
        }
        // 获取当前时间
        LocalDate nowDay = LocalDate.now();
        //经营许可证到期状态筛选 0 查询食品经营许可证已到期
        if (CommonConstant.FOOD_LICENCE_EXPIRE_STATUS.equals(foodLicenceWhetherExpiredStatus)) {
            queryWrapper.lt("a.food_licence_expiration_time", nowDay);
        } else if (CommonConstant.FOOD_LICENCE_ABOUT_TO_EXPIRE_STATUS.equals(foodLicenceWhetherExpiredStatus)) {//经营许可证筛选状态 1 查询食品经营许可证即将到期 距离到期时间30天内
            queryWrapper.lt("a.food_licence_expiration_time", nowDay.plusDays(31))
                    .ge("a.food_licence_expiration_time", nowDay);
        } else if (CommonConstant.FOOD_LICENCE_NOT_EXPIRED_STATUS.equals(foodLicenceWhetherExpiredStatus)) {//经营许可证筛选状态 2 查询食品经营许可证未到期 距离到期时间大于30天以上
            queryWrapper.gt("a.food_licence_expiration_time", nowDay.plusDays(31));
        }
        //查出所有店铺
        IPage<StoreInfoVo> storeInfoVoPage = storeInfoMapper.getStoreInfoVoPage(iPage, queryWrapper);
        List<StoreInfoVo> records = storeInfoVoPage.getRecords();
        if (!records.isEmpty()) {
            // 提前查询所有需要的字典数据
            List<StoreInfoVo> collect = records.stream().filter(record -> StringUtils.isNotEmpty(record.getStoreType())).collect(Collectors.toList());
            Set<String> allTypes = collect.stream().map(StoreInfoVo::getStoreType).flatMap(type -> Arrays.stream(type.split(","))).collect(Collectors.toSet());

            List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(new LambdaQueryWrapper<StoreDictionary>().eq(StoreDictionary::getTypeName, "storeType").isNull(StoreDictionary::getParentId).in(!allTypes.isEmpty(), StoreDictionary::getDictId, allTypes));
            Map<String, String> typeMap = storeDictionaries.stream().collect(Collectors.toMap(StoreDictionary::getDictId, StoreDictionary::getDictDetail));

            Map<String, List<LifeCoupon>> quanListByStoreId = new HashMap<>();
            Map<Object, List<Map<String, Object>>> avgScoreMap = new HashMap<>();
            Map<Object, List<Map<String, Object>>> avgPriceMap = new HashMap<>();
            Map<Integer, List<StoreComment>> commentMap = new HashMap<>();
            // 如果获取美食列表进行以下前置操作
            if (StringUtils.isNotEmpty(businessSection) && businessSection.equals("1")) {
                List<Integer> storeIds = records.stream().map(StoreInfoVo::getId).collect(Collectors.toList());
                LambdaUpdateWrapper<LifeCoupon> quanWrapper = new LambdaUpdateWrapper<>();
                quanWrapper.in(LifeCoupon::getStoreId, storeIds).eq(LifeCoupon::getStatus, 1).orderByDesc(LifeCoupon::getCreatedTime);
                List<LifeCoupon> quanList = lifeCouponMapper.selectList(quanWrapper);
                quanListByStoreId = quanList.stream().collect(Collectors.groupingBy(LifeCoupon::getStoreId));
                // 获取全部店铺的评分与平均花销
                // TODO sotre_comment 没有花销 怎么算平均花销
                avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream().collect(Collectors.groupingBy(o -> o.get("store_id")));
                commentMap = storeCommentMapper.selectList(new QueryWrapper<StoreComment>().eq("business_type", "5").eq("delete_flag", 0)).stream().collect(Collectors.groupingBy(StoreComment::getStoreId));
                avgPriceMap = lifeUserOrderMapper.allStoreAvgPrice().stream().collect(Collectors.groupingBy(o -> o.get("store_id")));
            }
            for (StoreInfoVo record : records) {
                //处理类型
                if (StringUtils.isNotEmpty(record.getStoreType())) {
                    String[] types = record.getStoreType().split(",");
                    List<String> typeDetails = Arrays.stream(types).map(typeMap::get).filter(Objects::nonNull).collect(Collectors.toList());
                    record.setStoreTypeStr(String.join(",", typeDetails));
                    record.setStoreTypeList(Arrays.asList(types));
                }
                //写经纬度
                String[] split = record.getStorePosition().split(",");
                record.setStorePositionLongitude(split[0]);
                record.setStorePositionLatitude(split[1]);
                //处理一下到期状态
                Date expirationTime = record.getExpirationTime();
                if (expirationTime != null) {
                    // 获取当前时间
                    Calendar now = Calendar.getInstance();
                    Date nowCurrentDate = now.getTime();
                    // 计算 30 天后的时间
                    now.add(Calendar.DAY_OF_YEAR, 30);
                    Date thirtyDaysLater = now.getTime();
                    // 比较两个日期
                    if (expirationTime.after(currentDate)) {
                        record.setExpiredState("0");
                        if (expirationTime != null && (expirationTime.after(nowCurrentDate) || expirationTime.equals(nowCurrentDate)) && expirationTime.before(thirtyDaysLater)) {
                            record.setExpiredState("1");
                        }
                    } else {
                        record.setExpiredState("2");
                    }

                    // 获取当前时间
                    LocalDate nowLocal = LocalDate.now();
                    // 将 expirationTime 转换为 LocalDate
                    LocalDate expDate = expirationTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                    // 计算距离到期的天数
                    long daysToExpire = ChronoUnit.DAYS.between(nowLocal, expDate);
                    record.setDaysToExpire(daysToExpire);
                }
                // 处理经营许可证到期时间回显状态 根据经营许可证筛选状态筛选
                Date foodDate = record.getFoodLicenceExpirationTime();
                if (foodDate != null) {
                    // 获取当前时间
                    LocalDate nowLocal = LocalDate.now();
                    LocalDate localDate = foodDate.toInstant()  // Date -> Instant（UTC时间戳）
                            .atZone(ZoneId.systemDefault())  // Instant -> ZonedDateTime（系统默认时区）
                            .toLocalDate();
                    long remainingDays = ChronoUnit.DAYS.between(nowLocal, localDate);
                    if (remainingDays == -1) {
                        record.setFoodLicenceRemainingDays("0天");
                        record.setFoodLicenceExpireStatus("已到期");
                    } else if (remainingDays >= 0 && remainingDays <= 30) {
                        record.setFoodLicenceRemainingDays(remainingDays + "天");
                        record.setFoodLicenceExpireStatus("即将到期");
                    } else if (remainingDays > 30) {
                        record.setFoodLicenceRemainingDays(remainingDays + "天");
                        record.setFoodLicenceExpireStatus("未到期");
                    }
                }


                // 处理状态
                if (record.getLogoutFlag() == 1) {
                    record.setStoreStatusStr("已注销");
                    record.setStoreStatus(2);
                }
                // 根据八大类不同进行个性化操作
                if (StringUtils.isNotEmpty(businessSection)) {
                    switch (businessSection) {
                        case "1":
                            record.setAvgScore("0");
                            record.setAvgPrice("0");
                            record.setTotalNum("0");

                            if ((jingdu != null && !jingdu.isEmpty()) && (weidu != null && !weidu.isEmpty())) {
                                double storeJing = Double.parseDouble(split[0]);
                                double storeWei = Double.parseDouble(split[1]);
                                double storeDistance = DistanceUtil.haversineCalculateDistance(Double.parseDouble(jingdu), Double.parseDouble(weidu), storeJing, storeWei);
                                record.setDistance(storeDistance);
                            } else {
                                record.setDistance(0);
                            }

                            // 设置店铺得分，设置店铺人均消费，设置总评论数
                            if (avgScoreMap.containsKey(String.valueOf(record.getId()))) {
                                record.setAvgScore(String.valueOf(avgScoreMap.get(String.valueOf(record.getId())).get(0).get("avg_score")));
                                record.setAvgPrice(String.valueOf(avgPriceMap.get(String.valueOf(record.getId())).get(0).get("avg_price")));
                            }
                            // 设置店铺得分，设置店铺人均消费，设置总评论数
                            if (commentMap.containsKey(record.getId())) {
                                record.setTotalNum(String.valueOf(commentMap.get(record.getId()).size()));
                            }

                            // 设置店铺优惠券列表
                            if (!quanListByStoreId.isEmpty() && quanListByStoreId.containsKey(String.valueOf(record.getId()))) {
                                record.setQuanList(quanListByStoreId.get(String.valueOf(record.getId())));
                            }
                            break;
                    }
                }
            }
        }
        toExcel = storeInfoVoPage.getRecords();
        return storeInfoVoPage;
    }

    @Override
    public IPage<StoreInfoVo> getNewStorePage(int page, int size, String storeName, String storeContact, String id, String storePhone, String storeType, String expiredState, String storeApplicationStatus, String storeStatus, String businessSection, String jingdu, String weidu, String renewContractStatus, String foodLicenceStatus, String foodLicenceWhetherExpiredStatus, String startApplyTime, String endApplyTime) {
        checkAndUpdateExpiredRecords();
        IPage<StoreInfoVo> iPage = new Page<>(page, size);
        QueryWrapper<StoreInfoVo> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(storeName != null && !storeName.isEmpty(), "a.store_name", storeName).like(storeContact != null && !storeContact.isEmpty(), "b.name", storeContact).like(storePhone != null && !storePhone.isEmpty(), "b.phone", storePhone).like(storeType != null && !storeType.isEmpty(), "a.store_type", storeType).eq(StringUtils.isNotEmpty(storeApplicationStatus), "a.store_application_status", storeApplicationStatus).eq(StringUtils.isNotEmpty(businessSection), "a.business_section", businessSection).eq(StringUtils.isNotEmpty(storeStatus), "a.store_status", storeStatus).eq(StringUtils.isNotEmpty(renewContractStatus), "a.renew_contract_status", renewContractStatus).eq(StringUtils.isNotEmpty(foodLicenceStatus), "a.food_licence_status", foodLicenceStatus).like(StringUtils.isNotEmpty(id), "a.id", id).eq("a.delete_flag", 0).eq("b.delete_flag", 0).orderByDesc("a.created_time");
        if (StringUtils.isNotEmpty(startApplyTime) && StringUtils.isNotEmpty(endApplyTime)) {
            queryWrapper.between("a.created_time", startApplyTime,endApplyTime);
        }
        //如果查询未过期
        // 获取当前时刻
        Date currentDate = new Date();
        // 获取当前日期和时间
        Calendar calendar = Calendar.getInstance();
        // 将时间设置为 0 点
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        // 加上 30 天
        calendar.add(Calendar.DAY_OF_MONTH, 30);
        // 获取 Date 对象
        Date thirtyDaysAgo = calendar.getTime();
        if ("0".equals(expiredState)) {
            queryWrapper.ge("a.expiration_time", thirtyDaysAgo);
        } else if ("1".equals(expiredState)) {
            queryWrapper.lt("a.expiration_time", thirtyDaysAgo);
            queryWrapper.ge("a.expiration_time", currentDate);
        } else if ("2".equals(expiredState)) {
            queryWrapper.lt("a.expiration_time", currentDate);
        }
        // 获取当前时间
        LocalDate nowDay = LocalDate.now();
        //经营许可证到期状态筛选 0 查询食品经营许可证已到期
        if (CommonConstant.FOOD_LICENCE_EXPIRE_STATUS.equals(foodLicenceWhetherExpiredStatus)) {
            queryWrapper.lt("a.food_licence_expiration_time", nowDay);
        } else if (CommonConstant.FOOD_LICENCE_ABOUT_TO_EXPIRE_STATUS.equals(foodLicenceWhetherExpiredStatus)) {//经营许可证筛选状态 1 查询食品经营许可证即将到期 距离到期时间30天内
            queryWrapper.lt("a.food_licence_expiration_time", nowDay.plusDays(31))
                    .ge("a.food_licence_expiration_time", nowDay);
        } else if (CommonConstant.FOOD_LICENCE_NOT_EXPIRED_STATUS.equals(foodLicenceWhetherExpiredStatus)) {//经营许可证筛选状态 2 查询食品经营许可证未到期 距离到期时间大于30天以上
            queryWrapper.gt("a.food_licence_expiration_time", nowDay.plusDays(31));
        }
        //查出所有店铺
        IPage<StoreInfoVo> storeInfoVoPage = storeInfoMapper.getNewStoreInfoVoPage(iPage, queryWrapper);
        List<StoreInfoVo> records = storeInfoVoPage.getRecords();
        if (!records.isEmpty()) {
            // 提前查询所有需要的字典数据
            List<StoreInfoVo> collect = records.stream().filter(record -> StringUtils.isNotEmpty(record.getStoreType())).collect(Collectors.toList());
            Set<String> allTypes = collect.stream().map(StoreInfoVo::getStoreType).flatMap(type -> Arrays.stream(type.split(","))).collect(Collectors.toSet());

            List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(new LambdaQueryWrapper<StoreDictionary>().eq(StoreDictionary::getTypeName, "storeType").isNull(StoreDictionary::getParentId).in(!allTypes.isEmpty(), StoreDictionary::getDictId, allTypes));
            Map<String, String> typeMap = storeDictionaries.stream().collect(Collectors.toMap(StoreDictionary::getDictId, StoreDictionary::getDictDetail));

            Map<String, List<LifeCoupon>> quanListByStoreId = new HashMap<>();
            Map<Object, List<Map<String, Object>>> avgScoreMap = new HashMap<>();
            Map<Object, List<Map<String, Object>>> avgPriceMap = new HashMap<>();
            Map<Integer, List<StoreComment>> commentMap = new HashMap<>();
            // 如果获取美食列表进行以下前置操作
            if (StringUtils.isNotEmpty(businessSection) && businessSection.equals("1")) {
                List<Integer> storeIds = records.stream().map(StoreInfoVo::getId).collect(Collectors.toList());
                LambdaUpdateWrapper<LifeCoupon> quanWrapper = new LambdaUpdateWrapper<>();
                quanWrapper.in(LifeCoupon::getStoreId, storeIds).eq(LifeCoupon::getStatus, 1).orderByDesc(LifeCoupon::getCreatedTime);
                List<LifeCoupon> quanList = lifeCouponMapper.selectList(quanWrapper);
                quanListByStoreId = quanList.stream().collect(Collectors.groupingBy(LifeCoupon::getStoreId));
                // 获取全部店铺的评分与平均花销
                // TODO sotre_comment 没有花销 怎么算平均花销
                avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream().collect(Collectors.groupingBy(o -> o.get("store_id")));
                commentMap = storeCommentMapper.selectList(new QueryWrapper<StoreComment>().eq("business_type", "5").eq("delete_flag", 0)).stream().collect(Collectors.groupingBy(StoreComment::getStoreId));
                avgPriceMap = lifeUserOrderMapper.allStoreAvgPrice().stream().collect(Collectors.groupingBy(o -> o.get("store_id")));
            }
            for (StoreInfoVo record : records) {
                //处理类型
                if (StringUtils.isNotEmpty(record.getStoreType())) {
                    String[] types = record.getStoreType().split(",");
                    List<String> typeDetails = Arrays.stream(types).map(typeMap::get).filter(Objects::nonNull).collect(Collectors.toList());
                    record.setStoreTypeStr(String.join(",", typeDetails));
                    record.setStoreTypeList(Arrays.asList(types));
                }
                //写经纬度
                String[] split = record.getStorePosition().split(",");
                record.setStorePositionLongitude(split[0]);
                record.setStorePositionLatitude(split[1]);
                //处理一下到期状态
                Date expirationTime = record.getExpirationTime();
                if (expirationTime != null) {
                    // 获取当前时间
                    Calendar now = Calendar.getInstance();
                    Date nowCurrentDate = now.getTime();
                    // 计算 30 天后的时间
                    now.add(Calendar.DAY_OF_YEAR, 30);
                    Date thirtyDaysLater = now.getTime();
                    // 比较两个日期
                    if (expirationTime.after(currentDate)) {
                        record.setExpiredState("0");
                        if (expirationTime != null && (expirationTime.after(nowCurrentDate) || expirationTime.equals(nowCurrentDate)) && expirationTime.before(thirtyDaysLater)) {
                            record.setExpiredState("1");
                        }
                    } else {
                        record.setExpiredState("2");
                    }

                    // 获取当前时间
                    LocalDate nowLocal = LocalDate.now();
                    // 将 expirationTime 转换为 LocalDate
                    LocalDate expDate = expirationTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                    // 计算距离到期的天数
                    long daysToExpire = ChronoUnit.DAYS.between(nowLocal, expDate);
                    record.setDaysToExpire(daysToExpire);
                }
                // 处理经营许可证到期时间回显状态 根据经营许可证筛选状态筛选
                Date foodDate = record.getFoodLicenceExpirationTime();
                if (foodDate != null) {
                    // 获取当前时间
                    LocalDate nowLocal = LocalDate.now();
                    LocalDate localDate = foodDate.toInstant()  // Date -> Instant（UTC时间戳）
                            .atZone(ZoneId.systemDefault())  // Instant -> ZonedDateTime（系统默认时区）
                            .toLocalDate();
                    long remainingDays = ChronoUnit.DAYS.between(nowLocal, localDate);
                    if (remainingDays == -1) {
                        record.setFoodLicenceRemainingDays("0天");
                        record.setFoodLicenceExpireStatus("已到期");
                    } else if (remainingDays >= 0 && remainingDays <= 30) {
                        record.setFoodLicenceRemainingDays(remainingDays + "天");
                        record.setFoodLicenceExpireStatus("即将到期");
                    } else if (remainingDays > 30) {
                        record.setFoodLicenceRemainingDays(remainingDays + "天");
                        record.setFoodLicenceExpireStatus("未到期");
                    }
                }


                // 处理状态
                if (record.getLogoutFlag() == 1) {
                    record.setStoreStatusStr("已注销");
                    record.setStoreStatus(2);
                }
                // 根据八大类不同进行个性化操作
                if (StringUtils.isNotEmpty(businessSection)) {
                    switch (businessSection) {
                        case "1":
                            record.setAvgScore("0");
                            record.setAvgPrice("0");
                            record.setTotalNum("0");

                            if ((jingdu != null && !jingdu.isEmpty()) && (weidu != null && !weidu.isEmpty())) {
                                double storeJing = Double.parseDouble(split[0]);
                                double storeWei = Double.parseDouble(split[1]);
                                double storeDistance = DistanceUtil.haversineCalculateDistance(Double.parseDouble(jingdu), Double.parseDouble(weidu), storeJing, storeWei);
                                record.setDistance(storeDistance);
                            } else {
                                record.setDistance(0);
                            }

                            // 设置店铺得分，设置店铺人均消费，设置总评论数
                            if (avgScoreMap.containsKey(String.valueOf(record.getId()))) {
                                record.setAvgScore(String.valueOf(avgScoreMap.get(String.valueOf(record.getId())).get(0).get("avg_score")));
                                record.setAvgPrice(String.valueOf(avgPriceMap.get(String.valueOf(record.getId())).get(0).get("avg_price")));
                            }
                            // 设置店铺得分，设置店铺人均消费，设置总评论数
                            if (commentMap.containsKey(record.getId())) {
                                record.setTotalNum(String.valueOf(commentMap.get(record.getId()).size()));
                            }

                            // 设置店铺优惠券列表
                            if (!quanListByStoreId.isEmpty() && quanListByStoreId.containsKey(String.valueOf(record.getId()))) {
                                record.setQuanList(quanListByStoreId.get(String.valueOf(record.getId())));
                            }
                            break;
                    }
                }
            }
        }

        toExcel = storeInfoVoPage.getRecords();
        return storeInfoVoPage;
    }

    /**
     * 重置门店密码
     *
     * @param storeId 门店id
     * @return boolean
     */
    @Override
    public boolean resetPassword(String storeId) {
        QueryWrapper<StoreUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("store_id", storeId);
        StoreUser storeUser = new StoreUser();
        storeUser.setPassword("000000");
        return storeUserMapper.update(storeUser, queryWrapper) > 0;
    }

    /**
     * 修改门店状态
     *
     * @param storeId        门店id
     * @param businessStatus 营业状态
     * @return boolean
     */
    @Override
    public boolean setStoreState(String storeId, Integer businessStatus) {
        LambdaUpdateWrapper<StoreInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(StoreInfo::getId, storeId).set(StoreInfo::getBusinessStatus, businessStatus);
        return this.update(null, updateWrapper);
    }

    /**
     * web-新增店铺
     *
     * @param multipartRequest 文件请求
     * @param store            店铺信息
     * @return boolean
     */
    @Override
    public boolean saveStore(MultipartRequest multipartRequest, StoreInfo store) {
        try {
            String LonAndLat = gaoDeMapUtil.getLonAndLatByAddress(store.getStoreAddress());
            if (LonAndLat == null || LonAndLat.isEmpty()) {
                log.error("LifeStoreController.addOrUpdateStore ERROR 经纬度获取失败");
                return false;
            }
            store.setStorePosition(LonAndLat);
            if (org.apache.commons.lang3.StringUtils.isBlank(store.getCommissionRate())) {
                store.setCommissionRate("3");
            }
            this.save(store);
            Set<String> fileNameSet = multipartRequest.getMultiFileMap().keySet();
            if (!fileNameSet.isEmpty()) {
                for (int i = 0; i < fileNameSet.size(); i++) {
                    MultipartFile multipartFile = multipartRequest.getFileMap().get(i);
                    if (null != multipartFile) {
                        StoreImg storeImg = new StoreImg();
                        storeImg.setStoreId(store.getId());
                        storeImg.setImgType(12);
                        storeImg.setImgSort(i + 1);
                        storeImg.setImgUrl(fileUploadUtil.uploadOneFile(multipartFile));
                        storeImgMapper.insert(storeImg);
                    }
                }
            }
            return true;
        } catch (Exception e) {
            log.error("LifeStoreController.addOrUpdateStore ERROR Msg={}", e);
            return false;
        }
    }

    /**
     * 导出Excel
     *
     * @return ResponseEntity
     */
    @Override
    public ResponseEntity<byte[]> exportToExcel() {
        try {
            String[] headers = {"商家名称", "联系人", "联系电话", "经营种类", "创建时间", "状态"};
            byte[] excelData = ExcelExporter.exportToExcel(toExcel, headers, "商家列表清单");
            HttpHeaders responseHeaders = new HttpHeaders();
            responseHeaders.add("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode("商家列表清单.xlsx") + "\";charset=utf-8");
            responseHeaders.set("Charset", "UTF-8");
            return new ResponseEntity<>(excelData, responseHeaders, HttpStatus.OK);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public StoreInfoVo saveStoreInfo(StoreInfoDto storeInfoDto) {
        StoreInfoVo result = new StoreInfoVo();
        StoreInfo storeInfo = new StoreInfo();
        BeanUtils.copyProperties(storeInfoDto, storeInfo);
//        List<String> storeTypeList = storeInfoDto.getStoreTypeList();
//        String storeType = String.join(",", storeTypeList);
//        //存入营运类型
//        storeInfo.setStoreType(storeType);
        //存入门店状态
        storeInfo.setStoreStatus(storeInfoDto.getStoreStatus());
        //存入经纬度
        storeInfo.setStorePosition(storeInfoDto.getStorePositionLongitude() + "," + storeInfoDto.getStorePositionLatitude());
        //如果有门店密码，并且门店密码不为默认密码。则存入密码
        if (StringUtils.isNotEmpty(storeInfoDto.getStorePass()) && !DEFAULT_PASSWORD.equals(storeInfoDto.getStorePass())) {
            storeInfo.setStorePass(storeInfoDto.getStorePass());
            storeInfo.setPassType(1);
        } else {
            storeInfo.setStorePass(DEFAULT_PASSWORD);
            storeInfo.setPassType(0);
        }
        
        // 经营板块
        if (storeInfoDto.getBusinessSection() != null) {
            storeInfo.setBusinessSection(storeInfoDto.getBusinessSection());
        }
        if (StringUtils.isNotEmpty(storeInfoDto.getBusinessSectionName())) {
            storeInfo.setBusinessSectionName(storeInfoDto.getBusinessSectionName());
        }
        
        // 经营种类
        // if (!CollectionUtils.isEmpty(storeInfoDto.getBusinessTypes())) {
        //     storeInfo.setBusinessTypes(String.join(",", storeInfoDto.getBusinessTypes()));
        // }
        if (StringUtils.isNotEmpty(storeInfoDto.getBusinessTypeName())) {
            storeInfo.setBusinessTypeName(storeInfoDto.getBusinessTypeName());
        }
        
        // 经营类目
        if (StringUtils.isNotEmpty(storeInfoDto.getBusinessCategoryName())) {
            storeInfo.setBusinessCategoryName(storeInfoDto.getBusinessCategoryName());
        }
        
        // 店铺评价：直接使用传入的值
        if (StringUtils.isNotEmpty(storeInfoDto.getStoreEvaluate())) {
            storeInfo.setStoreEvaluate(storeInfoDto.getStoreEvaluate());
        }

        // 门店类型
        if (storeInfoDto.getStoreTickets() != null) {
            storeInfo.setStoreTickets(storeInfoDto.getStoreTickets());
        }
        
        // //处理分类信息（保留原有逻辑，如果还有使用的话）
        // List<String> businessClassify = storeInfoDto.getBusinessClassify();
        // if (!CollectionUtils.isEmpty(businessClassify)) {
        //     List<String> businessClassifyNames = new ArrayList<>();
        //     //批量查询分类名称
        //     List<StoreDictionary> classifyDicts = storeDictionaryMapper.selectList(
        //             new LambdaQueryWrapper<StoreDictionary>()
        //                     .in(StoreDictionary::getDictId, businessClassify)
        //                     .eq(StoreDictionary::getTypeName, "business_classify")
        //                     .eq(StoreDictionary::getDeleteFlag, 0)
        //     );
        //     //转为Map方便快速获取
        //     Map<String, StoreDictionary> classifyDictMap = classifyDicts.stream()
        //             .collect(Collectors.toMap(
        //                     dict -> dict.getDictId().toString(),
        //                     Function.identity(),
        //                     (existing, replacement) -> existing
        //             ));
        //     //提取分类名称
        //     for (String classifyId : businessClassify) {
        //         StoreDictionary dict = classifyDictMap.get(classifyId);
        //         if (Objects.nonNull(dict)) {
        //             businessClassifyNames.add(dict.getDictDetail());
        //         } else {
        //             log.warn("无效的分类id：" + classifyId);
        //         }
        //     }
        //     storeInfo.setBusinessClassify(String.join(",", businessClassify));
        //     storeInfo.setBusinessClassifyName(String.join(",", businessClassifyNames));
        // }

        //存入审批状态为待审批
        storeInfo.setStoreApplicationStatus(0);
        //处理一下行政区域信息
        if (StringUtils.isNotEmpty(storeInfo.getAdministrativeRegionProvinceAdcode())) {
            try {
                Integer provinceAdcode = Integer.parseInt(storeInfo.getAdministrativeRegionProvinceAdcode());
                EssentialCityCode essentialCityCode1 = essentialCityCodeMapper.selectOne(new LambdaQueryWrapper<EssentialCityCode>().eq(EssentialCityCode::getAreaCode, provinceAdcode));
                if (null != essentialCityCode1) {
                    storeInfo.setAdministrativeRegionProvinceName(essentialCityCode1.getAreaName());
                } else {
                    log.warn("未找到省份编码对应的地区信息：{}", storeInfo.getAdministrativeRegionProvinceAdcode());
                }
            } catch (NumberFormatException e) {
                log.error("省份编码格式错误：{}", storeInfo.getAdministrativeRegionProvinceAdcode(), e);
            }
        }
        if (StringUtils.isNotEmpty(storeInfo.getAdministrativeRegionCityAdcode())) {
            try {
                Integer cityAdcode = Integer.parseInt(storeInfo.getAdministrativeRegionCityAdcode());
                EssentialCityCode essentialCityCode2 = essentialCityCodeMapper.selectOne(new LambdaQueryWrapper<EssentialCityCode>().eq(EssentialCityCode::getAreaCode, cityAdcode));
                if (null != essentialCityCode2) {
                    storeInfo.setAdministrativeRegionCityName(essentialCityCode2.getAreaName());
                } else {
                    log.warn("未找到城市编码对应的地区信息：{}", storeInfo.getAdministrativeRegionCityAdcode());
                }
            } catch (NumberFormatException e) {
                log.error("城市编码格式错误：{}", storeInfo.getAdministrativeRegionCityAdcode(), e);
            }
        }
        if (StringUtils.isNotEmpty(storeInfo.getAdministrativeRegionDistrictAdcode())) {
            try {
                Integer districtAdcode = Integer.parseInt(storeInfo.getAdministrativeRegionDistrictAdcode());
                EssentialCityCode essentialCityCode3 = essentialCityCodeMapper.selectOne(new LambdaQueryWrapper<EssentialCityCode>().eq(EssentialCityCode::getAreaCode, districtAdcode));
                if (null != essentialCityCode3) {
                    storeInfo.setAdministrativeRegionDistrictName(essentialCityCode3.getAreaName());
                } else {
                    log.warn("未找到区县编码对应的地区信息：{}", storeInfo.getAdministrativeRegionDistrictAdcode());
                }
            } catch (NumberFormatException e) {
                log.error("区县编码格式错误：{}", storeInfo.getAdministrativeRegionDistrictAdcode(), e);
            }
        }
        if (null == storeInfo.getCommissionRate()) {
            storeInfo.setCommissionRate("3");
        }

        // // 处理食品经营许可证OCR数据
        // if (StringUtils.isNotEmpty(storeInfoDto.getFoodLicenceUrl())) {
        //     // 查询食品经营许可证OCR识别记录
        //     OcrImageUpload foodLicenceOcr = ocrImageUploadMapper.selectOne(
        //             new LambdaQueryWrapper<OcrImageUpload>()
        //                     .eq(OcrImageUpload::getImageUrl, storeInfoDto.getFoodLicenceUrl())
        //                     .eq(OcrImageUpload::getOcrType, OcrTypeEnum.FOOD_MANAGE_LICENSE.getCode())
        //                     .orderByDesc(OcrImageUpload::getCreateTime)
        //                     .last("limit 1")
        //     );
        //     if (foodLicenceOcr != null && StringUtils.isNotEmpty(foodLicenceOcr.getOcrResult())) {
        //         try {
        //             com.alibaba.fastjson2.JSONObject ocrResult = com.alibaba.fastjson2.JSONObject.parseObject(foodLicenceOcr.getOcrResult());
        //             // 食品经营许可证OCR字段：validToDate(优先)、standardizedValidToDate
        //             Date expirationTime = parseFoodLicenceExpirationDate(ocrResult);
        //             if (expirationTime != null) {
        //                 storeInfo.setFoodLicenceExpirationTime(expirationTime);
        //             } else if (storeInfoDto.getFoodLicenceExpirationTime() != null) {
        //                 // OCR解析结果为空时，使用DTO中传入的值
        //                 storeInfo.setFoodLicenceExpirationTime(storeInfoDto.getFoodLicenceExpirationTime());
        //                 log.info("使用DTO中的食品经营许可证到期时间：{}", storeInfoDto.getFoodLicenceExpirationTime());
        //             }
        //             // 设置食品经营许可证状态为"待审核"（字典值2）
        //             storeInfo.setFoodLicenceStatus(2);
        //             storeInfo.setUpdateFoodLicenceTime(new Date());
        //             log.info("食品经营许可证OCR数据解析成功，到期时间：{}", storeInfo.getFoodLicenceExpirationTime());
        //         } catch (Exception e) {
        //             log.error("解析食品经营许可证OCR数据失败", e);
        //             // 解析失败时使用DTO中传入的值
        //             if (storeInfoDto.getFoodLicenceExpirationTime() != null) {
        //                 storeInfo.setFoodLicenceExpirationTime(storeInfoDto.getFoodLicenceExpirationTime());
        //                 log.info("OCR解析失败，使用DTO中的食品经营许可证到期时间：{}", storeInfoDto.getFoodLicenceExpirationTime());
        //             }
        //             storeInfo.setFoodLicenceStatus(2);
        //             storeInfo.setUpdateFoodLicenceTime(new Date());
        //         }
        //     } else {
        //         // 没有OCR记录时，使用DTO中传入的值
        //         if (storeInfoDto.getFoodLicenceExpirationTime() != null) {
        //             storeInfo.setFoodLicenceExpirationTime(storeInfoDto.getFoodLicenceExpirationTime());
        //             log.info("无OCR记录，使用DTO中的食品经营许可证到期时间：{}", storeInfoDto.getFoodLicenceExpirationTime());
        //         }
        //         storeInfo.setFoodLicenceStatus(2);
        //         storeInfo.setUpdateFoodLicenceTime(new Date());
        //     }
        // } else {
        //     // 没有食品经营许可证URL，初始化状态为"未提交"（字典值0）
        //     storeInfo.setFoodLicenceStatus(0);
        //     if (storeInfoDto.getFoodLicenceExpirationTime() != null) {
        //         storeInfo.setFoodLicenceExpirationTime(storeInfoDto.getFoodLicenceExpirationTime());
        //         log.info("无食品经营许可证URL，使用DTO中的到期时间：{}", storeInfoDto.getFoodLicenceExpirationTime());
        //     }
        // }
        //
        // // 处理娱乐经营许可证OCR数据（复用营业执照OCR类型，数据库中ocr_type存的是BUSINESS_LICENSE）
        // if (StringUtils.isNotEmpty(storeInfoDto.getEntertainmentLicenceUrl())) {
        //     // 查询娱乐经营许可证OCR识别记录
        //     OcrImageUpload entertainmentLicenceOcr = ocrImageUploadMapper.selectOne(
        //             new LambdaQueryWrapper<OcrImageUpload>()
        //                     .eq(OcrImageUpload::getImageUrl, storeInfoDto.getEntertainmentLicenceUrl())
        //                     .eq(OcrImageUpload::getOcrType, OcrTypeEnum.BUSINESS_LICENSE.getCode())
        //                     .orderByDesc(OcrImageUpload::getCreateTime)
        //                     .last("limit 1")
        //     );
        //     if (entertainmentLicenceOcr != null && StringUtils.isNotEmpty(entertainmentLicenceOcr.getOcrResult())) {
        //         try {
        //             com.alibaba.fastjson2.JSONObject ocrResult = com.alibaba.fastjson2.JSONObject.parseObject(entertainmentLicenceOcr.getOcrResult());
        //             // 娱乐经营许可证OCR字段（复用营业执照类型）：validToDate(优先，格式"20220903")、validPeriod(格式"2020年09月04日至2022年09月03日")
        //             Date expirationTime = parseEntertainmentLicenceExpirationDate(ocrResult);
        //             if (expirationTime != null) {
        //                 storeInfo.setEntertainmentLicenceExpirationTime(expirationTime);
        //             } else if (storeInfoDto.getEntertainmentLicenceExpirationTime() != null) {
        //                 // OCR解析结果为空时，使用DTO中传入的值
        //                 storeInfo.setEntertainmentLicenceExpirationTime(storeInfoDto.getEntertainmentLicenceExpirationTime());
        //                 log.info("使用DTO中的娱乐经营许可证到期时间：{}", storeInfoDto.getEntertainmentLicenceExpirationTime());
        //             }
        //             // 设置娱乐经营许可证状态为"待审核"（字典值2）
        //             storeInfo.setEntertainmentLicenceStatus(2);
        //             storeInfo.setUpdateEntertainmentLicenceTime(new Date());
        //             log.info("娱乐经营许可证OCR数据解析成功，到期时间：{}", storeInfo.getEntertainmentLicenceExpirationTime());
        //         } catch (Exception e) {
        //             log.error("解析娱乐经营许可证OCR数据失败", e);
        //             // 解析失败时使用DTO中传入的值
        //             if (storeInfoDto.getEntertainmentLicenceExpirationTime() != null) {
        //                 storeInfo.setEntertainmentLicenceExpirationTime(storeInfoDto.getEntertainmentLicenceExpirationTime());
        //                 log.info("OCR解析失败，使用DTO中的娱乐经营许可证到期时间：{}", storeInfoDto.getEntertainmentLicenceExpirationTime());
        //             }
        //             storeInfo.setEntertainmentLicenceStatus(2);
        //             storeInfo.setUpdateEntertainmentLicenceTime(new Date());
        //         }
        //     } else {
        //         // 没有OCR记录时，使用DTO中传入的值
        //         if (storeInfoDto.getEntertainmentLicenceExpirationTime() != null) {
        //             storeInfo.setEntertainmentLicenceExpirationTime(storeInfoDto.getEntertainmentLicenceExpirationTime());
        //             log.info("无OCR记录，使用DTO中的娱乐经营许可证到期时间：{}", storeInfoDto.getEntertainmentLicenceExpirationTime());
        //         }
        //         storeInfo.setEntertainmentLicenceStatus(2);
        //         storeInfo.setUpdateEntertainmentLicenceTime(new Date());
        //     }
        // } else {
        //     // 没有娱乐经营许可证URL，初始化状态为"未提交"（字典值0）
        //     storeInfo.setEntertainmentLicenceStatus(0);
        //     if (storeInfoDto.getEntertainmentLicenceExpirationTime() != null) {
        //         storeInfo.setEntertainmentLicenceExpirationTime(storeInfoDto.getEntertainmentLicenceExpirationTime());
        //         log.info("无娱乐经营许可证URL，使用DTO中的到期时间：{}", storeInfoDto.getEntertainmentLicenceExpirationTime());
        //     }
        // }

        // 处理营业执照OCR数据（复用营业执照OCR类型，数据库中ocr_type存的是BUSINESS_LICENSE）
        // 营业执照使用 businessLicenseAddress 列表中的第一个URL查询OCR
        String businessLicenseOcrUrl = null;
        if (!CollectionUtils.isEmpty(storeInfoDto.getBusinessLicenseAddress())) {
            businessLicenseOcrUrl = storeInfoDto.getBusinessLicenseAddress().get(0);
        } else if (StringUtils.isNotEmpty(storeInfoDto.getBusinessLicenseUrl())) {
            businessLicenseOcrUrl = storeInfoDto.getBusinessLicenseUrl();
        }

        if (StringUtils.isNotEmpty(businessLicenseOcrUrl)) {
            // 查询营业执照OCR识别记录
            OcrImageUpload businessLicenseOcr = ocrImageUploadMapper.selectOne(
                    new LambdaQueryWrapper<OcrImageUpload>()
                            .eq(OcrImageUpload::getImageUrl, businessLicenseOcrUrl)
                            .eq(OcrImageUpload::getOcrType, OcrTypeEnum.BUSINESS_LICENSE.getCode())
                            .orderByDesc(OcrImageUpload::getCreateTime)
                            .last("limit 1")
            );
            if (businessLicenseOcr != null && StringUtils.isNotEmpty(businessLicenseOcr.getOcrResult())) {
                try {
                    com.alibaba.fastjson2.JSONObject ocrResult = com.alibaba.fastjson2.JSONObject.parseObject(businessLicenseOcr.getOcrResult());
                    // 营业执照OCR字段：validToDate(优先，格式"20241217")、validPeriod(格式"2020年09月04日至2022年09月03日")
                    Date expirationTime = parseBusinessLicenseExpirationDate(ocrResult);
                    if (expirationTime != null) {
                        storeInfo.setBusinessLicenseExpirationTime(expirationTime);
                    } else if (storeInfoDto.getBusinessLicenseExpirationTime() != null) {
                        // OCR解析结果为空时，使用DTO中传入的值
                        storeInfo.setBusinessLicenseExpirationTime(storeInfoDto.getBusinessLicenseExpirationTime());
                        log.info("使用DTO中的营业执照到期时间：{}", storeInfoDto.getBusinessLicenseExpirationTime());
                    }
                    // 设置营业执照状态为"待审核"（字典值2）
                    storeInfo.setBusinessLicenseStatus(2);
                    storeInfo.setUpdateBusinessLicenseTime(new Date());
                    log.info("营业执照OCR数据解析成功，到期时间：{}", storeInfo.getBusinessLicenseExpirationTime());
                } catch (Exception e) {
                    log.error("解析营业执照OCR数据失败", e);
                    // 解析失败时使用DTO中传入的值
                    if (storeInfoDto.getBusinessLicenseExpirationTime() != null) {
                        storeInfo.setBusinessLicenseExpirationTime(storeInfoDto.getBusinessLicenseExpirationTime());
                        log.info("OCR解析失败，使用DTO中的营业执照到期时间：{}", storeInfoDto.getBusinessLicenseExpirationTime());
                    }
                    storeInfo.setBusinessLicenseStatus(2);
                    storeInfo.setUpdateBusinessLicenseTime(new Date());
                }
            } else {
                // 没有OCR记录时，使用DTO中传入的值
                if (storeInfoDto.getBusinessLicenseExpirationTime() != null) {
                    storeInfo.setBusinessLicenseExpirationTime(storeInfoDto.getBusinessLicenseExpirationTime());
                    log.info("无OCR记录，使用DTO中的营业执照到期时间：{}", storeInfoDto.getBusinessLicenseExpirationTime());
                }
                storeInfo.setBusinessLicenseStatus(2);
                storeInfo.setUpdateBusinessLicenseTime(new Date());
            }
        } else {
            // 没有营业执照URL，初始化状态为"未提交"（字典值0）
            storeInfo.setBusinessLicenseStatus(0);
            if (storeInfoDto.getBusinessLicenseExpirationTime() != null) {
                storeInfo.setBusinessLicenseExpirationTime(storeInfoDto.getBusinessLicenseExpirationTime());
                log.info("无营业执照URL，使用DTO中的到期时间：{}", storeInfoDto.getBusinessLicenseExpirationTime());
            }
        }

        // 计算并设置到期时间为过期时间的最小值（仅包含营业执照过期时间）
        List<Date> expirationTimeList = new ArrayList<>();
        // 收集所有非空的过期时间
        if (storeInfoDto.getExpirationTime() != null) {
            expirationTimeList.add(storeInfoDto.getExpirationTime());
        }
        // 仅保留营业执照过期时间
        if (storeInfo.getBusinessLicenseExpirationTime() != null) {
            expirationTimeList.add(storeInfo.getBusinessLicenseExpirationTime());
        }
        // // 以下字段已废弃，不再使用
        // if (storeInfo.getFoodLicenceExpirationTime() != null) {
        //     expirationTimeList.add(storeInfo.getFoodLicenceExpirationTime());
        // }
        // if (storeInfo.getEntertainmentLicenceExpirationTime() != null) {
        //     expirationTimeList.add(storeInfo.getEntertainmentLicenceExpirationTime());
        // }
        // 取最小值设置为门店到期时间
        if (!expirationTimeList.isEmpty()) {
            Date minExpirationTime = Collections.min(expirationTimeList);
            storeInfo.setExpirationTime(minExpirationTime);
            log.info("设置门店到期时间为过期时间的最小值：{}", minExpirationTime);
        }

        storeInfoMapper.insert(storeInfo);
        result.setId(storeInfo.getId());
        // 新建默认固定相册：环境相册和视频相册
        // 创建环境相册
        StoreOfficialAlbum environmentAlbum = new StoreOfficialAlbum();
        environmentAlbum.setStoreId(storeInfo.getId());
        environmentAlbum.setAlbumName("环境");
        environmentAlbum.setImgCount(0);
        environmentAlbum.setIsFixed(1); // 1-固定相册
        //storeOfficialAlbumMapper.insert(environmentAlbum);
        // 创建视频相册
        StoreOfficialAlbum videoAlbum = new StoreOfficialAlbum();
        videoAlbum.setStoreId(storeInfo.getId());
        videoAlbum.setAlbumName("视频");
        videoAlbum.setImgCount(0);
        videoAlbum.setIsFixed(1); // 1-固定相册
        //storeOfficialAlbumMapper.insert(videoAlbum);
        if (StringUtils.isNotEmpty(storeInfoDto.getStorePositionLongitude()) && StringUtils.isNotEmpty(storeInfoDto.getStorePositionLatitude())) {
            nearMeService.inGeolocation(new Point(Double.parseDouble(storeInfoDto.getStorePositionLongitude()), Double.parseDouble(storeInfoDto.getStorePositionLatitude())), storeInfo.getId().toString(), Boolean.TRUE);
        }

        //修改门店店铺用户绑定关系
        String userAccount = storeInfoDto.getUserAccount();
        StoreUser storeUser = storeUserMapper.selectById(userAccount);
        storeUser.setStoreId(storeInfo.getId());
        if (StringUtils.isNotEmpty(storeInfoDto.getStoreContact())) {
            storeUser.setName(storeInfoDto.getStoreContact());
        }
        if (StringUtils.isNotEmpty(storeInfoDto.getIdCard())) {
            storeUser.setIdCard(storeInfoDto.getIdCard());
        }

        // 通过store_user_id查询支付配置并更新绑定store_id
        StorePaymentConfig paymentConfig = storePaymentConfigService.getByStoreUserId(storeUser.getId());
        if (paymentConfig != null) {
            paymentConfig.setStoreId(storeInfo.getId());
            storePaymentConfigService.updateById(paymentConfig);
        }

        storeUserMapper.updateById(storeUser);
        //存入店铺营业执照图片
        List<String> businessLicenseAddress = storeInfoDto.getBusinessLicenseAddress();
        for (String licenseAddress : businessLicenseAddress) {
            StoreImg storeImg = new StoreImg();
            storeImg.setStoreId(storeInfo.getId());
            storeImg.setImgType(14);
            storeImg.setImgSort(0);
            storeImg.setImgDescription("营业执照");
            storeImg.setImgUrl(licenseAddress);
            storeImgMapper.insert(storeImg);
        }
        
        //存入其他资质证明图片（限九张）
        if (!CollectionUtils.isEmpty(storeInfoDto.getOtherQualificationImages())) {
            List<String> otherQualificationImages = storeInfoDto.getOtherQualificationImages();
            // 限制最多9张
            int maxCount = Math.min(otherQualificationImages.size(), 9);
            for (int i = 0; i < maxCount; i++) {
                StoreImg storeImg = new StoreImg();
                storeImg.setStoreId(storeInfo.getId());
                storeImg.setImgType(35); // 其他资质证明图片
                storeImg.setImgSort(i + 1);
                storeImg.setImgDescription("其他资质证明");
                storeImg.setImgUrl(otherQualificationImages.get(i));
                storeImgMapper.insert(storeImg);
            }
        }
        
        // //存入店铺合同图片
        // if (!CollectionUtils.isEmpty(storeInfoDto.getContractImageList())) {
        //     List<String> contractImageList = storeInfoDto.getContractImageList();
        //     //先移除此前数据
        //     storeImgMapper.delete(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeInfo.getId()).eq(StoreImg::getImgType, 15));
        //     for (String licenseAddress : contractImageList) {
        //         StoreImg storeImg = new StoreImg();
        //         storeImg.setStoreId(storeInfo.getId());
        //         storeImg.setImgType(15);
        //         storeImg.setImgSort(0);
        //         storeImg.setImgDescription("合同图片");
        //         storeImg.setImgUrl(licenseAddress);
        //         storeImgMapper.insert(storeImg);
        //     }
        // }
        //
        // //存入店铺经营许可证图片
        // if (StringUtils.isNotEmpty(storeInfoDto.getFoodLicenceUrl())) {
        //     StoreImg storeImg = new StoreImg();
        //     storeImg.setStoreId(storeInfo.getId());
        //     storeImg.setImgType(25);
        //     storeImg.setImgSort(0);
        //     storeImg.setImgDescription("经营许可证审核通过图片");
        //     storeImg.setImgUrl(storeInfoDto.getFoodLicenceUrl());
        //     storeImgMapper.insert(storeImg);
        // }
        // //存入店铺娱乐经营许可证图片
        // if (StringUtils.isNotEmpty(storeInfoDto.getEntertainmentLicenceUrl())) {
        //     StoreImg storeImg = new StoreImg();
        //     storeImg.setStoreId(storeInfo.getId());
        //     storeImg.setImgType(26);
        //     storeImg.setImgSort(0);
        //     storeImg.setImgDescription("娱乐经营许可证审核通过图片");
        //     storeImg.setImgUrl(storeInfoDto.getEntertainmentLicenceUrl());
        //     storeImgMapper.insert(storeImg);
        // }
        //
        // //存入身份证正反面图片
        // saveIdCardImages(storeInfo.getId(), storeUser.getId().toString(), storeInfo);
        //
        // // 更新门店到期时间，包含身份证过期时间
        // if (storeInfo.getIdCardExpirationTime() != null) {
        //     List<Date> allExpirationTimeList = new ArrayList<>();
        //     if (storeInfo.getExpirationTime() != null) {
        //         allExpirationTimeList.add(storeInfo.getExpirationTime());
        //     }
        //     allExpirationTimeList.add(storeInfo.getIdCardExpirationTime());
        //     Date minExpirationTime = Collections.min(allExpirationTimeList);
        //     storeInfo.setExpirationTime(minExpirationTime);
        //     // 更新数据库中的过期时间
        //     storeInfoMapper.updateById(storeInfo);
        //     log.info("更新门店到期时间，包含身份证过期时间，最小值：{}", minExpirationTime);
        // }

        //初始化标签数据
        LambdaQueryWrapper<TagStoreRelation> tagStoreRelationLambdaQueryWrapper = new LambdaQueryWrapper<>();
        tagStoreRelationLambdaQueryWrapper.eq(TagStoreRelation::getStoreId, storeInfo.getId());
        tagStoreRelationLambdaQueryWrapper.eq(TagStoreRelation::getDeleteFlag, 0);
        int tagStoreCount = tagStoreRelationMapper.selectCount(tagStoreRelationLambdaQueryWrapper);
        if (tagStoreCount == 0) {
            TagStoreRelation tagStoreRelation = new TagStoreRelation();
            tagStoreRelation.setStoreId(storeInfo.getId());
            tagStoreRelation.setDeleteFlag(0);
            tagStoreRelationMapper.insert(tagStoreRelation);
        }

        // 保存门店营业时间
        if (storeInfoDto.getStoreBusinessTime() != null && !storeInfoDto.getStoreBusinessTime().isEmpty()) {
            List<StoreBusinessInfo> storeBusinessTimeList = storeInfoDto.getStoreBusinessTime();
            for (StoreBusinessInfo businessInfo : storeBusinessTimeList) {
                // 设置门店ID
                businessInfo.setStoreId(storeInfo.getId());
                // 新增门店时，所有营业时间都是新增，清空ID确保是新增
                businessInfo.setId(null);
            }
            // 批量保存营业时间
            for (StoreBusinessInfo businessInfo : storeBusinessTimeList) {
                storeBusinessInfoMapper.insert(businessInfo);
            }
            log.info("保存门店营业时间成功，门店ID：{}，营业时间数量：{}", storeInfo.getId(), storeBusinessTimeList.size());
        }

        // 发送通知
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String commonDate = simpleDateFormat.format(new Date());
        String text = "您在" + commonDate + "提交的入驻店铺申请，平台已受理，1-3个工作日将审核结果发送至应用内的消息-通知中，请注意查收。";
        com.alibaba.fastjson2.JSONObject jsonObject = new com.alibaba.fastjson2.JSONObject();
        jsonObject.put("message", text);
        LifeNotice lifeMessage = new LifeNotice();
        lifeMessage.setReceiverId("store_" + storeUser.getPhone());
        lifeMessage.setContext(jsonObject.toJSONString());
        lifeMessage.setTitle("入驻店铺申请");
        lifeMessage.setSenderId("system");
        lifeMessage.setIsRead(0);
        lifeMessage.setNoticeType(1);
        lifeNoticeUtil.fillUserTypeAndRefId(lifeMessage);
        lifeNoticeMapper.insert(lifeMessage);

        WebSocketVo websocketVo = new WebSocketVo();
        websocketVo.setSenderId("system");
        websocketVo.setReceiverId("store_" + storeUser.getPhone());
        websocketVo.setCategory("notice");
        websocketVo.setNoticeType("1");
        websocketVo.setIsRead(0);
        websocketVo.setText(com.alibaba.fastjson2.JSONObject.from(lifeMessage).toJSONString());
        try {
            webSocketProcess.sendMessage("store_" + storeUser.getPhone(), com.alibaba.fastjson2.JSONObject.from(websocketVo).toJSONString());
        } catch (Exception e) {
            log.error("StoreInfoServiceImpl webSocketProcess Stack={}", e);
        }

        return result;
    }

    @Override
    public int saveStoreInfoDraft(StoreInfoDraft storeInfoDraft) {
        //处理一下行政区域信息
        if (StringUtils.isNotEmpty(storeInfoDraft.getAdministrativeRegionProvinceAdcode())) {
            try {
                Integer provinceAdcode = Integer.parseInt(storeInfoDraft.getAdministrativeRegionProvinceAdcode());
                EssentialCityCode essentialCityCode1 = essentialCityCodeMapper.selectOne(new LambdaQueryWrapper<EssentialCityCode>().eq(EssentialCityCode::getAreaCode, provinceAdcode));
                if (null != essentialCityCode1) {
                    storeInfoDraft.setAdministrativeRegionProvinceName(essentialCityCode1.getAreaName());
                } else {
                    log.warn("未找到省份编码对应的地区信息：{}", storeInfoDraft.getAdministrativeRegionProvinceAdcode());
                }
            } catch (NumberFormatException e) {
                log.error("省份编码格式错误：{}", storeInfoDraft.getAdministrativeRegionProvinceAdcode(), e);
            }
        }
        if (StringUtils.isNotEmpty(storeInfoDraft.getAdministrativeRegionCityAdcode())) {
            try {
                Integer cityAdcode = Integer.parseInt(storeInfoDraft.getAdministrativeRegionCityAdcode());
                EssentialCityCode essentialCityCode2 = essentialCityCodeMapper.selectOne(new LambdaQueryWrapper<EssentialCityCode>().eq(EssentialCityCode::getAreaCode, cityAdcode));
                if (null != essentialCityCode2) {
                    storeInfoDraft.setAdministrativeRegionCityName(essentialCityCode2.getAreaName());
                } else {
                    log.warn("未找到城市编码对应的地区信息：{}", storeInfoDraft.getAdministrativeRegionCityAdcode());
                }
            } catch (NumberFormatException e) {
                log.error("城市编码格式错误：{}", storeInfoDraft.getAdministrativeRegionCityAdcode(), e);
            }
        }
        if (StringUtils.isNotEmpty(storeInfoDraft.getAdministrativeRegionDistrictAdcode())) {
            try {
                Integer districtAdcode = Integer.parseInt(storeInfoDraft.getAdministrativeRegionDistrictAdcode());
                EssentialCityCode essentialCityCode3 = essentialCityCodeMapper.selectOne(new LambdaQueryWrapper<EssentialCityCode>().eq(EssentialCityCode::getAreaCode, districtAdcode));
                if (null != essentialCityCode3) {
                    storeInfoDraft.setAdministrativeRegionDistrictName(essentialCityCode3.getAreaName());
                } else {
                    log.warn("未找到区县编码对应的地区信息：{}", storeInfoDraft.getAdministrativeRegionDistrictAdcode());
                }
            } catch (NumberFormatException e) {
                log.error("区县编码格式错误：{}", storeInfoDraft.getAdministrativeRegionDistrictAdcode(), e);
            }
        }
        if (StringUtils.isEmpty(storeInfoDraft.getBusinessLicenseUrl())) {
            storeInfoDraft.setBusinessLicenseUrl(null);
        }
        // if (StringUtils.isEmpty(storeInfoDraft.getContractUrl())) {
        //     storeInfoDraft.setContractUrl(null);
        // }
        // if (StringUtils.isEmpty(storeInfoDraft.getFoodLicenceUrl())) {
        //     storeInfoDraft.setFoodLicenceUrl(null);
        // }
        
        // 处理其他资质证明图片列表（最多9张），转换为逗号分隔的字符串
        if (!CollectionUtils.isEmpty(storeInfoDraft.getOtherQualificationImages())) {
            List<String> otherQualificationImages = storeInfoDraft.getOtherQualificationImages();
            // 限制最多9张
            int maxCount = Math.min(otherQualificationImages.size(), 9);
            List<String> limitedImages = otherQualificationImages.subList(0, maxCount);
            String otherLicensesStr = String.join(",", limitedImages);
            storeInfoDraft.setOtherLicenses(otherLicensesStr);
        } else if (storeInfoDraft.getOtherQualificationImages() != null) {
            // 如果传入空列表，清空 otherLicenses
            storeInfoDraft.setOtherLicenses(null);
        }
        
        return storeInfoDraftMapper.insert(storeInfoDraft);
    }

    @Override
    public StoreInfoDraft selectDraftByUserId(int storeUserId) {
        LambdaQueryWrapper<StoreInfoDraft> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreInfoDraft::getStoreUserId, storeUserId);
        wrapper.orderByDesc(StoreInfoDraft::getCreatedTime);
        List<StoreInfoDraft> list = storeInfoDraftMapper.selectList(wrapper);
        StoreInfoDraft draft = CollectionUtils.isEmpty(list) ? null : list.get(0);
        
        // 将 otherLicenses 字段（逗号分隔的字符串）转换为 otherQualificationImages 列表
        if (draft != null && StringUtils.isNotEmpty(draft.getOtherLicenses())) {
            String[] urls = draft.getOtherLicenses().split(",");
            List<String> otherQualificationImages = new ArrayList<>();
            for (String url : urls) {
                if (StringUtils.isNotEmpty(url.trim())) {
                    otherQualificationImages.add(url.trim());
                }
            }
            draft.setOtherQualificationImages(otherQualificationImages);
        } else if (draft != null) {
            // 如果 otherLicenses 为空，设置空列表
            draft.setOtherQualificationImages(new ArrayList<>());
        }
        
        return draft;
    }

    @Override
    public StoreInfoVo editStoreInfo(StoreInfoDto storeInfoDto) {

        //判断是否修改变更过的用户账户
        String userAccountId = storeInfoDto.getUserAccount();
        Integer id = storeInfoDto.getId();
        StoreUser storeUserEntity = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, id));
        //如果更换了用户，则原有用户绑定门店删除
        if (!userAccountId.equals(storeUserEntity.getId().toString())) {
            LambdaUpdateWrapper<StoreUser> storeUserLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            storeUserLambdaUpdateWrapper.set(StoreUser::getStoreId, null).eq(StoreUser::getId, storeUserEntity.getId());
            storeUserMapper.update(null, storeUserLambdaUpdateWrapper);
        }
        //获取经营板块id
        Integer businessSection = storeInfoDto.getBusinessSection();
        //查询经营板块名称
        StoreDictionary businessSectionName = storeDictionaryMapper.selectOne(new LambdaQueryWrapper<StoreDictionary>().eq(StoreDictionary::getDictId, businessSection).eq(StoreDictionary::getTypeName, "business_section"));
        //查询经营种类
        List<String> businessTypes = storeInfoDto.getBusinessTypes();
        List<String> businessTypeNames = new ArrayList<>();
        //获取经营种类名称
        for (String businessType : businessTypes) {
            StoreDictionary storeDictionary = storeDictionaryMapper.selectOne(new LambdaQueryWrapper<StoreDictionary>()
                    .eq(StoreDictionary::getDictId, businessType)
                    .eq(StoreDictionary::getParentId, businessSectionName.getId())
                    .eq(StoreDictionary::getTypeName, "business_type")
                    .eq(StoreDictionary::getDeleteFlag, 0));
            if (storeDictionary != null) {
                businessTypeNames.add(storeDictionary.getDictDetail());
            }
        }

        StoreInfoVo result = new StoreInfoVo();
        StoreInfo storeInfo = new StoreInfo();
        BeanUtils.copyProperties(storeInfoDto, storeInfo);
//        List<String> storeTypeList = storeInfoDto.getStoreTypeList();
//        String storeType = String.join(",", storeTypeList);
        //存入营运类型
//        storeInfo.setStoreType(storeType);
        //存入门店状态
        storeInfo.setStoreStatus(storeInfoDto.getStoreStatus());
        //存入经纬度
        storeInfo.setStorePosition(storeInfoDto.getStorePositionLongitude() + "," + storeInfoDto.getStorePositionLatitude());
        //如果有门店密码，并且门店密码不为默认密码。则存入密码
        if (StringUtils.isNotEmpty(storeInfoDto.getStorePass()) && !DEFAULT_PASSWORD.equals(storeInfoDto.getStorePass())) {
            storeInfo.setStorePass(storeInfoDto.getStorePass());
            storeInfo.setPassType(1);
        } else {
            storeInfo.setStorePass(DEFAULT_PASSWORD);
            storeInfo.setPassType(0);
        }
        //板块及类型
        storeInfo.setBusinessSection(businessSection);
        storeInfo.setBusinessSectionName(businessSectionName.getDictDetail());
        storeInfo.setBusinessTypes(String.join(",", businessTypes));
        storeInfo.setBusinessTypesName(String.join(",", businessTypeNames));
        
        //处理分类信息
        List<String> businessClassify = storeInfoDto.getBusinessClassify();
        if (!CollectionUtils.isEmpty(businessClassify)) {
            List<String> businessClassifyNames = new ArrayList<>();
            //批量查询分类名称
            List<StoreDictionary> classifyDicts = storeDictionaryMapper.selectList(
                    new LambdaQueryWrapper<StoreDictionary>()
                            .in(StoreDictionary::getDictId, businessClassify)
                            .eq(StoreDictionary::getTypeName, "business_classify")
                            .eq(StoreDictionary::getDeleteFlag, 0)
            );
            //转为Map方便快速获取
            Map<String, StoreDictionary> classifyDictMap = classifyDicts.stream()
                    .collect(Collectors.toMap(
                            dict -> dict.getDictId().toString(),
                            Function.identity(),
                            (existing, replacement) -> existing
                    ));
            //提取分类名称
            for (String classifyId : businessClassify) {
                StoreDictionary dict = classifyDictMap.get(classifyId);
                if (Objects.nonNull(dict)) {
                    businessClassifyNames.add(dict.getDictDetail());
                } else {
                    log.warn("无效的分类id：" + classifyId);
                }
            }
            storeInfo.setBusinessClassify(String.join(",", businessClassify));
            storeInfo.setBusinessClassifyName(String.join(",", businessClassifyNames));
        }
        
        //处理一下行政区域信息
        if (StringUtils.isNotEmpty(storeInfo.getAdministrativeRegionProvinceAdcode())) {
            try {
                Integer provinceAdcode = Integer.parseInt(storeInfo.getAdministrativeRegionProvinceAdcode());
                EssentialCityCode essentialCityCode1 = essentialCityCodeMapper.selectOne(new LambdaQueryWrapper<EssentialCityCode>().eq(EssentialCityCode::getAreaCode, provinceAdcode));
                if (null != essentialCityCode1) {
                    storeInfo.setAdministrativeRegionProvinceName(essentialCityCode1.getAreaName());
                } else {
                    log.warn("未找到省份编码对应的地区信息：{}", storeInfo.getAdministrativeRegionProvinceAdcode());
                }
            } catch (NumberFormatException e) {
                log.error("省份编码格式错误：{}", storeInfo.getAdministrativeRegionProvinceAdcode(), e);
            }
        }
        if (StringUtils.isNotEmpty(storeInfo.getAdministrativeRegionCityAdcode())) {
            try {
                Integer cityAdcode = Integer.parseInt(storeInfo.getAdministrativeRegionCityAdcode());
                EssentialCityCode essentialCityCode2 = essentialCityCodeMapper.selectOne(new LambdaQueryWrapper<EssentialCityCode>().eq(EssentialCityCode::getAreaCode, cityAdcode));
                if (null != essentialCityCode2) {
                    storeInfo.setAdministrativeRegionCityName(essentialCityCode2.getAreaName());
                } else {
                    log.warn("未找到城市编码对应的地区信息：{}", storeInfo.getAdministrativeRegionCityAdcode());
                }
            } catch (NumberFormatException e) {
                log.error("城市编码格式错误：{}", storeInfo.getAdministrativeRegionCityAdcode(), e);
            }
        }
        if (StringUtils.isNotEmpty(storeInfo.getAdministrativeRegionDistrictAdcode())) {
            try {
                Integer districtAdcode = Integer.parseInt(storeInfo.getAdministrativeRegionDistrictAdcode());
                EssentialCityCode essentialCityCode3 = essentialCityCodeMapper.selectOne(new LambdaQueryWrapper<EssentialCityCode>().eq(EssentialCityCode::getAreaCode, districtAdcode));
                if (null != essentialCityCode3) {
                    storeInfo.setAdministrativeRegionDistrictName(essentialCityCode3.getAreaName());
                } else {
                    log.warn("未找到区县编码对应的地区信息：{}", storeInfo.getAdministrativeRegionDistrictAdcode());
                }
            } catch (NumberFormatException e) {
                log.error("区县编码格式错误：{}", storeInfo.getAdministrativeRegionDistrictAdcode(), e);
            }
        }
        storeInfoMapper.updateById(storeInfo);
        nearMeService.inGeolocation(new Point(Double.parseDouble(storeInfoDto.getStorePositionLongitude()), Double.parseDouble(storeInfoDto.getStorePositionLatitude())), storeInfo.getId().toString(), Boolean.TRUE);

        //修改门店店铺用户绑定关系
        String userAccount = storeInfoDto.getUserAccount();
        StoreUser storeUser = storeUserMapper.selectById(userAccount);
        storeUser.setStoreId(storeInfo.getId());
        storeUserMapper.updateById(storeUser);
        BeanUtils.copyProperties(storeInfoDto, result);
        //存入店铺营业执照图片
        if (!CollectionUtils.isEmpty(storeInfoDto.getBusinessLicenseAddress())) {
            List<String> businessLicenseAddress = storeInfoDto.getBusinessLicenseAddress();
            //先移除此前数据
            storeImgMapper.delete(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeInfo.getId()).eq(StoreImg::getImgType, 14));
            for (String licenseAddress : businessLicenseAddress) {
                StoreImg storeImg = new StoreImg();
                storeImg.setStoreId(storeInfo.getId());
                storeImg.setImgType(14);
                storeImg.setImgDescription("营业执照");
                storeImg.setImgSort(0);
                storeImg.setImgUrl(licenseAddress);
                storeImgMapper.insert(storeImg);
            }
        }

        //存入店铺合同图片
        List<String> contractImageList = storeInfoDto.getContractImageList();
        if (!CollectionUtils.isEmpty(contractImageList)) {
            //先移除此前数据
            storeImgMapper.delete(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeInfo.getId()).eq(StoreImg::getImgType, 15));
            for (String licenseAddress : contractImageList) {
                StoreImg storeImg = new StoreImg();
                storeImg.setStoreId(storeInfo.getId());
                storeImg.setImgType(15);
                storeImg.setImgSort(0);
                storeImg.setImgDescription("合同图片");
                storeImg.setImgUrl(licenseAddress);
                storeImgMapper.insert(storeImg);
            }
        }

        //存入店铺经营许可证图片
        if (StringUtils.isNotEmpty(storeInfoDto.getFoodLicenceUrl())) {
            //先移除此前数据 type:25 审核通过后的图片
            storeImgMapper.delete(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeInfo.getId()).eq(StoreImg::getImgType, 25));
            //先移除此前数据 type:24 审核前的或者审核拒绝的图片
            storeImgMapper.delete(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeInfo.getId()).eq(StoreImg::getImgType, 24));
            StoreImg storeImg = new StoreImg();
            storeImg.setStoreId(storeInfo.getId());
            //type:25 审核通过的类型
            storeImg.setImgType(25);
            storeImg.setImgSort(0);
            storeImg.setImgDescription("经营许可证审核通过图片");
            storeImg.setImgUrl(storeInfoDto.getFoodLicenceUrl());
            storeImgMapper.insert(storeImg);
        }

        return result;
    }

    @Override
    public String deleteStoreInfo(StoreInfoDto storeInfoDto) {
        StoreUser storeUser = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, storeInfoDto.getId()));
        //判断是否有未完成的订单
        List<LifeUserOrder> lifeUserOrders = lifeUserOrderMapper.selectList(new LambdaQueryWrapper<LifeUserOrder>().in(LifeUserOrder::getStatus, 0, 3).eq(ObjectUtils.isNotEmpty(storeUser), LifeUserOrder::getUserId, storeUser.getId()).eq(LifeUserOrder::getDeleteFlag, 0));
        if (ObjectUtils.isNotEmpty(lifeUserOrders)) {
            return "您有暂未完成的订单无法删除店铺，请在完成后删除";
        } else {
            //判断是否修改变更过的用户账户
            if (storeUser != null) {
                LambdaUpdateWrapper<StoreUser> storeUserLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                storeUserLambdaUpdateWrapper.set(StoreUser::getStoreId, null).eq(StoreUser::getId, storeUser.getId());
                storeUserMapper.update(null, storeUserLambdaUpdateWrapper);
            }
            //删除商铺信息
            storeInfoMapper.deleteById(storeInfoDto.getId());
            return "成功";
        }
    }

    @Override
    public void restPassword(StoreInfoDto storeInfoDto) {
        StoreInfo storeInfo = storeInfoMapper.selectById(storeInfoDto.getId());
        storeInfo.setStorePass(DEFAULT_PASSWORD);
        //修改商铺信息密码
        storeInfoMapper.updateById(storeInfo);
        //删除商铺的用户
        StoreUser storeUser = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, storeInfoDto.getId()));
        storeUser.setPassword(DEFAULT_PASSWORD);
        storeUserMapper.updateById(storeUser);
    }

    @Override
    public List<StoreDictionaryVo> getBusinessSection() {
        List<StoreDictionary> businessSection = storeDictionaryMapper.selectList(new LambdaQueryWrapper<StoreDictionary>().eq(StoreDictionary::getTypeName, "business_section").ne(StoreDictionary::getDictId, 0));
        List<StoreDictionaryVo> voList = new ArrayList<>();
        for (StoreDictionary storeDictionary : businessSection) {
            StoreDictionaryVo vo = new StoreDictionaryVo();
            BeanUtils.copyProperties(storeDictionary, vo);
            voList.add(vo);
        }
        return voList;
    }

    @Override
    public List<StoreDictionaryVo> getBusinessSectionTypes(String parentId) {
        StoreDictionary businessSection = storeDictionaryMapper.selectOne(new LambdaQueryWrapper<StoreDictionary>()
                .eq(StoreDictionary::getTypeName, "business_section")
                .eq(StoreDictionary::getDictId, parentId)
                .isNull(StoreDictionary::getParentId));
        List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(new LambdaQueryWrapper<StoreDictionary>()
                .eq(StoreDictionary::getTypeName, "business_type")
                .eq(StoreDictionary::getParentId, businessSection.getId())
                .eq(StoreDictionary::getDeleteFlag, 0));
        List<StoreDictionaryVo> voList = new ArrayList<>();
        for (StoreDictionary storeDictionary : storeDictionaries) {
            StoreDictionaryVo vo = new StoreDictionaryVo();
            BeanUtils.copyProperties(storeDictionary, vo);
            voList.add(vo);
        }
        return voList;
    }

    @Override
    public List<StoreUserVo> getUnboundAccountList(String id) {
        List<StoreUserVo> storeUserVoList = new ArrayList<>();
        List<StoreUser> storeUsers = storeUserMapper.selectList(new LambdaQueryWrapper<StoreUser>().isNull(StoreUser::getStoreId));
        for (StoreUser storeUser : storeUsers) {
            StoreUserVo vo = new StoreUserVo();
            BeanUtils.copyProperties(storeUser, vo);
            vo.setPayPassword("");
            vo.setPassword("");
            storeUserVoList.add(vo);
        }
        if (StringUtils.isNotEmpty(id)) {
            StoreUser storeUser = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, id));
            if (storeUser != null) {
                StoreUserVo vo = new StoreUserVo();
                BeanUtils.copyProperties(storeUser, vo);
                vo.setPayPassword("");
                vo.setPassword("");
                storeUserVoList.add(vo);
            }
        }
        return storeUserVoList;
    }

    @Override
    public void addBusinessSectionAndTypes(StoreInfoDto storeInfoDto) {
        StoreDictionary businessSectionParent = storeDictionaryMapper.selectOne(new LambdaQueryWrapper<StoreDictionary>().eq(StoreDictionary::getTypeName, "business_section").eq(StoreDictionary::getDictId, 0));
        //查看当前最大id
        List<StoreDictionary> businessSection = storeDictionaryMapper.selectList(new LambdaQueryWrapper<StoreDictionary>().eq(StoreDictionary::getTypeName, "business_section"));
        Integer maxId = 0;
        for (StoreDictionary storeDictionary : businessSection) {
            if (Integer.parseInt(storeDictionary.getDictId()) > maxId) {
                maxId = Integer.parseInt(storeDictionary.getDictId());
            }
        }
        //构建新增的经营板块
        StoreDictionary addStoreDictionary = new StoreDictionary();
        BeanUtils.copyProperties(businessSection.get(0), addStoreDictionary);
        addStoreDictionary.setId(null);
        addStoreDictionary.setDictDetail(storeInfoDto.getBusinessSectionName());
        addStoreDictionary.setDictId((maxId + 1) + "");
        addStoreDictionary.setParentId(businessSectionParent.getId());
        storeDictionaryMapper.insert(addStoreDictionary);
        //构建新增的经营类型
        List<String> businessTypesList = storeInfoDto.getBusinessTypesList();
        Integer dictgId = 0;
        for (String businessTypeName : businessTypesList) {
            StoreDictionary storeDictionary = new StoreDictionary();
            storeDictionary.setTypeName(storeInfoDto.getBusinessTypeValue());
            storeDictionary.setTypeDetail(addStoreDictionary.getDictDetail());
            storeDictionary.setParentId(addStoreDictionary.getId());
            storeDictionary.setDictId(dictgId + "");
            storeDictionary.setDictDetail(businessTypeName);
            storeDictionary.setCreatedTime(new Date());
            storeDictionaryMapper.insert(storeDictionary);
            dictgId++;
        }
    }

    @Override
    public StoreInfoVo getStoreDetail(String storeId, String userId, String jingdu, String weidu) {
        StoreInfoVo result = new StoreInfoVo();
        StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
        if (storeInfo == null) {
            return null;
        }
        BeanUtils.copyProperties(storeInfo, result);
        //将经营板块和种类拆分成集合
        String businessTypes = storeInfo.getBusinessTypes();
        if (StringUtils.isNotEmpty(businessTypes)) {
            String[] split = businessTypes.split(",");
            List<String> list = Arrays.asList(split);
            result.setBusinessTypesList(list);
        }
        //存入用户账户
        StoreUser storeUser = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, storeId));
        if (storeUser != null) {
            result.setUserAccount(storeUser.getId().toString());
            result.setStorePhone(storeUser.getPhone());
            result.setStoreUserName(storeUser.getName());
            result.setIdCard(storeUser.getIdCard());
        }
        //存入执照图片地址
        List<StoreImg> storeImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 14));
        List<String> storeImgPaths = new ArrayList<>();
        for (StoreImg storeImg : storeImgs) {
            storeImgPaths.add(storeImg.getImgUrl());
        }
        result.setBusinessLicenseAddress(storeImgPaths);
        //存入合同图片地址
        List<StoreImg> storeContractImageImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 15));
        List<String> storeContractImagePathImgs = new ArrayList<>();
        for (StoreImg storeImg : storeContractImageImgs) {
            storeContractImagePathImgs.add(storeImg.getImgUrl());
        }
        result.setContractImageList(storeContractImagePathImgs);
        //存入续签合同地址
        List<StoreImg> renewContractImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 22));
        List<String> renewContractImagePathImgs = new ArrayList<>();
        for (StoreImg storeImg : renewContractImgs) {
            renewContractImagePathImgs.add(storeImg.getImgUrl());
        }
        result.setRenewContractImageList(renewContractImagePathImgs);
        //存入经营许可证通过地址
        List<StoreImg> foodLicenceImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 25));
        List<String> foodLicenceImgsPathImgs = new ArrayList<>();
        for (StoreImg storeImg : foodLicenceImgs) {
            foodLicenceImgsPathImgs.add(storeImg.getImgUrl());
        }
        result.setFoodLicenceImageList(foodLicenceImgsPathImgs);
        //存入经营许可证未通过地址
        List<StoreImg> notPassFoodLicenceImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 24));
        List<String> notPassFoodLicenceList = new ArrayList<>();
        for (StoreImg storeImg : notPassFoodLicenceImgs) {
            notPassFoodLicenceList.add(storeImg.getImgUrl());
        }
        result.setNotPassFoodLicenceImageList(notPassFoodLicenceList);
        // 存放商家入口图
        List<StoreImg> storeEntranceImageImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 1));
        if (!storeEntranceImageImgs.isEmpty()) {
            result.setEntranceImage(storeEntranceImageImgs.get(0).getImgUrl());
        } else {
            result.setEntranceImage("null");
        }
        // 存放商家头像
        List<StoreImg> storeImgs1 = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 10));
        if (!storeImgs1.isEmpty()) {
            result.setImgUrl(storeImgs1.get(0).getImgUrl());
        } else {
            result.setImgUrl("null");
        }

        // 设置经纬度
        result.setStorePositionLongitude(result.getStorePosition().split(",")[0]);
        result.setStorePositionLatitude(result.getStorePosition().split(",")[1]);
        // 设置距离
        if ((jingdu != null && !jingdu.isEmpty()) && (weidu != null && !weidu.isEmpty())) {
            /*double storeJing = Double.parseDouble(result.getStorePosition().split(",")[0]);
            double storeWei = Double.parseDouble(result.getStorePosition().split(",")[1]);
            double storeDistance = DistanceUtil.haversineCalculateDistance(Double.parseDouble(jingdu), Double.parseDouble(weidu), storeJing, storeWei);*/

            Double distance = storeInfoMapper.getStoreDistance(jingdu + "," + weidu, result.getId());

            result.setDistance(distance);
        }
        // 计算店铺到最近地铁站的距离
        JSONObject nearbySubway = gaoDeMapUtil.getNearbySubway(result.getStorePosition().split(",")[0], result.getStorePosition().split(",")[1]);
        // 地铁名
        String subWayName = nearbySubway.getString("name");
        result.setSubwayName(subWayName);
        // 地铁站经纬度
        String subWayJing = nearbySubway.getString("location") == null ? null : nearbySubway.getString("location").split(",")[0];
        String subWayWei = nearbySubway.getString("location") == null ? null : nearbySubway.getString("location").split(",")[1];
        if ((subWayJing != null && !subWayJing.isEmpty()) && (subWayWei != null && !subWayWei.isEmpty())) {
            double storeJing = Double.parseDouble(result.getStorePosition().split(",")[0]);
            double storeWei = Double.parseDouble(result.getStorePosition().split(",")[1]);
            double storeDistance2 = DistanceUtil.haversineCalculateDistance(Double.parseDouble(subWayJing), Double.parseDouble(subWayWei), storeJing, storeWei);
            result.setDistance2(storeDistance2);
        } else {
            result.setDistance2(0);
        }
        // 当前登录用户是否收藏
        LambdaUpdateWrapper<LifeCollect> shouCangWrapper = new LambdaUpdateWrapper<>();
        LifeCollectIdentityQuery.applyUserSide(shouCangWrapper, LifeCollectIdentityQuery.resolve(userId, typeUtil));
        shouCangWrapper.eq(LifeCollect::getStoreId, storeId);
        List<LifeCollect> shouCangList = lifeCollectMapper.selectList(shouCangWrapper);
        if (null == shouCangList || shouCangList.isEmpty()) {
            result.setCollection(0);
        } else {
            result.setCollection(1);
        }
        // 获取店铺代金券列表
        LambdaUpdateWrapper<LifeCoupon> quanWrapper = new LambdaUpdateWrapper<>();
        quanWrapper.eq(LifeCoupon::getStoreId, storeId).eq(LifeCoupon::getStatus, CouponStatusEnum.ONGOING.getCode()).eq(LifeCoupon::getType, 1);
        List<LifeCoupon> quanList = lifeCouponMapper.selectList(quanWrapper);
        List<LifeCouponVo> quanVoList = new ArrayList<>();
        List<String> collect = quanList.stream().map(LifeCoupon::getId).collect(Collectors.toList());
        // 设置已售数量
        // 定义需要的订单状态集合
        Set<Integer> excludeStatuses = new HashSet<>(Arrays.asList(
                OrderStatusEnum.WAIT_PAY.getStatus(),
                OrderStatusEnum.WAIT_USE.getStatus(),
                OrderStatusEnum.USED.getStatus()
        ));
        if (!collect.isEmpty()) {
            List<LifeUserOrderVo> quanCount = lifeUserOrderMapper.getQuanCount(new QueryWrapper<LifeUserOrderVo>()
                    .eq("luo.store_id", storeId)
                    .eq("luo.coupon_type", CouponTypeEnum.COUPON.getCode())
                    .eq("luo.delete_flag", 0)
                    .in("ocm.status", excludeStatuses)
                    .groupBy("ocm.coupon_id"));
            quanList.forEach(a -> {
                LifeCouponVo lifeCouponVo = new LifeCouponVo();
                BeanUtils.copyProperties(a, lifeCouponVo);
                quanCount.forEach(item -> {
                    if (a.getId().equals(item.getCouponId().toString())) {
                        lifeCouponVo.setCount(item.getCount());
                    }
                });
                quanVoList.add(lifeCouponVo);
            });
        }
        result.setCouponList(quanVoList);

        // 获取店铺团购
        LambdaUpdateWrapper<LifeGroupBuyMain> tuangouWrapper = new LambdaUpdateWrapper<>();
        tuangouWrapper.eq(LifeGroupBuyMain::getStoreId, storeId).eq(LifeGroupBuyMain::getStatus, CouponStatusEnum.ONGOING.getCode()).orderByDesc(LifeGroupBuyMain::getCreatedTime);
        List<LifeGroupBuyMain> tuangouList = lifeGroupBuyMainMapper.selectList(tuangouWrapper);
        List<LifeGroupBuyMainVo> tuangouVOList = new ArrayList<>();
        for (LifeGroupBuyMain lifeGroupBuyMain : tuangouList) {
            LifeGroupBuyMainVo lifeGroupBuyMainVo = new LifeGroupBuyMainVo();
            BeanUtils.copyProperties(lifeGroupBuyMain, lifeGroupBuyMainVo);
            if (StringUtils.isNotEmpty(lifeGroupBuyMain.getImageId())) {
                List<String> ids = Arrays.stream(lifeGroupBuyMain.getImageId().split(",")).map(String::trim).collect(Collectors.toList());
                List<StoreImg> imgList = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().in(StoreImg::getId, ids));
                if (imgList != null) {
                    String imgs = imgList.stream().map(StoreImg::getImgUrl).collect(Collectors.joining(","));
                    lifeGroupBuyMainVo.setImageId(imgs);
                }
            }
            tuangouVOList.add(lifeGroupBuyMainVo);
        }
        result.setTuangouList(tuangouVOList);

        // 获取员工列表
        LambdaQueryWrapper<StoreStaffConfig> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StoreStaffConfig::getStoreId, storeId);
        List<StoreStaffConfig> storeStaffConfigs = storeStaffConfigMapper.selectList(lambdaQueryWrapper);
        result.setEmployeeList(storeStaffConfigs);

        // 该用户的打卡记录（仅审核通过 check_flag=2，未审核/审核中/拒绝均不计入）
        LambdaQueryWrapper<StoreClockIn> clockInWrapper = new LambdaQueryWrapper<>();
        clockInWrapper.eq(StoreClockIn::getUserId, userId);
        clockInWrapper.eq(StoreClockIn::getCheckFlag, 2);
        List<StoreClockIn> clockInList = storeClockInMapper.selectList(clockInWrapper);

        List<StoreClockIn> clockStoreList = clockInList.stream().filter(item -> item.getStoreId() == Integer.parseInt(storeId)).collect(Collectors.toList());
        // 该用户是否在该店铺打过卡
        if (!clockStoreList.isEmpty()) {
            result.setClockInStore(1);
        } else {
            result.setClockInStore(0);
        }

        // 今天在该店铺是否打过卡
        int today = (int) clockStoreList.stream().filter(item -> item.getCreatedTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().equals(LocalDate.now())).count();
        if (today > 0) {
            result.setClockInStoreToday(1);
        } else {
            result.setClockInStoreToday(0);
        }

        // 店铺平均分
        /*Map<Object, List<Map<String, Object>>> avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream().collect(Collectors.groupingBy(o -> o.get("store_id")));
        if (avgScoreMap.containsKey(String.valueOf(result.getId()))) {
            result.setScore(Double.parseDouble(avgScoreMap.get(String.valueOf(result.getId())).get(0).get("avg_score").toString()));
        }*/

        Map<String, Object> commitCountAndScore = storeCommentService.getCommitCountAndScore(null, 5, Integer.parseInt(storeId), null, null);
        result.setScore(Double.parseDouble(commitCountAndScore.get("score").toString()));
        result.setCommitCount(commitCountAndScore.get("commitCount").toString());


        // 在该店铺的打卡次数
        result.setClockInStoreNum(clockStoreList.size());

        // 该用户打卡的所有店铺次数（一个店铺只算一次）
        int clockInNum = (int) clockInList.stream().map(StoreClockIn::getStoreId).distinct().count();
        result.setClockInNum(clockInNum);

        // 获取店铺动态列表
        LambdaQueryWrapper<LifeBlacklist> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper1.eq(LifeBlacklist::getBlockerId, userId);
        lambdaQueryWrapper1.eq(LifeBlacklist::getBlockedPhoneId, "store_" + result.getStorePhone());
        LifeBlacklist blacklist = lifeBlacklistMapper.selectOne(lambdaQueryWrapper1);
        List<LifeUserDynamicsVo> storeDynamicslist = new ArrayList<>();

        //判断没有拉黑当前门店账户 查出门店动态
        if (blacklist == null) {
            PublisherScope storePublisher = dynamicsIdentityHelper.resolveStorePublisherByStorePhone(result.getStorePhone());
            storeDynamicslist = lifeUserDynamicsMapper.getStoreDynamicslist(
                    userId,
                    storePublisher.getPhoneUserType(),
                    storePublisher.getPhoneRefId());
        }

        List<String> followList = new ArrayList<>();
        List<String> fansList = new ArrayList<>();

        if (StringUtils.isNotEmpty(userId)) {
            LifeUser lifeUser = lifeUserMapper.selectById(userId);
            if (lifeUser != null && StringUtils.isNotEmpty(lifeUser.getUserPhone())) {
                // 查询我的关注信息，构建关注者ID列表
                LifeFansIdentityQuery.Scope storeViewerScope = LifeFansIdentityQuery.resolve("user_" + result.getStorePhone(), typeUtil);
                LambdaQueryWrapper<LifeFans> lifeFansWrapper = new LambdaQueryWrapper<>();
                lifeFansWrapper.eq(LifeFans::getDeleteFlag, 0);
                LifeFansIdentityQuery.applyFansSide(lifeFansWrapper, storeViewerScope);
                List<LifeFans> lifeFansList = lifeFansMapper.selectList(lifeFansWrapper);
                if (!CollectionUtils.isEmpty(lifeFansList)) {
                    followList = lifeFansList.stream().map(LifeFans::getFollowedId).collect(Collectors.toList());
                }

                // 查询我的粉丝信息，构建粉丝ID列表
                lifeFansWrapper = new LambdaQueryWrapper<>();
                lifeFansWrapper.eq(LifeFans::getDeleteFlag, 0);
                LifeFansIdentityQuery.applyFollowedSide(lifeFansWrapper, storeViewerScope);
                lifeFansList = lifeFansMapper.selectList(lifeFansWrapper);
                if (!CollectionUtils.isEmpty(lifeFansList)) {
                    fansList = lifeFansList.stream().map(LifeFans::getFansId).collect(Collectors.toList());
                }
            }
        }

        for (LifeUserDynamicsVo vo : storeDynamicslist) {
            dynamicsIdentityHelper.ensureVoLegacyPhoneId(vo);
            if (followList.contains(vo.getPhoneId())) {
                vo.setIsFollowThis("1");
            } else {
                vo.setIsFollowThis("0");
            }
            if (fansList.contains(vo.getPhoneId())) {
                vo.setIsFollowMe("1");
            } else {
                vo.setIsFollowMe("0");
            }
        }

        // 返回动态最新的5条
        List<LifeUserDynamicsVo> storeDynamicslist2 = storeDynamicslist.stream()
                .limit(5).collect(Collectors.toList());
        result.setDynamicsList(storeDynamicslist2);
        //设置动态条数
        Integer dynamicsNum = storeDynamicslist2.size();
        result.setDynamicsNum(dynamicsNum);

        // 获取店铺动态总数
        result.setTotalDynamicsNum(storeDynamicslist.size());

        //营业时间
        List<StoreBusinessInfo> storeBusinessInfos = storeBusinessInfoMapper.selectList(new LambdaQueryWrapper<StoreBusinessInfo>().eq(StoreBusinessInfo::getStoreId, storeId).eq(StoreBusinessInfo::getDeleteFlag, 0));
        if (ObjectUtils.isNotEmpty(storeBusinessInfos)) {
            result.setStoreBusinessInfo(storeBusinessInfos.get(0));
            result.setStoreBusinessInfos(storeBusinessInfos);
            //StoreBusinessInfo storeBusinessInfo = result.getStoreBusinessInfo();
            StoreBusinessInfo storeBusinessInfo = result.getStoreBusinessInfos().stream().filter(item -> item.getBusinessType() == 1).findFirst().orElse(null);
            if (ObjectUtils.isNotEmpty(storeBusinessInfo)) {

                Calendar calendar = Calendar.getInstance(); // 获取Calendar实例
                int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); // 获取星期几，注意Calendar中的DAY_OF_WEEK是从1（代表星期天）开始的
                String[] days = {"7", "1", "2", "3", "4", "5", "6"};
                String day = days[dayOfWeek - 1];
                if (storeBusinessInfo.getBusinessDate().contains(day)) {
                    if (StringUtils.isNotEmpty(storeBusinessInfo.getStartTime()) && StringUtils.isNotEmpty(storeBusinessInfo.getEndTime())) {
                        LocalTime now = LocalTime.now();
                        List<String> startList = Arrays.asList(storeBusinessInfo.getStartTime().split(":"));
                        List<String> endList = Arrays.asList(storeBusinessInfo.getEndTime().split(":"));
                        LocalTime start = LocalTime.of(Integer.parseInt(startList.get(0)), Integer.parseInt(startList.get(1)));
                        LocalTime end = LocalTime.of(Integer.parseInt(endList.get(0)), Integer.parseInt(startList.get(1)));
                        if (now.isAfter(start) && now.isBefore(end)) {
                            result.setYyFlag(1);
                        } else {
                            result.setYyFlag(0);
                        }
                    }
                } else {
                    result.setYyFlag(0);
                }
            }
        }
        LambdaQueryWrapper<StoreDictionary> storeDictionaryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        storeDictionaryLambdaQueryWrapper.eq(StoreDictionary::getTypeName, "businessStatus")
                .eq(StringUtils.isNotEmpty(result.getBusinessStatus().toString()), StoreDictionary::getDictId, result.getBusinessStatus());
        List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(storeDictionaryLambdaQueryWrapper);
        if (!storeDictionaries.isEmpty()) {
            result.setBusinessStatusStr(storeDictionaries.get(0).getDictDetail());
        }
        // TODO 之后修改********** 正常OcrType由前端传存储ocr表要加新字段。传参要由前端传。
        // 查询并设置各类证件OCR信息
        // 检查storeUser是否为null，避免空指针异常
        if (storeUser != null && storeUser.getId() != null) {
            result.setJyxkz(convertOcrResultToJson(storeUser.getId(), "BUSINESS_LICENSE", "营业执照", true));
            result.setIdcardFace(convertOcrResultToJson(storeUser.getId(), "ID_CARD", "face", true));
            result.setIdcardBack(convertOcrResultToJson(storeUser.getId(), "ID_CARD", "back", true));
            result.setFoodLicence(convertOcrResultToJson(storeUser.getId(), "FOOD_MANAGE_LICENSE", null, true));
            result.setEntertainmentLicence(convertOcrResultToJson(storeUser.getId(), "BUSINESS_LICENSE", "娱乐", false));
        }

        return result;
    }

    @Override
    public void approveStoreInfo(String storeId, Integer approvalStatus, String reason) {
        StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
        storeInfo.setStoreApplicationStatus(approvalStatus);
        storeInfo.setReason(reason);
        storeInfo.setReviewDate(new Date());
        StoreUser storeUser = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, storeInfo.getId()).eq(StoreUser::getDeleteFlag, 0));
        storeInfoMapper.updateById(storeInfo);

        //处理中台审核记录
        LambdaUpdateWrapper<WebAudit> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(WebAudit::getStoreInfoId, storeId);
        wrapper.set(WebAudit::getStatus, "1");
        webAuditMapper.update(null, wrapper);

        // 发送审核通知
        LifeNotice lifeNotice = new LifeNotice();
        lifeNotice.setSenderId("system");
        lifeNotice.setReceiverId("store_" + storeUser.getPhone());

        lifeNotice.setBusinessId(storeInfo.getId());
        lifeNotice.setTitle("店铺审核通知");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String createDate = simpleDateFormat.format(storeInfo.getCreatedTime());

        com.alibaba.fastjson2.JSONObject jsonObject = new com.alibaba.fastjson2.JSONObject();
        if (2 == approvalStatus) {
            jsonObject.put("message", "您在" + createDate + "提交的入驻店铺申请，审核失败。失败原因：" + reason + "。");
        } else {
            jsonObject.put("message", "您在" + createDate + "提交的入驻店铺申请，已通过审核，欢迎您的加入。");
        }
        lifeNotice.setContext(jsonObject.toJSONString());
        lifeNotice.setNoticeType(1); // 系统通知
        lifeNotice.setIsRead(0);
        lifeNoticeUtil.fillUserTypeAndRefId(lifeNotice);
        lifeNoticeMapper.insert(lifeNotice);

        WebSocketVo websocketVo = new WebSocketVo();
        websocketVo.setSenderId("system");
        websocketVo.setReceiverId("store_" + storeUser.getPhone());
        websocketVo.setCategory("notice");
        websocketVo.setNoticeType("1");
        websocketVo.setIsRead(0);
        websocketVo.setText(com.alibaba.fastjson2.JSONObject.from(lifeNotice).toJSONString());
        try {
            webSocketProcess.sendMessage("store_" + storeUser.getPhone(), com.alibaba.fastjson2.JSONObject.from(websocketVo).toJSONString());
        } catch (Exception e) {
            log.error("LifeUserService webSocketProcess approveStoreInfo Stack={}", e);
        }
    }

    @Override
    public boolean manualReview(StoreInfoDto storeInfoDto) {
        if (storeInfoDto == null || storeInfoDto.getId() == null) {
            throw new IllegalArgumentException("门店ID不能为空");
        }

        LambdaUpdateWrapper<StoreInfo> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(StoreInfo::getId, storeInfoDto.getId());

        if (storeInfoDto.getManualReviewStatus() != null) {
            wrapper.set(StoreInfo::getManualReviewStatus, storeInfoDto.getManualReviewStatus());
        }

        Date reviewTime = storeInfoDto.getManualReviewTime() == null ? new Date() : storeInfoDto.getManualReviewTime();
        wrapper.set(StoreInfo::getManualReviewTime, reviewTime);

        if (StringUtils.isNotEmpty(storeInfoDto.getManualReviewReason())) {
            wrapper.set(StoreInfo::getManualReviewReason, storeInfoDto.getManualReviewReason());
        }

        return storeInfoMapper.update(null, wrapper) > 0;
    }

    @Override
    public String exportExcel(String id, String storePhone, String businessSection, String storeApplicationStatusStr) throws IOException {
        // 定义格式化模式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 先将 Date 转换为 Instant
        List<StoreInfoVo> storeInfoVos = storeInfoMapper.getStoreInfoVo(new QueryWrapper<StoreInfoVo>().like(StringUtils.isNotEmpty(id), "a.id", id).like(StringUtils.isNotEmpty(storePhone), "b.phone", storePhone).eq(StringUtils.isNotEmpty(storeApplicationStatusStr), "a.store_application_status", storeApplicationStatusStr).eq(StringUtils.isNotEmpty(businessSection), "a.business_section", businessSection).eq("a.delete_flag", 0).eq("b.delete_flag", 0).orderByDesc("a.created_time"));
        List<StoreInfoExcelVo> storeInfoExcelVos = new ArrayList<>();
        int serialNumber = 0;
        for (StoreInfoVo storeInfoVo : storeInfoVos) {
            StoreInfoExcelVo storeInfoExcelVo = new StoreInfoExcelVo();
            //存入序号
            storeInfoExcelVo.setSerialNumber(++serialNumber);
            //获取营业执照图片
            List<StoreImg> storeImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeInfoVo.getId()).eq(StoreImg::getImgType, 14));
            storeInfoExcelVo.setBusinessLicense(storeImgs != null && storeImgs.size() > 0 ? storeImgs.get(0).getImgUrl() : "");
            //获取合同图片
            List<StoreImg> storeContractImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeInfoVo.getId()).eq(StoreImg::getImgType, 15));
            storeInfoExcelVo.setContractImage(storeContractImgs != null && storeContractImgs.size() > 0 ? storeContractImgs.get(0).getImgUrl() : "");
            BeanUtils.copyProperties(storeInfoVo, storeInfoExcelVo);
            Instant instant = storeInfoVo.getCreatedTime().toInstant();
            // 格式化时间
            String formattedTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime().format(formatter);
            storeInfoExcelVo.setCreatedTime(formattedTime);
            //格式化状态
            storeInfoExcelVo.setStoreStatus(storeInfoVo.getStoreStatus() == 0 ? "禁用" : "正常");
            //格式化审批状态
            Integer storeApplicationStatus = storeInfoVo.getStoreApplicationStatus();
            if (storeApplicationStatus == 0) {
                storeInfoExcelVo.setStoreApplicationStatus("待审批");
            } else if (storeApplicationStatus == 1) {
                storeInfoExcelVo.setStoreApplicationStatus("审批通过");
            } else if (storeApplicationStatus == 2) {
                storeInfoExcelVo.setStoreApplicationStatus("审批拒绝");
            }
            //存入创建时间
            storeInfoExcelVos.add(storeInfoExcelVo);
        }
        String fileName = UUID.randomUUID().toString().replace("-", "");
        String filePath = ExcelGenerator.generateExcel(excelPath + excelGeneratePath + fileName + ".xlsx", storeInfoExcelVos, StoreInfoExcelVo.class);
        return aliOSSUtil.uploadFile(new File(filePath), "excel/" + fileName + ".xlsx");
    }

    @Override
    public String exportExcelExpirationTime(String id, String expiredState) throws IOException {
        // 获取当前时刻
        Date currentDate = new Date();
        // 定义格式化模式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 先将 Date 转换为 Instant
        List<StoreInfoVo> storeInfoVos = storeInfoMapper.getStoreInfoVo(new QueryWrapper<StoreInfoVo>().like(StringUtils.isNotEmpty(id), "a.id", id).eq("a.delete_flag", 0).eq("b.delete_flag", 0).orderByDesc("a.created_time"));
        List<StoreInfoExpiredRecordsExcelVo> storeInfoExpiredRecordsExcelVos = new ArrayList<>();
        int serialNumber = 0;
        for (StoreInfoVo storeInfoVo : storeInfoVos) {
            StoreInfoExpiredRecordsExcelVo storeInfoExpiredRecordsExcelVo = new StoreInfoExpiredRecordsExcelVo();
            storeInfoExpiredRecordsExcelVo.setSerialNumber(++serialNumber);
            BeanUtils.copyProperties(storeInfoVo, storeInfoExpiredRecordsExcelVo);
            if (storeInfoVo.getExpirationTime() != null) {
                Instant instant = storeInfoVo.getExpirationTime().toInstant();
                // 格式化时间
                String formattedTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime().format(formatter);
                storeInfoExpiredRecordsExcelVo.setExpirationTime(formattedTime);
                //格式化过期状态
                //处理一下到期状态
                Date expirationTime = storeInfoVo.getExpirationTime();
                // 获取当前时间
                Calendar now = Calendar.getInstance();
                Date nowCurrentDate = now.getTime();

                // 计算 30 天后的时间
                now.add(Calendar.DAY_OF_YEAR, 30);
                Date thirtyDaysLater = now.getTime();
                // 比较两个日期
                if (expirationTime.after(currentDate)) {
                    storeInfoExpiredRecordsExcelVo.setExpiredState("未过期");
                    if (expirationTime != null && (expirationTime.after(nowCurrentDate) || expirationTime.equals(nowCurrentDate)) && expirationTime.before(thirtyDaysLater)) {
                        storeInfoExpiredRecordsExcelVo.setExpiredState("即将过期");
                    }
                } else {
                    storeInfoExpiredRecordsExcelVo.setExpiredState("已过期");
                }
                // 获取当前时间
                LocalDate nowLocal = LocalDate.now();
                // 将 expirationTime 转换为 LocalDate
                LocalDate expDate = expirationTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

                // 计算距离到期的天数
                long daysToExpire = ChronoUnit.DAYS.between(nowLocal, expDate);
                storeInfoExpiredRecordsExcelVo.setDaysToExpire(daysToExpire > 0 ? daysToExpire : 0);

                //存入创建时间
                if (StringUtils.isNotEmpty(expiredState)) {
                    String expiredStateName = storeInfoExpiredRecordsExcelVo.getExpiredState();
                    if (expiredState.equals("0") && expiredStateName.equals("未过期")) {
                        storeInfoExpiredRecordsExcelVos.add(storeInfoExpiredRecordsExcelVo);
                    }
                    if (expiredState.equals("1") && expiredStateName.equals("即将过期")) {
                        storeInfoExpiredRecordsExcelVos.add(storeInfoExpiredRecordsExcelVo);
                    }
                    if (expiredState.equals("2") && expiredStateName.equals("已过期")) {
                        storeInfoExpiredRecordsExcelVos.add(storeInfoExpiredRecordsExcelVo);
                    }
                } else {
                    storeInfoExpiredRecordsExcelVos.add(storeInfoExpiredRecordsExcelVo);
                }
            }
        }
        String fileName = UUID.randomUUID().toString().replace("-", "");
        String filePath = ExcelGenerator.generateExcel(excelPath + excelGeneratePath + fileName + ".xlsx", storeInfoExpiredRecordsExcelVos, StoreInfoExpiredRecordsExcelVo.class);
        String url = aliOSSUtil.uploadFile(new File(filePath), "excel/" + fileName + ".xlsx");
        new File(filePath).delete();
        return url;
    }

    @Override
    public IPage<StoreInfo> getScreening(ScreeningOfEightMajorCategoriesVO vo) {
        // 参数校验
        if (vo == null) {
            throw new IllegalArgumentException("筛选参数不能为空");
        }

        // 创建分页对象
        IPage<StoreInfo> page = new Page<>(vo.getPageNum(), vo.getPageSize());

        // 获取筛选条件
        String screeningId = vo.getScreeningId();
        Double lon = vo.getLon();
        Double lat = vo.getLat();
        Double distance = vo.getDistance();
        Boolean flag = vo.getFlag();
        String startTime = vo.getStartTime();
        String endTime = vo.getEndTime();
        Double priceStr = vo.getPriceStr();
        Double priceEnd = vo.getPriceEnd();

        // 验证经纬度和距离参数
        if (flag != null && flag) {
            if (lon == null || lat == null || distance == null) {
                throw new IllegalArgumentException("启用距离筛选时，经纬度和距离参数不能为空");
            }
            if (distance <= 0) {
                throw new IllegalArgumentException("距离参数必须大于0");
            }
        }

        String storeId = "";

        // 通过经纬度距离获取商家id
        if (lat != null && lon != null && distance != null) {
            List<NearMeDto> nearMeDtos = nearMeService.nearbyMerchants(lon, lat, distance, flag);
            if (nearMeDtos != null && !nearMeDtos.isEmpty()) {
                storeId = nearMeDtos.stream().map(item -> String.valueOf(item.getConent())).collect(Collectors.joining(","));
            }
        }

        // 通过筛选id获取商家id
        if (StringUtils.isNotEmpty(screeningId)) {
            String[] list = screeningId.split(",");
            for (String id : list) {
                if (StringUtils.isEmpty(storeId)) {
                    storeId = baseRedisService.getString(id);
                } else {
                    String redisStoreId = baseRedisService.getString(id);
                    if (redisStoreId != null) {
                        storeId = findCommon(storeId, redisStoreId);
                    }
                }
            }
        }

        // 通过商家id获取商家信息
        IPage<StoreInfo> storeInfoIPage = new Page<>();

        if (StringUtils.isNotEmpty(storeId)) {
            List<String> storeIds = Arrays.asList(storeId.split(","));
            if (StringUtils.isNotEmpty(startTime) && StringUtils.isNotEmpty(endTime)) {
                List<StoreBusinessInfo> storeBusinessInfos = storeBusinessInfoMapper.selectList(new LambdaQueryWrapper<StoreBusinessInfo>().in(StoreBusinessInfo::getStoreId, storeIds));
                DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendValue(ChronoField.HOUR_OF_DAY, 1, 2, SignStyle.NOT_NEGATIVE).appendLiteral(':').appendValue(ChronoField.MINUTE_OF_HOUR, 2).toFormatter();
                List<StoreBusinessInfo> list = storeBusinessInfos.stream().filter(item -> {
                    // 商家开门时间
                    LocalTime timeStart = LocalTime.parse(item.getEndTime(), formatter);
                    // 商家关门时间
                    LocalTime timeEnd = LocalTime.parse(item.getEndTime(), formatter);
                    // 开始时间
                    LocalTime time1 = LocalTime.parse(startTime);
                    // 结束时间
                    LocalTime time2 = LocalTime.parse(endTime);
                    return !time1.isBefore(timeStart) && !time2.isAfter(timeEnd);
                }).collect(Collectors.toList());

                storeIds = list.stream().map(item -> String.valueOf(item.getStoreId())).collect(Collectors.toList());
            }
            storeIds.stream().filter(Objects::nonNull) // 确保 storeId 不为 null
                    .distinct() // 去重
                    .map(String::valueOf).collect(Collectors.toList());
            if (priceStr != null && priceEnd != null) {
                List<LifeCoupon> lifeCoupons = lifeCouponMapper.selectList(new LambdaQueryWrapper<LifeCoupon>().in(LifeCoupon::getStoreId, storeIds));
                List<LifeCoupon> list = lifeCoupons.stream().filter(item -> Double.parseDouble(item.getPrice()) >= priceStr && Double.parseDouble(item.getPrice()) < priceEnd).collect(Collectors.toList());
                storeIds = list.stream().map(item -> String.valueOf(item.getStoreId())).collect(Collectors.toList());
            }
            if (!CollectionUtils.isEmpty(storeIds)) {
                LambdaQueryWrapper<StoreInfo> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.in(StoreInfo::getId, storeIds);
                storeInfoIPage = storeInfoMapper.selectPage(page, queryWrapper);
            }
        }
        return storeInfoIPage;
    }

    @Override
    public IPage<StoreInfoVo> getScreeningNew(ScreeningOfEightMajorCategoriesVO vo) {
        // 参数校验
        if (vo == null) {
            throw new IllegalArgumentException("筛选参数不能为空");
        }

        // 获取筛选条件
        String screeningId = vo.getScreeningId();
        Double lon = vo.getLon();
        Double lat = vo.getLat();
        Double distance = vo.getDistance();
        Boolean flag = vo.getFlag();
        String startTime = vo.getStartTime();
        String endTime = vo.getEndTime();
        Double priceStr = vo.getPriceStr();
        Double priceEnd = vo.getPriceEnd();

        if (lon == null || lat == null) {
            throw new IllegalArgumentException("经纬度参数不能为空");
        }
        // 创建分页对象
        IPage<StoreInfoVo> page = new Page<>(vo.getPageNum(), vo.getPageSize());

        String storeId = "";

        // 通过筛选id获取商家id
        if (StringUtils.isNotEmpty(screeningId)) {
            String[] list = screeningId.split(",");
            for (String id : list) {
                if (StringUtils.isEmpty(storeId)) {
                    storeId = baseRedisService.getString(id);
                } else {
                    String redisStoreId = baseRedisService.getString(id);
                    if (redisStoreId != null) {
                        storeId = findCommon(storeId, redisStoreId);
                    }
                }
            }
        }

        // 通过商家id获取商家信息
        IPage<StoreInfoVo> storeInfoIPage = new Page<>();
        QueryWrapper<StoreInfoVo> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(storeId)) {
            List<String> storeIds = Arrays.asList(storeId.split(","));
            if (StringUtils.isNotEmpty(startTime) && StringUtils.isNotEmpty(endTime)) {
                List<StoreBusinessInfo> storeBusinessInfos = storeBusinessInfoMapper.selectList(new LambdaQueryWrapper<StoreBusinessInfo>().in(StoreBusinessInfo::getStoreId, storeIds));
                DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendValue(ChronoField.HOUR_OF_DAY, 1, 2, SignStyle.NOT_NEGATIVE).appendLiteral(':').appendValue(ChronoField.MINUTE_OF_HOUR, 2).toFormatter();
                List<StoreBusinessInfo> list = storeBusinessInfos.stream().filter(item -> {
                    // 商家开门时间
                    LocalTime timeStart = LocalTime.parse(item.getEndTime(), formatter);
                    // 商家关门时间
                    LocalTime timeEnd = LocalTime.parse(item.getEndTime(), formatter);
                    // 开始时间
                    LocalTime time1 = LocalTime.parse(startTime);
                    // 结束时间
                    LocalTime time2 = LocalTime.parse(endTime);
                    return !time1.isBefore(timeStart) && !time2.isAfter(timeEnd);
                }).collect(Collectors.toList());

                storeIds = list.stream().map(item -> String.valueOf(item.getStoreId())).collect(Collectors.toList());
            }
            storeIds.stream().filter(Objects::nonNull) // 确保 storeId 不为 null
                    .distinct() // 去重
                    .map(String::valueOf).collect(Collectors.toList());
            if (priceStr != null && priceEnd != null) {
                List<LifeCoupon> lifeCoupons = lifeCouponMapper.selectList(new LambdaQueryWrapper<LifeCoupon>().in(LifeCoupon::getStoreId, storeIds));
                List<LifeCoupon> list = lifeCoupons.stream().filter(item -> Double.parseDouble(item.getPrice()) >= priceStr && Double.parseDouble(item.getPrice()) < priceEnd).collect(Collectors.toList());
                storeIds = list.stream().map(item -> String.valueOf(item.getStoreId())).collect(Collectors.toList());
            }
            if (!CollectionUtils.isEmpty(storeIds)) {
                queryWrapper.in("a.id", storeIds);
            }
        }

        queryWrapper.eq("a.delete_flag", 0);
        queryWrapper.eq("a.logout_flag", 0);
        queryWrapper.ne("a.store_status", 0);
        queryWrapper.eq("a.business_section", 1);

        queryWrapper.ge("a.food_licence_expiration_time", new Date());

        queryWrapper.like(StringUtils.isNotEmpty(vo.getFoodType()), "a.business_types_name", vo.getFoodType());
        queryWrapper.like(StringUtils.isNotEmpty(vo.getStoreName()), "a.store_name", vo.getStoreName());

        if (ObjectUtils.isNotEmpty(vo.getRqyx())) {
            if (vo.getRqyx() == 1) {
                queryWrapper.orderByDesc("collect_num");
            }
        }

        if (ObjectUtils.isNotEmpty(vo.getKwyx())) {
            if (vo.getKwyx() == 1) {
                queryWrapper.orderByDesc("taste_score");
            }
        }

        if (ObjectUtils.isNotEmpty(vo.getHjyx())) {
            if (vo.getHjyx() == 1) {
                queryWrapper.orderByDesc("en_score");
            }
        }

        if (ObjectUtils.isNotEmpty(vo.getFwyx())) {
            if (vo.getFwyx() == 1) {
                queryWrapper.orderByDesc("service_score");
            }
        }

        if (ObjectUtils.isNotEmpty(vo.getHpyx())) {
            if (vo.getHpyx() == 1) {
                queryWrapper.orderByDesc("score_avg");
            }
        }
        queryWrapper.orderByAsc("dist");
        storeInfoIPage = storeInfoMapper.getPageForDistance(page, lon + "," + lat, queryWrapper);
        List<StoreInfoVo> storeInfoVoList = storeInfoIPage.getRecords();

        // 提取所有符合条件的门店ID
        List<Integer> storeIds = storeInfoVoList.stream().map(StoreInfoVo::getId).collect(Collectors.toList());
        // 构建查询优惠券的条件对象
        LambdaUpdateWrapper<LifeCoupon> quanWrapper = new LambdaUpdateWrapper<>();
        // 添加门店ID筛选条件
        quanWrapper.in(ObjectUtils.isNotEmpty(storeIds), LifeCoupon::getStoreId, storeIds)
                // 添加优惠券状态筛选条件
                .eq(LifeCoupon::getStatus, CouponStatusEnum.ONGOING.getCode())
                // 按照创建时间降序排序
                .orderByDesc(LifeCoupon::getCreatedTime);
        // 查询符合条件的优惠券列表
        List<LifeCoupon> quanList = lifeCouponMapper.selectList(quanWrapper);
        // 构建查询团购套餐条件对象
        LambdaUpdateWrapper<LifeGroupBuyMain> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 添加门店ID筛选条件
        lambdaUpdateWrapper.in(ObjectUtils.isNotEmpty(storeIds), LifeGroupBuyMain::getStoreId, storeIds)
                // 添加团购套餐状态筛选条件
                .eq(LifeGroupBuyMain::getStatus, 5)
                .orderByDesc(LifeGroupBuyMain::getCreatedTime);
        // 查询符合条件的团购套餐列表
        List<LifeGroupBuyMain> lifeGroupBuyMainList = lifeGroupBuyMainMapper.selectList(lambdaUpdateWrapper);
        // 获取全部店铺的评分与平均花销
        Map<String, List<Map<String, Object>>> avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream().collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
        // 获取用户订单信息，用于计算平均消费
        Map<String, List<Map<String, Object>>> avgPriceMap = lifeUserOrderMapper.allStoreAvgPrice().stream().collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
        // 获取所有店铺的打卡次数
        List<Map<Integer, Integer>> storeClockInCountList = storeClockInService.getStoreClockInCount();
        // 遍历所有门店信息，构造返回结果
        for (StoreInfoVo store : storeInfoVoList) {
            Map<String, Object> storeMap = new HashMap<>();
            storeMap.put("dist", store.getDist());
            // 添加门店的业务状态及其描述
            storeMap.put("businessStatus", store.getBusinessStatus());
            storeMap.put("businessStatusStr", store.getBusinessStatusStr());
            // 添加门店ID
            storeMap.put("storeId", store.getId());
            // 如果存在评分数据，则添加评分、平均消费及评价总数
            if (avgScoreMap.containsKey(String.valueOf(store.getId()))) {
                store.setAvgScore(new BigDecimal(avgScoreMap.get(String.valueOf(store.getId())).get(0).get("avg_score").toString()).setScale(1, RoundingMode.HALF_UP).toString());
                store.setTotalNum(avgScoreMap.get(String.valueOf(store.getId())).get(0).get("total_num").toString());
                /*storeMap.put("avgScore", avgScoreMap.get(String.valueOf(store.getId())).get(0).get("avg_score"));
                storeMap.put("avgPrice", avgPriceMap.get(String.valueOf(store.getId())).get(0).get("avg_price"));
                // 条数
                storeMap.put("totalNum", avgScoreMap.get(String.valueOf(store.getId())).get(0).get("total_num"));*/
            } else {
                // 否则，设置默认值
                /*storeMap.put("avgScore", 0);
                storeMap.put("avgPrice", 0);
                storeMap.put("totalNum", 0);*/
                store.setAvgScore("0");
                store.setTotalNum("0");
            }
            if (avgPriceMap.containsKey(String.valueOf(store.getId()))) {
                store.setAvgPrice(avgPriceMap.get(String.valueOf(store.getId())).get(0).get("avg_price").toString());
            } else {
                store.setAvgPrice("0");
            }
            // 添加门店名称
            storeMap.put("storeName", store.getStoreName());
            // 添加门店地址
            storeMap.put("storeAddress", store.getStoreAddress());
            // 添加门店类型
            storeMap.put("storeType", store.getStoreType());
            // 添加门店入口图片
            storeMap.put("entranceImage", store.getEntranceImage());
            // 添加门店图片
            storeMap.put("storeImage", store.getImgUrl());
            // 解析并添加门店经纬度
            String[] position = store.getStorePosition().split(",");
            storeMap.put("longitude", position.length == 2 ? position[0] : "");
            storeMap.put("latitude", position.length == 2 ? position[1] : "");
            // 构造该门店的优惠券列表
            List<Map<String, Object>> quanMapList = new ArrayList<>();
            if (!quanList.isEmpty()) {
                for (LifeCoupon quan : quanList) {
                    // 如果优惠券的门店ID与当前门店ID匹配，则添加到优惠券列表中
                    if (store.getId().toString().equals(quan.getStoreId())) {
                        Map<String, Object> quanMap = new HashMap<>();
                        quanMap.put("quanType", quan.getType());
                        quanMap.put("name", quan.getName());
                        quanMap.put("price", quan.getPrice());
                        // 折扣价
                        quanMap.put("offprice", quan.getOffprice());
                        quanMap.put("quanId", quan.getId());
                        quanMapList.add(quanMap);
                    }
                }
                // 将优惠券列表添加到门店信息中
                storeMap.put("quanList", quanMapList);
                store.setQuanList(quanMapList);
            }

            // 构造该门店的团购套餐列表
            List<LifeGroupBuyMainVo> lifeGroupBuyMains = new ArrayList<>();
            if (!lifeGroupBuyMainList.isEmpty()) {
                for (LifeGroupBuyMain quan : lifeGroupBuyMainList) {
                    // 如果团购套餐的门店ID与当前门店ID匹配，则添加到团购列表中
                    if (store.getId().toString().equals(quan.getStoreId())) {
                        LifeGroupBuyMainVo lifeGroupBuyMainVo = new LifeGroupBuyMainVo();
                        BeanUtils.copyProperties(quan, lifeGroupBuyMainVo);
                        lifeGroupBuyMains.add(lifeGroupBuyMainVo);
                    }
                }
                // 将团购套餐列表添加到门店信息中
                storeMap.put("tuangouList", lifeGroupBuyMains);
                // 将团购套餐列表添加到门店信息中
                store.setTuangouList(lifeGroupBuyMains);
            }
            // 添加门店类型的描述
            storeMap.put("storeTypeStr", store.getStoreTypeStr());
            // 遍历打卡次数列表，找到当前门店的打卡次数并添加到门店信息中
            storeClockInCountList.forEach(b -> {
                Integer stId = b.get("storeId");
                if (Objects.equals(stId, store.getId())) {
                    storeMap.put("storeClockInCount", b.get("count"));
                    store.setStoreClockInCount(String.valueOf(b.get("count")));
                }
            });
            // 如果未找到打卡次数，则设置为0
            if (null == storeMap.get("storeClockInCount")) {
                storeMap.put("storeClockInCount", 0);
                store.setStoreClockInCount("0");
            }
            // 将当前门店的信息添加到返回结果列表中
//            returnMaps.add(storeMap);
        }

        return storeInfoIPage;
    }

    @Override
    public List<StoreInfo> getBusinessTypesName(String businessTypesNames) {
        String[] businessTypesName = businessTypesNames.split(",");
        List<StoreInfo> storeInfos = new ArrayList<>();
        for (String typesName : businessTypesName) {
            LambdaQueryWrapper<StoreInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.like(StoreInfo::getBusinessTypesName, typesName);
            List<StoreInfo> infos = storeInfoMapper.selectList(queryWrapper);
            storeInfos.addAll(infos);
        }
        return new ArrayList<>(storeInfos.stream().collect(Collectors.toMap(StoreInfo::getId, info -> info, (existing, replacement) -> existing)).values());
    }

    public static String findCommon(String... strings) {
        if (strings == null || strings.length == 0) {
            return "";
        }
        // 将第一个字符串拆分成集合
        Set<String> common = new HashSet<>(Arrays.asList(strings[0].split(",")));
        // 遍历其余字符串
        for (int i = 1; i < strings.length; i++) {
            Set<String> currentSet = new HashSet<>(Arrays.asList(strings[i].split(",")));
            // 找出共同元素
            common.retainAll(currentSet);
        }
        // 将共同元素集合转换为以逗号分隔的字符串
        return String.join(",", common);
    }

    /**
     * 检查并更新过期记录
     * 将过期时间已到且业务状态为0的店铺状态更新为99（过期状态）
     *
     * @return 更新的记录数
     */
    public int checkAndUpdateExpiredRecords() {
        LambdaUpdateWrapper<StoreInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.isNotNull(StoreInfo::getExpirationTime)
                .lt(StoreInfo::getExpirationTime, LocalDateTime.now())
                .eq(StoreInfo::getBusinessStatus, 0)
                .set(StoreInfo::getStoreStatus, 0);
        return storeInfoMapper.update(null, updateWrapper);
    }

    @Override
    public void logoutStore(StoreInfoVo storeInfo) {
        throw new IllegalArgumentException("店铺注销已合并至商家账号注销，请通过商家账号注销接口操作");
    }

    @Override
    public void cancelLogoutStore(StoreInfoVo storeInfo) {
        throw new IllegalArgumentException("店铺撤销注销已合并至商家账号注销，请通过商家账号撤销注销接口操作");
    }

    @Override
    public List<StoreInfo> getStoreInfoByStoreTel(String storeTel) {
        LambdaQueryWrapper<StoreInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StoreInfo::getStoreTel, storeTel);
        return storeInfoMapper.selectList(queryWrapper);
    }

    @Override
    public int editStoreCommissionRate(StoreInfoDto storeInfoDto) {
        LambdaUpdateWrapper<StoreInfo> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(StoreInfo::getId, storeInfoDto.getId());
        wrapper.set(StoreInfo::getCommissionRate, storeInfoDto.getCommissionRate());
        return storeInfoMapper.update(null, wrapper);
    }

    @Override
    public boolean saveOrUpdateTablewareFee(Integer storeId, Integer tablewareFee) {
        if (storeId == null) {
            throw new IllegalArgumentException("门店ID不能为空");
        }
        
        // 验证餐具费：限2位正整数（0-99）
        if (tablewareFee != null && (tablewareFee < 0 || tablewareFee > 99)) {
            throw new IllegalArgumentException("餐具费必须是0-99之间的整数");
        }
        
        LambdaUpdateWrapper<StoreInfo> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(StoreInfo::getId, storeId);
        wrapper.set(StoreInfo::getTablewareFee, tablewareFee);
        int result = storeInfoMapper.update(null, wrapper);
        return result > 0;
    }

    @Override
    public int saveOrUpdateStoreInfo(StoreInfoDto storeInfodto) {
        if (storeInfodto.getId() != null) {
            // 校验当前店铺存在未完成的订单及正在销售的商品
            verificationStoreInfoStatus(storeInfodto);

            // 1. 处理经营板块及经营种类（不再查询字典表，直接使用传入的名称）

            // 2. 构建StoreInfo对象
            StoreInfo storeInfo = new StoreInfo();
            BeanUtils.copyProperties(storeInfodto, storeInfo);

            // 3. 处理经纬度
            String longitude = storeInfodto.getStorePositionLongitude();
            String latitude = storeInfodto.getStorePositionLatitude();
            if (StringUtils.isEmpty(longitude) || StringUtils.isEmpty(latitude)) {
                // 经纬度为空时，复用原数据
                StoreInfo oldStore = storeInfoMapper.selectById(storeInfodto.getId());
                if (Objects.nonNull(oldStore)) {
                    storeInfo.setStorePosition(oldStore.getStorePosition());
                }
            } else {
                // 拼接经纬度
                storeInfo.setStorePosition(longitude + "," + latitude);
            }

            // 4. 设置门店状态、经营板块及类型
            storeInfo.setStoreStatus(storeInfodto.getStoreStatus());
            
            // 经营板块
            if (storeInfodto.getBusinessSection() != null) {
                storeInfo.setBusinessSection(storeInfodto.getBusinessSection());
            }
            if (StringUtils.isNotEmpty(storeInfodto.getBusinessSectionName())) {
                storeInfo.setBusinessSectionName(storeInfodto.getBusinessSectionName());
            }
            
            // 经营种类
            if (!CollectionUtils.isEmpty(storeInfodto.getBusinessTypes())) {
                storeInfo.setBusinessTypes(String.join(",", storeInfodto.getBusinessTypes()));
            }
            if (StringUtils.isNotEmpty(storeInfodto.getBusinessTypeName())) {
                storeInfo.setBusinessTypeName(storeInfodto.getBusinessTypeName());
            }
            
            // 经营类目
            if (StringUtils.isNotEmpty(storeInfodto.getBusinessCategoryName())) {
                storeInfo.setBusinessCategoryName(storeInfodto.getBusinessCategoryName());
            }
            
            // 店铺评价：直接使用传入的值（前端传入以逗号拼接的三个值：环境,卫生,口味）
            if (StringUtils.isNotEmpty(storeInfodto.getStoreEvaluate())) {
                storeInfo.setStoreEvaluate(storeInfodto.getStoreEvaluate());
            }

            // // 处理分类信息（已废弃，不再使用）
            // List<String> businessClassify = storeInfodto.getBusinessClassify();
            // if (!CollectionUtils.isEmpty(businessClassify)) {
            //     List<String> businessClassifyNames = new ArrayList<>();
            //     //批量查询分类名称
            //     List<StoreDictionary> classifyDicts = storeDictionaryMapper.selectList(
            //             new LambdaQueryWrapper<StoreDictionary>()
            //                     .in(StoreDictionary::getDictId, businessClassify)
            //                     .eq(StoreDictionary::getTypeName, "business_classify")
            //                     .eq(StoreDictionary::getDeleteFlag, 0)
            //     );
            //     //转为Map方便快速获取
            //     Map<String, StoreDictionary> classifyDictMap = classifyDicts.stream()
            //             .collect(Collectors.toMap(
            //                     dict -> dict.getDictId().toString(),
            //                     Function.identity(),
            //                     (existing, replacement) -> existing
            //             ));
            //     //提取分类名称
            //     for (String classifyId : businessClassify) {
            //         StoreDictionary dict = classifyDictMap.get(classifyId);
            //         if (Objects.nonNull(dict)) {
            //             businessClassifyNames.add(dict.getDictDetail());
            //         } else {
            //             log.warn("无效的分类id：" + classifyId);
            //         }
            //     }
            //     storeInfo.setBusinessClassify(String.join(",", businessClassify));
            //     storeInfo.setBusinessClassifyName(String.join(",", businessClassifyNames));
            // }

            // 5. 处理行政区域信息（抽取为方法，减少重复） 不存在单独查的情况
            if (!Objects.isNull(storeInfo.getAdministrativeRegionProvinceAdcode())) {

                storeInfo.setAdministrativeRegionProvinceName(
                        getAreaName(storeInfo.getAdministrativeRegionProvinceAdcode())
                );
                storeInfo.setAdministrativeRegionCityName(
                        getAreaName(storeInfo.getAdministrativeRegionCityAdcode())
                );
                storeInfo.setAdministrativeRegionDistrictName(
                        getAreaName(storeInfo.getAdministrativeRegionDistrictAdcode())
                );
            }

            // 5.5. 判断门店名称是否改变，如果改变则清空类型为20或21的图片
            StoreInfo oldStoreInfo = storeInfoMapper.selectById(storeInfodto.getId());
            if (Objects.nonNull(oldStoreInfo) && StringUtils.isNotEmpty(storeInfodto.getStoreName())) {
                String oldStoreName = oldStoreInfo.getStoreName();
                String newStoreName = storeInfodto.getStoreName();
                // 如果门店名称发生改变
                if (!Objects.equals(oldStoreName, newStoreName)) {
                    log.info("门店名称发生改变，清空类型为20或21的图片。门店ID：{}，旧名称：{}，新名称：{}", 
                            storeInfodto.getId(), oldStoreName, newStoreName);
                    // 删除该门店类型为20或21的图片
                    LambdaUpdateWrapper<StoreImg> imgUpdateWrapper = new LambdaUpdateWrapper<>();
                    imgUpdateWrapper.eq(StoreImg::getStoreId, storeInfodto.getId())
                            .in(StoreImg::getImgType, Arrays.asList(20, 21))
                            .set(StoreImg::getDeleteFlag, 1); // 逻辑删除
                    storeImgMapper.update(null, imgUpdateWrapper);
                }
            }

            // 6. 执行更新
            int updateNum = storeInfoMapper.updateById(storeInfo);

            // 7. 更新地理位置信息（处理经纬度解析异常）
            if (!StringUtils.isEmpty(longitude) && !StringUtils.isEmpty(latitude)) {
                try {
                    double lon = Double.parseDouble(longitude);
                    double lat = Double.parseDouble(latitude);
                    nearMeService.inGeolocation(new Point(lon, lat), storeInfo.getId().toString(), Boolean.TRUE);
                } catch (NumberFormatException e) {
                    log.error("经纬度解析失败：longitude=" + longitude + ", latitude=" + latitude);
                    // 可选：根据业务是否抛出异常，或忽略
                    // throw new IllegalArgumentException("经纬度格式错误", e);
                }
            }
            return updateNum;
        } else {
            StoreInfo storeInfo = new StoreInfo();
            BeanUtils.copyProperties(storeInfodto, storeInfo);
            int num = storeInfoMapper.insert(storeInfo);
            return num;
        }
    }

    // 抽取：根据区域编码查询区域名称（通用方法）
    private String getAreaName(String areaCode) {
        if (StringUtils.isEmpty(areaCode)) {
            return ""; // 或返回null，根据业务定义
        }
        try {
            Integer areaCodeInt = Integer.parseInt(areaCode);
            EssentialCityCode cityCode = essentialCityCodeMapper.selectOne(
                    new LambdaQueryWrapper<EssentialCityCode>().eq(EssentialCityCode::getAreaCode, areaCodeInt)
            );
            return Objects.nonNull(cityCode) ? cityCode.getAreaName() : "";
        } catch (NumberFormatException e) {
            log.error("区域编码格式错误：{}", areaCode, e);
            return "";
        }
    }

    @Override
    public Map<String, String> storeInfoVerification(int id) {
        Map<String, String> storeInfoMap = new HashMap<>();
        LambdaQueryWrapper<StoreInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StoreInfo::getId, id);
        StoreInfo storeInfo = storeInfoMapper.selectOne(queryWrapper);
//      当前时间 string类型的当前时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        String formattedDate = sdf.format(date);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_YEAR, -4);
        Date startDay = calendar.getTime();
        String startDayS = sdf.format(startDay);
        JSONObject jsonObject = storeIncomeDetailsRecordService.noYetPayment(id, 0, 0, startDayS, formattedDate, 1, 10);
        String moneyNew = jsonObject.getString("money");
        if (storeInfo != null) {
            Map<String, Object> map = storeIncomeDetailsRecordService.accountBalance(id);
            double balance = Double.parseDouble(map.get("balance").toString());
            double cashOutMoney = Double.parseDouble(map.get("cashOutMoney").toString());
            //判断店铺存在未体现金额 0：未通过 1：通过
//            StoreUser storeUser = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, id));
            if (balance >= 0.1 || cashOutMoney >= 0.1 || !"0.00".equals(moneyNew)) {
                storeInfoMap.put("storeMoneyStatus", "0");
            } else {
                storeInfoMap.put("storeMoneyStatus", "1");
            }
            //判断店铺存在未完成订单 0：未通过 1：通过
//            List<LifeUserOrder> lifeUserOrders = lifeUserOrderMapper.selectList(new LambdaQueryWrapper<LifeUserOrder>().in(LifeUserOrder::getStatus, 0, 1).eq(LifeUserOrder::getStoreId, id).eq(LifeUserOrder::getDeleteFlag, 0));
//            if (!CollectionUtils.isEmpty(lifeUserOrders)) {
//                storeInfoMap.put("storeOrderStatus", "0");
//            } else {
//                storeInfoMap.put("storeOrderStatus", "1");
//            }
            //判断店铺存在正在售卖的商品 0：未通过 1：通过  storeGoodsStatus 代金券   storeGroupStatus 团购
            List<LifeGroupBuyMain> lifeGroupBuyMainList = lifeGroupBuyMainMapper.selectList(new LambdaQueryWrapper<LifeGroupBuyMain>().eq(LifeGroupBuyMain::getStoreId, id).eq(LifeGroupBuyMain::getStatus, 5).eq(LifeGroupBuyMain::getDeleteFlag, 0));
            List<LifeCoupon> lifeCoupons = lifeCouponMapper.selectList(new LambdaQueryWrapper<LifeCoupon>().in(LifeCoupon::getStatus, 5).and(qw -> qw.gt(LifeCoupon::getSingleQty, 0)).eq(LifeCoupon::getStoreId, id).eq(LifeCoupon::getType, 1).eq(LifeCoupon::getDeleteFlag, 0));
            if (!CollectionUtils.isEmpty(lifeCoupons)) {
                storeInfoMap.put("storeGoodsStatus", "0");
            } else {
                storeInfoMap.put("storeGoodsStatus", "1");
            }
            if (!CollectionUtils.isEmpty(lifeGroupBuyMainList)) {
                storeInfoMap.put("storeGroupStatus", "0");
            } else {
                storeInfoMap.put("storeGroupStatus", "1");
            }

        }
        return storeInfoMap;
    }

    @Override
    public void deleteManualStoreInfo(int id) {
        LambdaQueryWrapper<StoreInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StoreInfo::getId, id);
        StoreInfo storeInfo = storeInfoMapper.selectOne(queryWrapper);
        if (storeInfo != null && storeInfo.getStoreStatus() == -1) {
            storeInfoMapper.deleteById(id);
            StoreUser storeUser = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, id));
            if (storeUser != null) {
                UpdateWrapper<StoreUser> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("id", storeUser.getId());
                updateWrapper.set("store_id", null);
                storeUserMapper.update(null, updateWrapper);
            }
        }
    }

    @Override
    public int uploadRenewalContract(List<StoreImg> storeImgList) {
        //取出集合中门店id
        Optional<Integer> storeId = storeImgList.stream().map(StoreImg::getStoreId).findFirst();
        int value = storeId.orElse(0);
        int num = 0;
        //先清除数据
        storeImgMapper.delete(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 22).eq(StoreImg::getStoreId, value));
        for (StoreImg renewContract : storeImgList) {
            StoreImg storeImg = new StoreImg();
            storeImg.setStoreId(renewContract.getStoreId());
            storeImg.setImgType(22);
            storeImg.setImgSort(renewContract.getImgSort());
            storeImg.setImgDescription("续签合同图片");
            storeImg.setImgUrl(renewContract.getImgUrl());
            storeImg.setCreatedUserId(renewContract.getCreatedUserId());
            num = storeImgMapper.insert(storeImg);
        }
        if (num > 0) {
            StoreInfo storeInfo = new StoreInfo();
            storeInfo.setRenewContractStatus(2);
            storeInfo.setUpdateRenewContractTime(new Date());
            storeInfo.setId(value);
            storeInfoMapper.updateById(storeInfo);
        }
        return num;
    }

    @Override
    public int uploadfoodLicence(StoreImg storeImg) {
        storeImgMapper.delete(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 24).eq(StoreImg::getStoreId, storeImg.getStoreId()));
        storeImg.setImgType(24);
        storeImg.setImgDescription("经营许可证审核通过前图片");
        storeImgMapper.insert(storeImg);

        // 经营许可证历史表插入
        StoreLicenseHistory licenseHistory = new StoreLicenseHistory();
        licenseHistory.setStoreId(storeImg.getStoreId());
        licenseHistory.setLicenseStatus(2);
        licenseHistory.setLicenseExecuteStatus(2);
        licenseHistory.setImgUrl(storeImg.getImgUrl());
        licenseHistory.setDeleteFlag(0);
        licenseHistoryMapper.insert(licenseHistory);

        //更新店铺
        StoreInfo storeInfo = new StoreInfo();
        storeInfo.setFoodLicenceStatus(2);
        storeInfo.setId(storeImg.getStoreId());
        storeInfo.setUpdateFoodLicenceTime(new Date());

        // 从OCR识别记录中获取食品经营许可证到期时间
        if (StringUtils.isNotEmpty(storeImg.getImgUrl())) {
            OcrImageUpload foodLicenceOcr = ocrImageUploadMapper.selectOne(
                    new LambdaQueryWrapper<OcrImageUpload>()
                            .eq(OcrImageUpload::getImageUrl, storeImg.getImgUrl())
                            .eq(OcrImageUpload::getOcrType, OcrTypeEnum.FOOD_MANAGE_LICENSE.getCode())
                            .orderByDesc(OcrImageUpload::getCreateTime)
                            .last("limit 1")
            );
            if (foodLicenceOcr != null && StringUtils.isNotEmpty(foodLicenceOcr.getOcrResult())) {
                try {
                    com.alibaba.fastjson2.JSONObject ocrResult = com.alibaba.fastjson2.JSONObject.parseObject(foodLicenceOcr.getOcrResult());
                    // 解析食品经营许可证到期时间（优先validToDate，其次standardizedValidToDate）
                    Date expirationTime = parseFoodLicenceExpirationDate(ocrResult);
                    if (expirationTime != null) {
                        storeInfo.setFoodLicenceExpirationTime(expirationTime);
                        log.info("食品经营许可证OCR数据解析成功，门店ID：{}，到期时间：{}", storeImg.getStoreId(), expirationTime);
                    }
                } catch (Exception e) {
                    log.error("解析食品经营许可证OCR数据失败，门店ID：{}", storeImg.getStoreId(), e);
                }
            }
        }

        return storeInfoMapper.updateById(storeInfo);
    }

    @Override
    public Map<String, Object> getStoreContractStatus(int id) {
        Map<String, Object> map = new HashMap<>();
        StoreInfo storeInfo = storeInfoMapper.selectOne(new LambdaQueryWrapper<StoreInfo>().eq(StoreInfo::getId, id));
        //审核通过给前台反显未提交
        if (storeInfo.getRenewContractStatus() == 1) {
            map.put("renewContractStatus", 0);
        } else {
            map.put("renewContractStatus", storeInfo.getRenewContractStatus());
        }
        //续签合同照片列表
        List<StoreImg> storeImgList = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 22).eq(StoreImg::getStoreId, id));
        if (!CollectionUtils.isEmpty(storeImgList)) {
            map.put("contractImgList", storeImgList);
        } else {
            map.put("contractImgList", "");
        }
        if (storeInfo.getContractReason() != null) {
            map.put("contractReason", storeInfo.getContractReason());
        } else {
            map.put("contractReason", "");
        }
        return map;
    }

    @Override
    public Map<String, Object> getStoreFoodLicenceStatus(int id) {
        Map<String, Object> map = new HashMap<>();
        StoreInfo storeInfo = storeInfoMapper.selectOne(new LambdaQueryWrapper<StoreInfo>().eq(StoreInfo::getId, id));
        //审核通过给前台反显未提交
        if (storeInfo.getFoodLicenceStatus() == 1) {
            map.put("foodLicenceStatus", 0);
        } else {
            map.put("foodLicenceStatus", storeInfo.getFoodLicenceStatus());
        }
        //食品经营许可证照片列表
        List<StoreImg> storeImgList = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 24).eq(StoreImg::getStoreId, id));
        if (!CollectionUtils.isEmpty(storeImgList)) {
            map.put("foodLicenceImgList", storeImgList);
        } else {
            map.put("foodLicenceImgList", "");
        }
        if (storeInfo.getFoodLicenceReason() != null) {
            map.put("foodLicenceReason", storeInfo.getFoodLicenceReason());
        } else {
            map.put("foodLicenceReason", "");
        }
        return map;
    }

    @Override
    public int conversionContract(int id) {
        //删除原合同照片
        LambdaQueryWrapper<StoreImg> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StoreImg::getStoreId, id);
        lambdaQueryWrapper.eq(StoreImg::getImgType, 15);
        storeImgMapper.delete(lambdaQueryWrapper);
        //修改续签合同类型为合同类型
        List<StoreImg> storeImgList = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, id).eq(StoreImg::getImgType, 22));
        List<Integer> imgList = storeImgList.stream().map(StoreImg::getId).collect(Collectors.toList());
        LambdaUpdateWrapper<StoreImg> lambdaUpdateWrapper = new LambdaUpdateWrapper();
        lambdaUpdateWrapper.in(StoreImg::getId, imgList).set(StoreImg::getImgType, 15).set(StoreImg::getImgDescription, "合同图片");
        int num = storeImgMapper.update(null, lambdaUpdateWrapper);
        return num;
    }

    @Override
    public int foodLicenceType(int id) {

        List<StoreImg> storeImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, id)
                .eq(StoreImg::getImgType,25)
                .orderByDesc(StoreImg::getCreatedTime));

        List<Integer> deleteIds = storeImgs.stream()
                .skip(1) // 跳过最新的第一条
                .map(StoreImg::getId) // 替换为你的主键字段（如imgId）
                .collect(Collectors.toList());

        if(deleteIds!=null && deleteIds.size()>0){
            storeImgMapper.deleteBatchIds(deleteIds);
        }

//        //修改续签合同类型为合同类型
//        List<StoreImg> storeImgList = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, id).eq(StoreImg::getImgType, 25));
//        List<Integer> imgList = storeImgList.stream().map(StoreImg::getId).collect(Collectors.toList());
//        LambdaUpdateWrapper<StoreImg> imgLambdaUpdateWrapper = new LambdaUpdateWrapper();
//        imgLambdaUpdateWrapper.in(StoreImg::getId, imgList).set(StoreImg::getImgType, 25).set(StoreImg::getImgDescription, "经营许可证图片");
//        int num = storeImgMapper.update(null, imgLambdaUpdateWrapper);


        // 将原来的食品经营许可证历史表数据删除
//        LambdaUpdateWrapper<StoreLicenseHistory> wrapper = new LambdaUpdateWrapper<>();
//        wrapper.eq(StoreLicenseHistory::getStoreId, id);
//        wrapper.eq(StoreLicenseHistory::getLicenseStatus, 2);
//        wrapper.eq(StoreLicenseHistory::getLicenseExecuteStatus, 1);
//        wrapper.eq(StoreLicenseHistory::getDeleteFlag, 0);
//        wrapper.set(StoreLicenseHistory::getDeleteFlag, 1);
//        licenseHistoryMapper.update(null, wrapper);

        // 将新的食品经营许可证历史表数据变为审核通过
        LambdaUpdateWrapper<StoreLicenseHistory> wrapper1 = new LambdaUpdateWrapper<>();
        wrapper1.eq(StoreLicenseHistory::getStoreId, id);
        wrapper1.eq(StoreLicenseHistory::getLicenseStatus, 2);
        wrapper1.eq(StoreLicenseHistory::getLicenseExecuteStatus, 2);
        wrapper1.eq(StoreLicenseHistory::getDeleteFlag, 0);
        wrapper1.set(StoreLicenseHistory::getLicenseExecuteStatus, 1);
        int num = licenseHistoryMapper.update(null, wrapper1);

        return num;
    }

    void verificationStoreInfoStatus(StoreInfoDto storeInfo) {
        //营业状态 0:正常营业, 1:暂停营业, 2:筹建中, 99:永久关门
        if (storeInfo.getBusinessStatus() == 99) {
            //判断店铺有未完成的订单
            List<LifeUserOrder> lifeUserOrders = lifeUserOrderMapper.selectList(new LambdaQueryWrapper<LifeUserOrder>().in(LifeUserOrder::getStatus, 0, 3).eq(LifeUserOrder::getStoreId, storeInfo.getId()).eq(LifeUserOrder::getDeleteFlag, 0));
            if (!CollectionUtils.isEmpty(lifeUserOrders)) {
                throw new RuntimeException("店铺有未完成的订单");
            }
            //判断店铺有正在售卖的商品
            List<LifeGroupBuyMain> lifeGroupBuyMainList = lifeGroupBuyMainMapper.selectList(new LambdaQueryWrapper<LifeGroupBuyMain>().eq(LifeGroupBuyMain::getStoreId, storeInfo.getId()).eq(LifeGroupBuyMain::getStatus, 5).eq(LifeGroupBuyMain::getDeleteFlag, 0));
            List<LifeCoupon> lifeCoupons = lifeCouponMapper.selectList(new LambdaQueryWrapper<LifeCoupon>().in(LifeCoupon::getStatus, 0, 1).and(qw -> qw.gt(LifeCoupon::getStockQty, 0).or().gt(LifeCoupon::getSingleQty, 0)).eq(LifeCoupon::getStoreId, storeInfo.getId()).eq(LifeCoupon::getType, 1).eq(LifeCoupon::getDeleteFlag, 0));
            if (!CollectionUtils.isEmpty(lifeCoupons) || !CollectionUtils.isEmpty(lifeGroupBuyMainList)) {
                throw new RuntimeException("店铺有正在销售的商品");
            }
        }
    }

    public int updateStoreImgModeInfo(StoreImgInfoVo storeImgInfoVo) {
        int result = 0;
        if (storeImgInfoVo != null) {
            // 校验必要参数是否为null
            if (storeImgInfoVo.getStoreId() == null || storeImgInfoVo.getImgMode() == null) {
                return result;
            }
            int imgType = storeImgInfoVo.getImgType();
            if (imgType == GroupConstant.IMG_TYPE_SINGLE_MODE || imgType == GroupConstant.IMG_TYPE_MULTI_MODE||imgType==4) {
                LambdaUpdateWrapper<StoreInfo> wrapper = new LambdaUpdateWrapper<>();
                wrapper.eq(StoreInfo::getId, storeImgInfoVo.getStoreId());
                wrapper.set(StoreInfo::getImgMode, storeImgInfoVo.getImgMode());
                result = storeInfoMapper.update(null, wrapper);
            }
        }
        return result;
    }

    public void updateLicenseHistoryInfo(Integer storeId, Integer foodLicenceStatus) {
        if (foodLicenceStatus == 3) {
            // 审核拒绝时修改提交记录
            LambdaUpdateWrapper<StoreLicenseHistory> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(StoreLicenseHistory::getStoreId, storeId);
            wrapper.eq(StoreLicenseHistory::getLicenseStatus, 1);
            wrapper.eq(StoreLicenseHistory::getLicenseExecuteStatus, 2);
            wrapper.set(StoreLicenseHistory::getLicenseExecuteStatus, 3);
            wrapper.set(StoreLicenseHistory::getReasonRefusal, storeId);
            wrapper.set(StoreLicenseHistory::getDeleteFlag, 1);
            licenseHistoryMapper.update(null, wrapper);
        } else {
            // 将原来的食品经营许可证历史表数据删除
            LambdaUpdateWrapper<StoreLicenseHistory> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(StoreLicenseHistory::getStoreId, storeId);
            wrapper.eq(StoreLicenseHistory::getLicenseStatus, 1);
            wrapper.eq(StoreLicenseHistory::getLicenseExecuteStatus, 1);
            wrapper.eq(StoreLicenseHistory::getDeleteFlag, 0);
            wrapper.set(StoreLicenseHistory::getDeleteFlag, 1);
            licenseHistoryMapper.update(null, wrapper);

            // 将新的食品经营许可证历史表数据变为审核通过
            LambdaUpdateWrapper<StoreLicenseHistory> wrapper1 = new LambdaUpdateWrapper<>();
            wrapper1.eq(StoreLicenseHistory::getStoreId, storeId);
            wrapper1.eq(StoreLicenseHistory::getLicenseStatus, 1);
            wrapper1.eq(StoreLicenseHistory::getLicenseExecuteStatus, 2);
            wrapper1.eq(StoreLicenseHistory::getDeleteFlag, 0);
            wrapper1.set(StoreLicenseHistory::getLicenseExecuteStatus, 1);
            licenseHistoryMapper.update(null, wrapper1);
        }
    }

    @Override
    public AiApproveStoreInfoResultVo aiApproveStoreInfo(AiApproveStoreInfo aiApproveStoreInfo) {
        HttpHeaders aiHeaders = new HttpHeaders();
        aiHeaders.setContentType(MediaType.APPLICATION_JSON);
        aiHeaders.set("Authorization", "Bearer " + aiAuthTokenUtil.getAccessToken());

        HttpEntity<AiApproveStoreInfo> request = new HttpEntity<>(aiApproveStoreInfo, aiHeaders);
        ResponseEntity<String> response = null;
        try {
            response = restTemplate.postForEntity(applicationsPath, request, String.class);
            if (response.getStatusCodeValue() != 200) {
                throw new RuntimeException("AI门店审核接口调用失败 http状态：" + response.getStatusCode());
            }
            if (StringUtils.isNotEmpty(response.getBody())) {
                JSONObject jsonObject = JSONObject.parseObject(response.getBody());
                if (Integer.valueOf(200).equals(jsonObject.getInteger("code"))) {
                    JSONObject data = jsonObject.getJSONObject("data");
                    if (data == null) {
                        log.info("AI门店审核接口返回 data 为空, userId={}", aiApproveStoreInfo.getUserId());
                        throw new RuntimeException("AI门店审核接口返回 data 为空");
                    }
                    String registrationNo = data.getString("registration_no");
                    if (StringUtils.isEmpty(registrationNo)) {
                        registrationNo = data.getString("registrationNo");
                    }
                    List<StoreInfo> storeInfos = storeInfoMapper.selectList(new LambdaQueryWrapper<StoreInfo>()
                            .eq(StoreInfo::getCreatedUserId, aiApproveStoreInfo.getUserId()).eq(StoreInfo::getStoreApplicationStatus, 0).eq(StoreInfo::getDeleteFlag, 0));
                    String status = data.getString("status");
                    for (StoreInfo storeInfo : storeInfos) {
                        if ("approved".equals(status)) {
                            log.info("AI门店审核通过, storeId={}", storeInfo.getId());
                            approveStoreInfo(storeInfo.getId().toString(), 1, "审核通过");
                        } else if ("rejected".equals(status)) {
                            log.info("AI门店审核拒绝, storeId={}", storeInfo.getId());
                            String reason = data.getString("audit_summary");
                            if (StringUtils.isEmpty(reason) && data.containsKey("risk_tags")) {
                                log.info("AI门店审核拒绝, risk_tags 不为空, storeId={}", storeInfo.getId());
                                JSONArray riskTags = data.getJSONArray("risk_tags");
                                if (riskTags != null && !riskTags.isEmpty()) {
                                    StringBuilder sb = new StringBuilder();
                                    for (int i = 0; i < riskTags.size(); i++) {
                                        if (i > 0) sb.append("；");
                                        sb.append(riskTags.getString(i));
                                    }
                                    reason = sb.toString();
                                }
                            }
                            approveStoreInfo(storeInfo.getId().toString(), 2, StringUtils.isNotEmpty(reason) ? reason : "审核未通过");
                        } else {
                            log.warn("AI门店审核返回未知状态: status={}, storeId={}", status, storeInfo.getId());
                        }
                    }
                    AiApproveStoreInfoResultVo resultVo = new AiApproveStoreInfoResultVo();
                    resultVo.setRegistrationNo(registrationNo);
                    return resultVo;
                } else {
                    log.error("AI门店审核接口调用失败, userId={}, code={}", aiApproveStoreInfo.getUserId(), jsonObject.getInteger("code"));
                    throw new RuntimeException("AI门店审核接口调用失败 code：" + jsonObject.getInteger("code"));
                }
            }
        } catch (Exception e) {
            log.error("调用门店审核接口异常, userId={},{}", aiApproveStoreInfo.getUserId(), e);
            throw new RuntimeException("调用门店审核接口异常", e);
        }
        return new AiApproveStoreInfoResultVo();
    }

    @Override
    public Map<String, Object> getStoreOcrData(String imageUrl, String merchantName) {
        Map<String, Object> map = new HashMap<>();
        String accessToken = aiAuthTokenUtil.getAccessToken();

        HttpHeaders aiHeaders = new HttpHeaders();
        aiHeaders.setContentType(MediaType.APPLICATION_JSON);
        aiHeaders.set("Authorization", "Bearer " + accessToken);
        Map<String, Object> jsonBody = new HashMap<>();
        List<String> imageUrls = new ArrayList<>();
        imageUrls.add(imageUrl);
        jsonBody.put("image_urls", imageUrls);
        jsonBody.put("merchant_name", merchantName);

        HttpEntity<Map<String, Object>> request = new HttpEntity<>(jsonBody, aiHeaders);
        ResponseEntity<String> response = null;
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setConnectTimeout(5000);
        factory.setReadTimeout(60000);
        restTemplate.setRequestFactory(factory);
        try {
            response = restTemplate.postForEntity(identificationPath, request, String.class);
            if (response.getStatusCodeValue() != 200) {
                throw new RuntimeException("AI内容审核接口调用失败 http状态：" + response.getStatusCode());
            }

        } catch (Exception e) {
            throw new RuntimeException("AI接口调用失败");
        }
        com.alibaba.fastjson2.JSONObject responseNode = com.alibaba.fastjson2.JSONObject.parseObject(response.getBody());
        if (responseNode == null) {
            throw new RuntimeException("AI接口调用失败，响应内容为空");
        } else {
            Integer code = responseNode.getInteger("code");
            if (code == 200) {
                Map<String, Object> dataMap = (Map<String, Object>) responseNode.get("data");
                if (Objects.nonNull(dataMap)) {
                    // 获取match_results（JSON中是数组，反序列化为List<Map>）
                    List<Map<String, Object>> matchResults = (List<Map<String, Object>>) dataMap.get("match_results");
                    map.put("overall_match", dataMap.get("overall_match"));
                    if (Objects.nonNull(matchResults) && !matchResults.isEmpty()) {
                        map.put("match_reason", matchResults.get(0).get("match_reason"));

                        //根据url查询表中图片信息
//                        LambdaQueryWrapper<StoreImg> eq = new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 20).eq(StoreImg::getImgUrl, imageUrl);
//                        StoreImg storeImg = storeImgMapper.selectOne(eq);
//                        storeImg.setImgStatus("true".equals(matchResults.get(0).get("overall_match"))?1:2);
                    }
                }
            } else {
                throw new RuntimeException("AI接口调用失败，错误码: " + code);
            }
        }
        return map;
    }

    /**
     * 头图上传后AI审核并更新审核状态
     * 流程：上传头图 → 调用AI门头识别接口 → 根据结果更新head_img_status → 保存到store_img表
     *
     * @param storeImgInfoVo 图片信息VO
     * @return 审核结果 true-审核通过，false-审核不通过
     */
    @Override
    public boolean auditHeadImageAndUpdateStatus(StoreImgInfoVo storeImgInfoVo) {
        // 判断是否是头图（20:单图模式, 21:多图模式）
        Integer imgType = storeImgInfoVo.getImgType();
        if (imgType == null || (imgType != GroupConstant.IMG_TYPE_SINGLE_MODE && imgType != GroupConstant.IMG_TYPE_MULTI_MODE)) {
            // 不是头图，不需要审核，直接返回true
            return true;
        }

        List<StoreImg> storeImgList = storeImgInfoVo.getStoreImgList();
        if (storeImgList == null || storeImgList.isEmpty()) {
            // 没有图片，设置审核状态为不通过
            updateHeadImgStatus(storeImgInfoVo.getStoreId(), 2);
            return false;
        }

        // 获取第一张头图的URL（头图可能有多张，取第一张进行审核）
        StoreImg firstHeadImg = storeImgList.get(0);
        String imageUrl = firstHeadImg.getImgUrl();
        if (imageUrl == null || imageUrl.trim().isEmpty()) {
            // 图片URL为空，设置审核状态为不通过
            updateHeadImgStatus(storeImgInfoVo.getStoreId(), 2);
            return false;
        }

        // 获取门店信息（需要门店名称用于AI审核）
        StoreInfo storeInfo = storeInfoMapper.selectById(storeImgInfoVo.getStoreId());
        if (storeInfo == null) {
            log.error("门店不存在，storeId={}", storeImgInfoVo.getStoreId());
            updateHeadImgStatus(storeImgInfoVo.getStoreId(), 2);
            return false;
        }

        String merchantName = storeInfo.getStoreName();
        if (merchantName == null || merchantName.trim().isEmpty()) {
            log.error("门店名称为空，storeId={}", storeImgInfoVo.getStoreId());
            updateHeadImgStatus(storeImgInfoVo.getStoreId(), 2);
            return false;
        }

        try {
            // 调用AI门头识别接口进行审核
            Map<String, Object> ocrData = getStoreOcrData(imageUrl, merchantName);
            Boolean overallMatch = (Boolean) ocrData.get("overall_match");

            // 根据AI审核结果更新head_img_status
            // overall_match = true -> 审核通过 -> head_img_status = 1（保持通过状态）
            // overall_match = false -> 审核不通过 -> head_img_status = 2（改为不通过）
            if (overallMatch != null && overallMatch) {
                // AI审核通过，保持审核通过状态（1）
                updateHeadImgStatus(storeImgInfoVo.getStoreId(), 1);
                log.info("头图AI审核通过，storeId={}, imageUrl={}, headImgStatus=1",
                        storeImgInfoVo.getStoreId(), imageUrl);
                return true;
            } else {
                // AI审核不通过，更新为不通过状态（2）
                updateHeadImgStatus(storeImgInfoVo.getStoreId(), 2);
                log.info("头图AI审核不通过，storeId={}, imageUrl={}, overallMatch={}, headImgStatus=2",
                        storeImgInfoVo.getStoreId(), imageUrl, overallMatch);
                return false;
            }
        } catch (Exception e) {
            log.error("头图AI审核失败，storeId={}, imageUrl={}, error={}",
                    storeImgInfoVo.getStoreId(), imageUrl, e.getMessage(), e);
            // AI审核失败，设置审核状态为不通过
            updateHeadImgStatus(storeImgInfoVo.getStoreId(), 2);
            return false;
        }
    }

    /**
     * 更新门店头图审核状态
     *
     * @param storeId 门店ID
     * @param headImgStatus 审核状态 1-审核通过，2-审核不通过
     */
    @Override
    public void updateHeadImgStatus(Integer storeId, Integer headImgStatus) {
        LambdaUpdateWrapper<StoreInfo> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(StoreInfo::getId, storeId);
        wrapper.set(StoreInfo::getHeadImgStatus, headImgStatus);
        storeInfoMapper.update(null, wrapper);
        log.info("更新门店头图审核状态，storeId={}, headImgStatus={}", storeId, headImgStatus);
    }

    @Override
    public boolean manualReviewReport(Integer reportId, Integer type) {
        LifeUserViolation lifeUserViolation = lifeUserViolationMapper.selectById(reportId);
        lifeUserViolation.setProcessingStatus(type.toString());
        int i = lifeUserViolationMapper.updateById(lifeUserViolation);
        return i > 0 ;
    }

    /**
     * 获取活动banner图
     * 关联查询 store_img 和 store_operational_activity 表
     * 关联条件：store_operational_activity.id = store_img.business_id
     */
    public List<StoreImg> getBannerUrl(String storeId) {
        // 先查询符合条件的运营活动（包含未开始/已售罄/进行中/已结束）
        LambdaQueryWrapper<StoreOperationalActivity> activityWrapper = new LambdaQueryWrapper<StoreOperationalActivity>()
                .eq(StoreOperationalActivity::getStoreId, Integer.parseInt(storeId))
                .eq(StoreOperationalActivity::getDeleteFlag, 0)
                .in(StoreOperationalActivity::getStatus, 2, 5);
        List<StoreOperationalActivity> activities = storeOperationalActivityMapper.selectList(activityWrapper);

        // 如果没有活动，返回空列表
        if (CollectionUtils.isEmpty(activities)) {
            return new ArrayList<>();
        }

        // 过滤活动：MARKETING 且报名未开始的不展示
        Date now = new Date();
        List<StoreOperationalActivity> filteredActivities = activities.stream()
                .filter(activity -> {
                    if (activity == null) {
                        return false;
                    }
                    Integer status = activity.getStatus();
                    String activityType = activity.getActivityType();
                    if (!"MARKETING".equals(activityType)) {
                        // 非MARKETING且未开始，不展示
                        return status == null || status != 2;
                    }
                    if (status == null || (status != 2 && status != 5)) {
                        return false;
                    }
                    Date signupStartTime = activity.getSignupStartTime();
                    return signupStartTime == null || !now.before(signupStartTime);
                })
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(filteredActivities)) {
            return new ArrayList<>();
        }

        // 获取活动ID列表
        List<Integer> activityIds = filteredActivities.stream()
                .map(StoreOperationalActivity::getId)
                .collect(Collectors.toList());

        // 查询与活动关联的图片
        LambdaQueryWrapper<StoreImg> queryWrapper = new LambdaQueryWrapper<StoreImg>()
                .eq(StoreImg::getStoreId, Integer.parseInt(storeId))
                .eq(StoreImg::getImgType, 26)
                .eq(StoreImg::getDeleteFlag, 0)
                .in(StoreImg::getBusinessId, activityIds);
        List<StoreImg> storeImgs = storeImgMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(storeImgs)) {
            return storeImgs;
        }

        // 活动类型映射到图片返回值
        Map<Integer, String> activityTypeMap = filteredActivities.stream()
                .collect(Collectors.toMap(StoreOperationalActivity::getId,
                        activity -> activity.getActivityType() == null ? "" : activity.getActivityType(),
                        (a, b) -> a));
        for (StoreImg storeImg : storeImgs) {
            if (storeImg == null || storeImg.getBusinessId() == null) {
                continue;
            }
            storeImg.setActivityType(activityTypeMap.get(storeImg.getBusinessId()));
        }
        return storeImgs;
    }


    /**
     * 获取活动详情banner图
     */

    public List<StoreImg> getBannerUrlInfo(String storeId, Integer businessId) {
        LambdaQueryWrapper<StoreImg> queryWrapper = new LambdaQueryWrapper<StoreImg>()
                .eq(StoreImg::getStoreId, Integer.parseInt(storeId))
                .eq(StoreImg::getImgType, 27)
                .eq(StoreImg::getDeleteFlag, 0)
                .eq(StoreImg::getBusinessId, businessId);
        return storeImgMapper.selectList(queryWrapper);
    }


    @Override
    public IPage<StoreInfoVo> getLifeServicesByDistance(Double lon, Double lat, Double distance, Integer sortType, Integer businessType, Integer categoryId, String storeName, int pageNum, int pageSize) {
        // 参数校验
        if (lon == null || lat == null) {
            throw new IllegalArgumentException("经纬度参数不能为空");
        }
        
        // 智能检测：如果参数可能传反了（lat超出范围但lon在范围内），给出提示
        if (Math.abs(lat) > 90 && Math.abs(lon) <= 90) {
            throw new IllegalArgumentException(
                    String.format("参数可能传反了！当前值: lon=%s, lat=%s。经度范围: [-180, 180]，纬度范围: [-90, 90]。请检查参数顺序。", lon, lat)
            );
        }
        
        // 校验经纬度范围：经度 [-180, 180]，纬度 [-90, 90]
        if (lon < -180 || lon > 180) {
            throw new IllegalArgumentException("经度参数超出有效范围 [-180, 180]，当前值: " + lon);
        }
        if (lat < -90 || lat > 90) {
            throw new IllegalArgumentException("纬度参数超出有效范围 [-90, 90]，当前值: " + lat);
        }
        final int finalSortType = (sortType == null || sortType < 1 || sortType > 3) ? 1 : sortType; // 默认智能排序
        if (pageNum <= 0) {
            pageNum = 1;
        }
        if (pageSize <= 0) {
            pageSize = 10;
        }

        // 构建查询条件
        QueryWrapper<StoreInfoVo> queryWrapper = new QueryWrapper<>();

        // 如果传入了dictId，根据字典id查询经营板块、经营种类、分类并匹配店铺
        if (categoryId != null) {
            // 根据categoryId查询字典表记录
            StoreDictionary dict = storeDictionaryMapper.selectById(categoryId);
            if (dict == null || dict.getDeleteFlag() == 1) {
                throw new IllegalArgumentException("字典id不存在或已删除: " + categoryId);
            }

            String typeName = dict.getTypeName();
            String dictIdStr = dict.getDictId();

            if ("business_section".equals(typeName)) {
                // 如果是经营板块，直接匹配business_section
                try {
                    Integer sectionId = Integer.parseInt(dictIdStr);
                    queryWrapper.eq("a.business_section", sectionId);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("经营板块dictId格式错误: " + dictIdStr);
                }
            } else if ("business_type".equals(typeName)) {
                // 如果是经营种类，需要：
                // 1. 向上查找父级（经营板块）
                // 2. 匹配business_section和business_types
                StoreDictionary parentDict = storeDictionaryMapper.selectById(dict.getParentId());
                if (parentDict == null || !"business_section".equals(parentDict.getTypeName())) {
                    throw new IllegalArgumentException("经营种类的父级不是经营板块，categoryId: " + categoryId);
                }

                try {
                    Integer sectionId = Integer.parseInt(parentDict.getDictId());
                    queryWrapper.eq("a.business_section", sectionId);
                    // 使用FIND_IN_SET匹配business_types字段（逗号分隔）
                    queryWrapper.apply("FIND_IN_SET({0}, a.business_types) > 0", dictIdStr);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("经营板块或经营种类dictId格式错误");
                }
            } else if ("business_classify".equals(typeName)) {
                // 如果是分类，需要：
                // 1. 向上查找父级（经营种类）
                // 2. 向上查找祖父级（经营板块）
                // 3. 匹配business_section、business_types和business_classify
                StoreDictionary parentDict = storeDictionaryMapper.selectById(dict.getParentId());
                if (parentDict == null || !"business_type".equals(parentDict.getTypeName())) {
                    throw new IllegalArgumentException("分类的父级不是经营种类，categoryId: " + categoryId);
                }

                StoreDictionary grandParentDict = storeDictionaryMapper.selectById(parentDict.getParentId());
                if (grandParentDict == null || !"business_section".equals(grandParentDict.getTypeName())) {
                    throw new IllegalArgumentException("经营种类的父级不是经营板块，categoryId: " + categoryId);
                }

                try {
                    Integer sectionId = Integer.parseInt(grandParentDict.getDictId());
                    queryWrapper.eq("a.business_section", sectionId);
                    // 使用FIND_IN_SET匹配business_types字段
                    queryWrapper.apply("FIND_IN_SET({0}, a.business_types) > 0", parentDict.getDictId());
                    // 使用FIND_IN_SET匹配business_classify字段
                    queryWrapper.apply("FIND_IN_SET({0}, a.business_classify) > 0", dictIdStr);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("经营板块、经营种类或分类dictId格式错误");
                }
            } else {
                throw new IllegalArgumentException("不支持的字典类型: " + typeName + ", categoryId: " + categoryId);
            }
        } else if (businessType != null) {
            // 如果指定了businessType，则根据传入的数值进行筛选
            // 直接使用传入的数值作为business_section进行筛选
            // KTV=3、洗浴汗蒸=4、按摩足浴=5，酒吧的数值未知（由调用方传入）
            queryWrapper.eq("a.business_section", businessType);
        } else {
            // 如果没有指定businessType，则查询所有两种类型的店铺
            // 需要查询字典表获取所有四种类型的dictId
            List<String> storeTypeNames = Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足疗");
            List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(
                    new LambdaQueryWrapper<StoreDictionary>()
                            .eq(StoreDictionary::getTypeName, "business_section")
                            .in(StoreDictionary::getDictDetail, storeTypeNames)
                            .eq(StoreDictionary::getDeleteFlag, 0)
            );

            List<Integer> businessSectionIds = storeDictionaries.stream()
                    .filter(d -> StringUtils.isNotEmpty(d.getDictId()))
                    .map(StoreDictionary::getDictId)
                    .map(dictIdStr -> {
                        try {
                            return Integer.parseInt(dictIdStr);
                        } catch (NumberFormatException e) {
                            return null;
                        }
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());

            // 使用business_section字段进行筛选
            queryWrapper.in("a.business_section", businessSectionIds);
        }

        // 过滤已删除的门店
        queryWrapper.eq("a.delete_flag", 0);
        // 过滤注销的门店
        queryWrapper.eq("a.logout_flag", 0);
        // 过滤禁用的门店
        queryWrapper.ne("a.store_status", 0);
        // 过滤永久关门的店铺
        queryWrapper.ne("a.business_status", 99);
        // 过滤过期的经营许可证
        queryWrapper.ge("a.entertainment_licence_expiration_time", new Date());
        // 添加商家名称模糊查询
        if (StringUtils.isNotEmpty(storeName)) {
            queryWrapper.like("a.store_name", storeName);
        }

        // 距离优先模式：只显示10公里内且3.5星以上的店铺
        final Double finalDistance;
        if (finalSortType == 3) {
            queryWrapper.ge("a.score_avg", 3.5);
            if (distance == null || distance <= 0) {
                finalDistance = 10.0; // 默认10公里
            } else if (distance > 10) {
                finalDistance = 10.0; // 距离优先最多10公里
            } else {
                finalDistance = distance;
            }
        } else {
            finalDistance = distance;
        }

        // 先按距离排序获取所有数据（用于计算距离）
        queryWrapper.orderByAsc("dist");

        // 创建分页对象（先获取更多数据用于排序计算）
        IPage<StoreInfoVo> page = new Page<>(1, 1000); // 先获取足够多的数据
        IPage<StoreInfoVo> storeInfoIPage = storeInfoMapper.getPageForDistance(page, lon + "," + lat, queryWrapper);
        List<StoreInfoVo> storeInfoVoList = storeInfoIPage.getRecords();

        // 如果指定了距离范围，进行距离筛选
        if (finalDistance != null && finalDistance > 0) {
            storeInfoVoList = storeInfoVoList.stream()
                    .filter(store -> {
                        String distStr = store.getDist();
                        if (distStr == null || distStr.isEmpty()) {
                            return false;
                        }
                        try {
                            double storeDistance = Double.parseDouble(distStr);
                            return storeDistance <= finalDistance;
                        } catch (NumberFormatException e) {
                            return false;
                        }
                    })
                    .collect(Collectors.toList());
        }

        // 计算时间范围
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime sevenDaysAgo = now.minusDays(7);
        LocalDateTime thirtyDaysAgo = now.minusDays(30);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String sevenDaysAgoStr = sevenDaysAgo.format(formatter);
        String thirtyDaysAgoStr = thirtyDaysAgo.format(formatter);

        // 提取所有门店ID
        List<Integer> storeIds = storeInfoVoList.stream().map(StoreInfoVo::getId).collect(Collectors.toList());
        
        if (CollectionUtils.isEmpty(storeIds)) {
            // 如果没有符合条件的店铺，返回空结果
            IPage<StoreInfoVo> emptyPage = new Page<>(pageNum, pageSize);
            emptyPage.setRecords(new ArrayList<>());
            emptyPage.setTotal(0);
            return emptyPage;
        }

        // 查询近7天销量（订单数）
        Map<Integer, Long> sales7DaysMap = new HashMap<>();
        if (finalSortType == 1) { // 智能排序需要销量数据
            LambdaQueryWrapper<LifeUserOrder> orderWrapper = new LambdaQueryWrapper<>();
            orderWrapper.in(LifeUserOrder::getStoreId, storeIds)
                    .and(w -> w.and(w1 -> w1.eq(LifeUserOrder::getStatus, 7)
                                    .ge(LifeUserOrder::getFinishTime, sevenDaysAgoStr))
                            .or(w2 -> w2.eq(LifeUserOrder::getStatus, 1)
                                    .ge(LifeUserOrder::getPayTime, sevenDaysAgoStr)))
                    .eq(LifeUserOrder::getDeleteFlag, 0);
            List<LifeUserOrder> orders7Days = lifeUserOrderMapper.selectList(orderWrapper);
            Map<Integer, Long> tempSalesMap = orders7Days.stream()
                    .filter(order -> order.getStoreId() != null)
                    .collect(Collectors.groupingBy(
                            order -> Integer.parseInt(order.getStoreId()),
                            Collectors.counting()));
            sales7DaysMap.putAll(tempSalesMap);
        }

        // 查询近30天好评数（score >= 4.5）
        Map<Integer, Long> goodComment30DaysMap = new HashMap<>();
        // 查询近7天评论数
        Map<Integer, Long> comment7DaysMap = new HashMap<>();
        // 查询总评论数
        Map<Integer, Long> totalCommentMap = new HashMap<>();

        if (finalSortType == 2) { // 好评优先需要评论数据
            // 近30天好评数
            LambdaQueryWrapper<StoreComment> goodCommentWrapper = new LambdaQueryWrapper<>();
            goodCommentWrapper.in(StoreComment::getStoreId, storeIds)
                    .eq(StoreComment::getBusinessType, 5)
                    .eq(StoreComment::getDeleteFlag, 0)
                    .isNull(StoreComment::getReplyId)
                    .ge(StoreComment::getScore, 4.5)
                    .ge(StoreComment::getCreatedTime, thirtyDaysAgoStr);
            List<StoreComment> goodComments30Days = storeCommentMapper.selectList(goodCommentWrapper);
            Map<Integer, Long> tempGoodCommentMap = goodComments30Days.stream()
                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
            goodComment30DaysMap.putAll(tempGoodCommentMap);

            // 近7天评论数
            LambdaQueryWrapper<StoreComment> comment7DaysWrapper = new LambdaQueryWrapper<>();
            comment7DaysWrapper.in(StoreComment::getStoreId, storeIds)
                    .eq(StoreComment::getBusinessType, 5)
                    .eq(StoreComment::getDeleteFlag, 0)
                    .isNull(StoreComment::getReplyId)
                    .ge(StoreComment::getCreatedTime, sevenDaysAgoStr);
            List<StoreComment> comments7Days = storeCommentMapper.selectList(comment7DaysWrapper);
            Map<Integer, Long> tempComment7DaysMap = comments7Days.stream()
                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
            comment7DaysMap.putAll(tempComment7DaysMap);

            // 总评论数
            LambdaQueryWrapper<StoreComment> totalCommentWrapper = new LambdaQueryWrapper<>();
            totalCommentWrapper.in(StoreComment::getStoreId, storeIds)
                    .eq(StoreComment::getBusinessType, 5)
                    .eq(StoreComment::getDeleteFlag, 0)
                    .isNull(StoreComment::getReplyId);
            List<StoreComment> totalComments = storeCommentMapper.selectList(totalCommentWrapper);
            Map<Integer, Long> tempTotalCommentMap = totalComments.stream()
                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
            totalCommentMap.putAll(tempTotalCommentMap);
        }

        // 获取全部店铺的评分
        Map<String, List<Map<String, Object>>> avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream()
                .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
        Map<String, List<Map<String, Object>>> avgPriceMap = lifeUserOrderMapper.allStoreAvgPrice().stream()
                .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));

        // 计算综合得分并排序
        List<StoreInfoVo> sortedList = storeInfoVoList.stream()
                .map(store -> {
                    // 获取基础评分（score_avg × 2，标准化为0-10分）
                    Double scoreAvg = store.getScoreAvg() != null ? store.getScoreAvg() : 0.0;
                    double baseScore = Math.min(scoreAvg * 2, 10.0); // 基础评分，最高10分

                    // 获取距离
                    double storeDistance = 999999;
                    try {
                        String distStr = store.getDist();
                        if (distStr != null && !distStr.isEmpty()) {
                            storeDistance = Double.parseDouble(distStr);
                        }
                    } catch (NumberFormatException e) {
                        // 忽略
                    }

                    double finalScore = 0.0;

                    if (finalSortType == 1) {
                        // 智能排序：综合评分×50% + 近7天销量×30% + 距离得分×20%
                        // 综合评分（基础评分）
                        double scorePart = baseScore * 0.5;

                        // 近7天销量（需要标准化，假设最大销量为100）
                        long sales7Days = sales7DaysMap.getOrDefault(store.getId(), 0L);
                        double salesScore = Math.min(sales7Days / 100.0 * 10, 10.0); // 标准化到0-10
                        double salesPart = salesScore * 0.3;

                        // 距离得分（距离越近得分越高，10公里内计算）
                        double distanceScore = storeDistance <= 10 ? (10 - storeDistance) / 10.0 * 10 : 0;
                        double distancePart = distanceScore * 0.2;

                        finalScore = scorePart + salesPart + distancePart;
                    } else if (finalSortType == 2) {
                        // 好评优先：综合评分×50% + 近30天好评数×35% + 近7天新评占比×15%
                        double scorePart = baseScore * 0.5;

                        // 近30天好评数（需要标准化，假设最大好评数为50）
                        long goodComment30Days = goodComment30DaysMap.getOrDefault(store.getId(), 0L);
                        double goodCommentScore = Math.min(goodComment30Days / 50.0 * 10, 10.0);
                        double goodCommentPart = goodCommentScore * 0.35;

                        // 近7天新评占比
                        long comment7Days = comment7DaysMap.getOrDefault(store.getId(), 0L);
                        long totalComment = totalCommentMap.getOrDefault(store.getId(), 1L); // 避免除0
                        double newCommentRatio = (double) comment7Days / totalComment;
                        double newCommentPart = newCommentRatio * 10 * 0.15; // 占比转换为0-10分

                        finalScore = scorePart + goodCommentPart + newCommentPart;
                    } else if (finalSortType == 3) {
                        // 距离优先：距离得分 = (10 - 实际距离) × 80% + 基础评分 × 20%（10公里内计算）
                        if (storeDistance <= 10) {
                            double distanceScore = (10 - storeDistance) / 10.0 * 10; // 标准化到0-10
                            double distancePart = distanceScore * 0.8;
                            double scorePart = baseScore * 0.2;
                            finalScore = distancePart + scorePart;
                        } else {
                            finalScore = -1; // 超出范围，不展示
                        }
                    }

                    // 设置综合得分（用于排序）
                    store.setDistance(storeDistance);
                    // 使用反射或扩展字段存储finalScore，这里我们使用一个临时字段
                    // 由于StoreInfoVo没有finalScore字段，我们使用distance字段临时存储，排序后再恢复
                    return new Object[] { store, finalScore };
                })
                .filter(item -> {
                    // 距离优先模式：过滤掉超出范围的
                    if (finalSortType == 3) {
                        return ((Double) item[1]) >= 0;
                    }
                    return true;
                })
                .sorted((a, b) -> Double.compare((Double) b[1], (Double) a[1])) // 按得分降序
                .map(item -> (StoreInfoVo) item[0])
                .collect(Collectors.toList());

        // 分页处理
        long total = sortedList.size();
        int start = (pageNum - 1) * pageSize;
        int end = Math.min(start + pageSize, sortedList.size());
        List<StoreInfoVo> pagedList;
        if (start < sortedList.size()) {
            pagedList = sortedList.subList(start, end);
        } else {
            pagedList = new ArrayList<>();
        }

        // 查询每个店铺的最新代金券（只显示一个，最新创建的）
        Map<Integer, LifeCoupon> latestCouponMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(pagedList)) {
            List<Integer> pagedStoreIds = pagedList.stream().map(StoreInfoVo::getId).collect(Collectors.toList());
            // 查询所有店铺的代金券，按创建时间降序
            LambdaQueryWrapper<LifeCoupon> couponWrapper = new LambdaQueryWrapper<>();
            couponWrapper.in(LifeCoupon::getStoreId, pagedStoreIds.stream().map(String::valueOf).collect(Collectors.toList()))
                    .eq(LifeCoupon::getStatus, CouponStatusEnum.ONGOING.getCode())
                    .eq(LifeCoupon::getType, 1) // 代金券类型
                    .eq(LifeCoupon::getDeleteFlag, 0)
                    .orderByDesc(LifeCoupon::getCreatedTime);
            List<LifeCoupon> allCoupons = lifeCouponMapper.selectList(couponWrapper);

            // 为每个店铺只保留最新创建的一个代金券
            for (LifeCoupon coupon : allCoupons) {
                if (coupon.getStoreId() != null) {
                    try {
                        Integer storeId = Integer.parseInt(coupon.getStoreId());
                        // 如果该店铺还没有代金券，或者当前代金券更新，则更新
                        if (!latestCouponMap.containsKey(storeId)) {
                            latestCouponMap.put(storeId, coupon);
                        }
                    } catch (NumberFormatException e) {
                        // 忽略无效的storeId
                    }
                }
            }
        }

        // 设置评分、平均消费和代金券
        for (StoreInfoVo store : pagedList) {
            if (avgScoreMap.containsKey(String.valueOf(store.getId()))) {
                store.setAvgScore(new BigDecimal(avgScoreMap.get(String.valueOf(store.getId())).get(0).get("avg_score").toString())
                        .setScale(1, RoundingMode.HALF_UP).toString());
                store.setTotalNum(avgScoreMap.get(String.valueOf(store.getId())).get(0).get("total_num").toString());
            } else {
                store.setAvgScore("0");
                store.setTotalNum("0");
            }

            if (avgPriceMap.containsKey(String.valueOf(store.getId()))) {
                store.setAvgPrice(avgPriceMap.get(String.valueOf(store.getId())).get(0).get("avg_price").toString());
            } else {
                store.setAvgPrice("0");
            }

            // 设置最新代金券（只显示一个）
            if (latestCouponMap.containsKey(store.getId())) {
                LifeCoupon latestCoupon = latestCouponMap.get(store.getId());
                LifeCouponVo couponVo = new LifeCouponVo();
                BeanUtils.copyProperties(latestCoupon, couponVo);
                // 只设置一个代金券到列表中
                List<LifeCouponVo> couponList = new ArrayList<>();
                couponList.add(couponVo);
                store.setCouponList(couponList);
            } else {
                // 如果没有代金券，设置为空列表
                store.setCouponList(new ArrayList<>());
            }
        }

        // 创建分页对象
        IPage<StoreInfoVo> resultPage = new Page<>(pageNum, pageSize);
        resultPage.setRecords(pagedList);
        resultPage.setTotal(total);
        resultPage.setCurrent(pageNum);
        resultPage.setSize(pageSize);
        resultPage.setPages((total + pageSize - 1) / pageSize);

        return resultPage;
    }

    /**
     * 查询OCR图片上传记录并转换为JSONObject
     *
     * @param storeUserId     店铺用户ID
     * @param ocrType         OCR类型
     * @param likeKeyword     模糊查询关键词，可为null
     * @param includeImageUrl 是否包含imageUrl字段
     * @return JSONObject，如果查询结果为空则返回空的JSONObject
     */
    private com.alibaba.fastjson2.JSONObject convertOcrResultToJson(Integer storeUserId, String ocrType, String likeKeyword, boolean includeImageUrl) {
        LambdaQueryWrapper<OcrImageUpload> wrapper = new LambdaQueryWrapper<OcrImageUpload>()
                .eq(OcrImageUpload::getStoreUserId, storeUserId)
                .eq(OcrImageUpload::getOcrType, ocrType)
                .orderByDesc(OcrImageUpload::getCreateTime)
                .last("limit 1");

        if (StringUtils.isNotEmpty(likeKeyword)) {
            wrapper.like(OcrImageUpload::getOcrResult, likeKeyword);
        }

        OcrImageUpload ocrImageUpload = ocrImageUploadMapper.selectOne(wrapper);

        if (ocrImageUpload == null || StringUtils.isEmpty(ocrImageUpload.getOcrResult())) {
            return new com.alibaba.fastjson2.JSONObject();
        }

        com.alibaba.fastjson2.JSONObject jsonObject = com.alibaba.fastjson2.JSONObject.parseObject(ocrImageUpload.getOcrResult());
        if (includeImageUrl && StringUtils.isNotEmpty(ocrImageUpload.getImageUrl())) {
            jsonObject.put("imageUrl", ocrImageUpload.getImageUrl());
        }

        return jsonObject;
    }


    /**
     * 你可能还喜欢（推荐店铺）
     * 根据一级分类、二级分类、三级分类进行店铺筛选
     * 筛选顺序：先三级，然后二级，最后一级
     *
     * @param businessSection  一级分类（经营板块）
     * @param businessTypes    二级分类（经营种类）
     * @param businessClassify 三级分类（分类）
     * @param lon              经度
     * @param lat              纬度
     * @return List<StoreInfoVo> 店铺信息列表
     */
    @Override
    public List<StoreInfoVo> getRecommendedStores(String businessSection, String businessTypes, String businessClassify, Double lon, Double lat) {
        log.info("StoreInfoServiceImpl.getRecommendedStores?businessSection={},businessTypes={},businessClassify={},lon={},lat={}",
                businessSection, businessTypes, businessClassify, lon, lat);

        QueryWrapper<StoreInfoVo> queryWrapper = new QueryWrapper<>();
        // 基础条件：未删除、已启用
        queryWrapper.eq("a.delete_flag", 0)
                .eq("b.delete_flag", 0)
                .ne("a.business_status", 99) // 过滤永久关门的店铺
                .ne("a.store_status", 0); // 过滤禁用的店铺

        // 按照三级->二级->一级的顺序筛选

        // 1. 先按三级分类（business_classify）筛选
        if (StringUtils.isNotEmpty(businessClassify)) {
            // 解析businessClassify参数（格式：1,2,3）
            String[] classifyArray = businessClassify.split(",");
            // 使用FIND_IN_SET函数检查数据库字段是否包含参数中的任何一个值
            queryWrapper.and(wrapper -> {
                for (int i = 0; i < classifyArray.length; i++) {
                    String classify = classifyArray[i].trim();
                    if (StringUtils.isNotEmpty(classify)) {
                        if (i == 0) {
                            wrapper.apply("FIND_IN_SET({0}, a.business_classify) > 0", classify);
                        } else {
                            wrapper.or().apply("FIND_IN_SET({0}, a.business_classify) > 0", classify);
                        }
                    }
                }
            });
        }

        // 2. 然后按二级分类（business_types）筛选
        if (StringUtils.isNotEmpty(businessTypes)) {
            // business_types可能是逗号分隔的字符串，使用FIND_IN_SET处理
            String[] typesArray = businessTypes.split(",");
            queryWrapper.and(wrapper -> {
                for (int i = 0; i < typesArray.length; i++) {
                    String type = typesArray[i].trim();
                    if (StringUtils.isNotEmpty(type)) {
                        if (i == 0) {
                            wrapper.apply("FIND_IN_SET({0}, a.business_types) > 0", type);
                        } else {
                            wrapper.or().apply("FIND_IN_SET({0}, a.business_types) > 0", type);
                        }
                    }
                }
            });
        }

        // 3. 最后按一级分类（business_section）筛选
        if (StringUtils.isNotEmpty(businessSection)) {
            try {
                Integer sectionId = Integer.parseInt(businessSection.trim());
                queryWrapper.eq("a.business_section", sectionId);
            } catch (NumberFormatException e) {
                log.warn("一级分类参数格式错误: {}", businessSection);
            }
        }

        // 查询店铺列表
        List<StoreInfoVo> storeInfoVoList;
        if (lon != null && lat != null) {
            // 如果提供了经纬度，使用带距离计算的查询方法
            String position = lon + "," + lat;
            queryWrapper.isNotNull("a.store_position")
                    .ne("a.store_position", "");
            // 按距离排序
            queryWrapper.orderByAsc("dist");
            storeInfoVoList = storeInfoMapper.getStoreInfoVoListNew(queryWrapper, position);
        } else {
            // 如果没有提供经纬度，使用普通查询方法
            queryWrapper.orderByDesc("a.created_time");
            storeInfoVoList = storeInfoMapper.getStoreInfoVoList(queryWrapper);
        }

        if (CollectionUtils.isEmpty(storeInfoVoList)) {
            return Collections.emptyList();
        }

        // 处理店铺信息，设置评分等
        // 提前查询所有需要的字典数据
        List<StoreInfoVo> collect = storeInfoVoList.stream()
                .filter(record -> StringUtils.isNotEmpty(record.getStoreType()))
                .collect(Collectors.toList());
        Set<String> allTypes = collect.stream()
                .map(StoreInfoVo::getStoreType)
                .flatMap(type -> Arrays.stream(type.split(",")))
                .collect(Collectors.toSet());

        List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(
                new LambdaQueryWrapper<StoreDictionary>()
                        .eq(StoreDictionary::getTypeName, "storeType")
                        .isNull(StoreDictionary::getParentId)
                        .in(!allTypes.isEmpty(), StoreDictionary::getDictId, allTypes));
        Map<String, String> typeMap = storeDictionaries.stream()
                .collect(Collectors.toMap(StoreDictionary::getDictId, StoreDictionary::getDictDetail));

        // 计算平均分和评价
        Map<String, List<Map<String, Object>>> avgScoreMap = new HashMap<>();
        Map<Integer, List<StoreComment>> commentMap = new HashMap<>();

        avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream()
                .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
        commentMap = storeCommentMapper.selectList(
                        new QueryWrapper<StoreComment>()
                                .eq("business_type", "5")
                                .eq("delete_flag", 0))
                .stream()
                .collect(Collectors.groupingBy(StoreComment::getStoreId));

        for (StoreInfoVo record : storeInfoVoList) {
            // 处理类型
            if (StringUtils.isNotEmpty(record.getStoreType())) {
                String[] types = record.getStoreType().split(",");
                List<String> typeDetails = Arrays.stream(types)
                        .map(typeMap::get)
                        .filter(Objects::nonNull)
                        .collect(Collectors.toList());
                record.setStoreTypeStr(String.join(",", typeDetails));
                record.setStoreTypeList(Arrays.asList(types));
            }

            // 处理经纬度
            if (StringUtils.isNotEmpty(record.getStorePosition())) {
                String[] split = record.getStorePosition().split(",");
                if (split.length >= 2) {
                    record.setStorePositionLongitude(split[0]);
                    record.setStorePositionLatitude(split[1]);
                }
            }

            // 如果提供了经纬度，处理距离信息
            if (lon != null && lat != null && StringUtils.isNotEmpty(record.getStorePosition())) {
                try {
                    // 手动计算距离（单位：公里）
                    String[] positionArray = record.getStorePosition().split(",");
                    if (positionArray.length >= 2) {
                        double storeLon = Double.parseDouble(positionArray[0].trim());
                        double storeLat = Double.parseDouble(positionArray[1].trim());
                        // 计算距离（单位：公里）
                        double distanceKm = DistanceUtil.haversineCalculateDistance(lon, lat, storeLon, storeLat);
                        record.setDistance(distanceKm);
                    }
                } catch (Exception e) {
                    log.warn("计算店铺距离失败，storeId={}，error={}", record.getId(), e.getMessage());
                }
            }

            // 处理到期状态
            Date expirationTime = record.getExpirationTime();
            if (expirationTime != null) {
                Date currentDate = new Date();
                Calendar now = Calendar.getInstance();
                Date nowCurrentDate = now.getTime();
                now.add(Calendar.DAY_OF_YEAR, 30);
                Date thirtyDaysLater = now.getTime();

                if (expirationTime.after(currentDate)) {
                    record.setExpiredState("0");
                    if ((expirationTime.after(nowCurrentDate) || expirationTime.equals(nowCurrentDate))
                            && expirationTime.before(thirtyDaysLater)) {
                        record.setExpiredState("1");
                    }
                } else {
                    record.setExpiredState("2");
                }

                LocalDate nowLocal = LocalDate.now();
                LocalDate expDate = expirationTime.toInstant()
                        .atZone(ZoneId.systemDefault())
                        .toLocalDate();
                long daysToExpire = ChronoUnit.DAYS.between(nowLocal, expDate);
                record.setDaysToExpire(daysToExpire);
            }

            // 设置店铺得分和总评论数
            if (avgScoreMap.containsKey(String.valueOf(record.getId()))) {
                record.setAvgScore(String.valueOf(
                        avgScoreMap.get(String.valueOf(record.getId())).get(0).get("avg_score")));
            }
            if (commentMap.containsKey(record.getId())) {
                record.setTotalNum(String.valueOf(commentMap.get(record.getId()).size()));
            }
        }

        return storeInfoVoList;
    }

    /**
     * 门店证照查询（分页）
     *
     * @param pageNum         页码
     * @param pageSize        页容
     * @param storeName       门店名称（模糊）
     * @param storeTel        门店电话（模糊）
     * @param imgType         证照图片类型（14：营业执照；35：其他资质证明）
     * @param states          证照状态
     * @param startSubmitDate 提交开始时间（yyyy-MM-dd HH:mm:ss）
     * @param endSubmitDate   提交结束时间（yyyy-MM-dd HH:mm:ss）
     * @return 证照分页结果
     */
    @Override
    public IPage<StoreLicenseInfoVo> getStoreLicenseList(int pageNum,
                                                         int pageSize,
                                                         String storeName,
                                                         String storeContact,
                                                         String storeTel,
                                                         String businessSection,
                                                         Integer imgType,
                                                         String states,
                                                         String startSubmitDate,
                                                         String endSubmitDate) {
        IPage<StoreLicenseInfoVo> page = new Page<>(pageNum, pageSize);
        IPage<StoreLicenseInfoVo> storeLicensePage = storeInfoMapper.getStoreLicensePage(page, storeName, storeContact, storeTel, businessSection, imgType, states, startSubmitDate, endSubmitDate);
        // 所有记录统一来自 store_license_history，状态值为 license_execute_status: 1-审核通过, 2-审核中, 3-审核拒绝
        for (StoreLicenseInfoVo record : storeLicensePage.getRecords()) {
            if (record.getStates() != null) {
                switch (record.getStates().toString()) {
                    case "1":
                        record.setStatesName("审核通过");
                        break;
                    case "2":
                        record.setStatesName("审核中");
                        break;
                    case "3":
                        record.setStatesName("审核拒绝");
                        break;
                    default:
                        record.setStatesName("未知");
                        break;
                }
            }
        }
        return storeLicensePage;
    }


    /**
     * 构建树形结构（优化版）
     *
     * @param flatList 扁平列表
     * @return 树形结构列表
     */
    private List<StoreDictionary> buildTreeOptimized(List<StoreDictionary> flatList) {
        if (flatList == null || flatList.isEmpty()) {
            return new ArrayList<>();
        }

        // 创建三个存储结构
        Map<Integer, StoreDictionary> nodeMap = new HashMap<>();  // ID到节点的映射
        Map<Integer, List<StoreDictionary>> parentChildMap = new HashMap<>();  // 父ID到子节点列表的映射
        List<StoreDictionary> result = new ArrayList<>();  // 结果列表

        // 填充nodeMap和parentChildMap
        for (StoreDictionary entity : flatList) {
            Integer id = entity.getId();
            Integer parentId = entity.getParentId();

            // 存入节点映射
            nodeMap.put(id, entity);

            // 初始化子节点列表
            entity.setStoreDictionaryList(new ArrayList<>());

            // 如果是根节点（parentId为null或0），直接添加到结果
            if (parentId == null || parentId == 0) {
                result.add(entity);
            } else {
                // 否则，记录父子关系
                parentChildMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(entity);
            }
        }

        // 建立父子关系
        for (StoreDictionary entity : flatList) {
            Integer id = entity.getId();
            if (parentChildMap.containsKey(id)) {
                entity.getStoreDictionaryList().addAll(parentChildMap.get(id));
            }
        }

        return result;
    }

    @Override
    public List<StoreDictionaryVo> getLeisureEntertainmentCategories() {
        // 定义四种主分类名称
        List<String> mainCategoryNames = Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足疗");

        // 查询所有主分类（business_section类型）
        List<StoreDictionary> allMainCategories = storeDictionaryMapper.selectList(
                new LambdaQueryWrapper<StoreDictionary>()
                        .eq(StoreDictionary::getTypeName, "business_section")
                        .in(StoreDictionary::getDictDetail, mainCategoryNames)
                        .eq(StoreDictionary::getDeleteFlag, 0)
        );

        // 构建主分类列表，包含"全部"选项
        List<StoreDictionaryVo> result = new ArrayList<>();

        // 添加"全部"选项
        StoreDictionaryVo allCategory = new StoreDictionaryVo();
        allCategory.setId(0);
        allCategory.setDictId("0");
        allCategory.setDictDetail("全部");
        allCategory.setTypeName("business_section");
        allCategory.setSubDataList(new ArrayList<>());
        result.add(allCategory);

        // 查询所有子分类（根据parent_id关联）
        Map<Integer, List<StoreDictionary>> subCategoryMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(allMainCategories)) {
            List<Integer> mainCategoryIds = allMainCategories.stream()
                    .map(StoreDictionary::getId)
                    .collect(Collectors.toList());

            // 查询所有子分类
            List<StoreDictionary> allSubCategories = storeDictionaryMapper.selectList(
                    new LambdaQueryWrapper<StoreDictionary>()
                            .in(StoreDictionary::getParentId, mainCategoryIds)
                            .eq(StoreDictionary::getDeleteFlag, 0)
                            .in(StoreDictionary::getTypeName, "business_section", "business_type", "business_classify")
            );

            // 按parentId分组
            subCategoryMap = allSubCategories.stream()
                    .collect(Collectors.groupingBy(StoreDictionary::getParentId));
        }

        // 构建主分类及其子分类
        for (StoreDictionary mainCategory : allMainCategories) {
            StoreDictionaryVo mainVo = new StoreDictionaryVo();
            BeanUtils.copyProperties(mainCategory, mainVo);

            // 获取该主分类下的子分类
            List<StoreDictionary> subCategories = subCategoryMap.getOrDefault(mainCategory.getId(), new ArrayList<>());
            List<StoreDictionaryVo> subVoList = new ArrayList<>();

            for (StoreDictionary subCategory : subCategories) {
                StoreDictionaryVo subVo = new StoreDictionaryVo();
                BeanUtils.copyProperties(subCategory, subVo);
                subVoList.add(subVo);
            }

            mainVo.setSubDataList(subVoList);
            result.add(mainVo);
        }

        return result;
    }


    @Override
    public IPage<StoreInfoVo> getSpecialTypeStoresByDistance(Double lon, Double lat, Double distance, Integer sortType, Integer businessType, Integer categoryId, String storeName,Integer storeType, int pageNum, int pageSize) {
        // 参数校验
        if (lon == null || lat == null) {
            throw new IllegalArgumentException("经纬度参数不能为空");
        }

        // 智能检测：如果参数可能传反了（lat超出范围但lon在范围内），给出提示
        if (Math.abs(lat) > 90 && Math.abs(lon) <= 90) {
            throw new IllegalArgumentException(
                    String.format("参数可能传反了！当前值: lon=%s, lat=%s。经度范围: [-180, 180]，纬度范围: [-90, 90]。请检查参数顺序。", lon, lat)
            );
        }

        // 校验经纬度范围：经度 [-180, 180]，纬度 [-90, 90]
        if (lon < -180 || lon > 180) {
            throw new IllegalArgumentException("经度参数超出有效范围 [-180, 180]，当前值: " + lon);
        }
        if (lat < -90 || lat > 90) {
            throw new IllegalArgumentException("纬度参数超出有效范围 [-90, 90]，当前值: " + lat);
        }
        final int finalSortType = (sortType == null || sortType < 1 || sortType > 3) ? 1 : sortType; // 默认智能排序
        if (pageNum <= 0) {
            pageNum = 1;
        }
        if (pageSize <= 0) {
            pageSize = 10;
        }

        // 构建查询条件
        QueryWrapper<StoreInfoVo> queryWrapper = new QueryWrapper<>();

        // 如果传入了dictId，根据字典id查询经营板块、经营种类、分类并匹配店铺
        if (categoryId != null) {
            // 根据categoryId查询字典表记录
            StoreDictionary dict = storeDictionaryMapper.selectById(categoryId);
            if (dict == null || dict.getDeleteFlag() == 1) {
                throw new IllegalArgumentException("字典id不存在或已删除: " + categoryId);
            }

            String typeName = dict.getTypeName();
            String dictIdStr = dict.getDictId();

            if ("business_section".equals(typeName)) {
                // 如果是经营板块，直接匹配business_section
                try {
                    Integer sectionId = Integer.parseInt(dictIdStr);
                    queryWrapper.eq("a.business_section", sectionId);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("经营板块dictId格式错误: " + dictIdStr);
                }
            } else if ("business_type".equals(typeName)) {
                // 如果是经营种类，需要：
                // 1. 向上查找父级（经营板块）
                // 2. 匹配business_section和business_types
                StoreDictionary parentDict = storeDictionaryMapper.selectById(dict.getParentId());
                if (parentDict == null || !"business_section".equals(parentDict.getTypeName())) {
                    throw new IllegalArgumentException("经营种类的父级不是经营板块，categoryId: " + categoryId);
                }

                try {
                    Integer sectionId = Integer.parseInt(parentDict.getDictId());
                    queryWrapper.eq("a.business_section", sectionId);
                    // 使用FIND_IN_SET匹配business_types字段（逗号分隔）
                    queryWrapper.apply("FIND_IN_SET({0}, a.business_types) > 0", dictIdStr);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("经营板块或经营种类dictId格式错误");
                }
            } else if ("business_classify".equals(typeName)) {
                // 如果是分类，需要：
                // 1. 向上查找父级（经营种类）
                // 2. 向上查找祖父级（经营板块）
                // 3. 匹配business_section、business_types和business_classify
                StoreDictionary parentDict = storeDictionaryMapper.selectById(dict.getParentId());
                if (parentDict == null || !"business_type".equals(parentDict.getTypeName())) {
                    throw new IllegalArgumentException("分类的父级不是经营种类，categoryId: " + categoryId);
                }

                StoreDictionary grandParentDict = storeDictionaryMapper.selectById(parentDict.getParentId());
                if (grandParentDict == null || !"business_section".equals(grandParentDict.getTypeName())) {
                    throw new IllegalArgumentException("经营种类的父级不是经营板块，categoryId: " + categoryId);
                }

                try {
                    Integer sectionId = Integer.parseInt(grandParentDict.getDictId());
                    queryWrapper.eq("a.business_section", sectionId);
                    // 使用FIND_IN_SET匹配business_types字段
                    queryWrapper.apply("FIND_IN_SET({0}, a.business_types) > 0", parentDict.getDictId());
                    // 使用FIND_IN_SET匹配business_classify字段
                    queryWrapper.apply("FIND_IN_SET({0}, a.business_classify) > 0", dictIdStr);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("经营板块、经营种类或分类dictId格式错误");
                }
            } else {
                throw new IllegalArgumentException("不支持的字典类型: " + typeName + ", categoryId: " + categoryId);
            }
        } else if (businessType != null) {
            // 如果指定了businessType，则根据传入的数值进行筛选
            // 直接使用传入的数值作为business_section进行筛选
            // KTV=3、洗浴汗蒸=4、按摩足浴=5，酒吧的数值未知（由调用方传入）
            queryWrapper.eq("a.business_section", businessType);
        } else {
            // 如果没有指定businessType，则查询所有四种类型的店铺
            // 需要查询字典表获取所有四种类型的dictId
            List<String> storeTypeNames = Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足疗");
//            List<String> storeTypeNames=new ArrayList<>();
//            if (storeType !=null &&   storeType ==1 ){
//                 storeTypeNames = Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足疗");
//            } else if (storeType !=null &&   storeType==2) {
//                 storeTypeNames = Arrays.asList("丽人美发", "运动健身");
//            }else if ( storeType !=null && storeType==3) {
//                 storeTypeNames = Arrays.asList("特色美食");
//            }


            List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(
                    new LambdaQueryWrapper<StoreDictionary>()
                            .eq(StoreDictionary::getTypeName, "business_section")
                            .in(StoreDictionary::getDictDetail, storeTypeNames)
                            .eq(StoreDictionary::getDeleteFlag, 0)
            );

            List<Integer> businessSectionIds = storeDictionaries.stream()
                    .filter(d -> StringUtils.isNotEmpty(d.getDictId()))
                    .map(StoreDictionary::getDictId)
                    .map(dictIdStr -> {
                        try {
                            return Integer.parseInt(dictIdStr);
                        } catch (NumberFormatException e) {
                            return null;
                        }
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());

            // 使用business_section字段进行筛选
            queryWrapper.in("a.business_section", businessSectionIds);
        }

        // 过滤已删除的门店
        queryWrapper.eq("a.delete_flag", 0);
        // 过滤注销的门店
        queryWrapper.eq("a.logout_flag", 0);
        // 过滤禁用的门店
        queryWrapper.ne("a.store_status", 0);
        // 过滤永久关门的店铺
        queryWrapper.ne("a.business_status", 99);
        // 过滤过期的经营许可证
        queryWrapper.ge("a.entertainment_licence_expiration_time", new Date());
        // 添加一个模糊查询，根据店铺名称进行查询
        if (StringUtils.isNotEmpty(storeName)) {
            queryWrapper.like("a.store_name", storeName);
        }

        // 距离优先模式：只显示10公里内且3.5星以上的店铺
        final Double finalDistance;
        if (finalSortType == 3) {
            queryWrapper.ge("a.score_avg", 3.5);
            if (distance == null || distance <= 0) {
                finalDistance = 10.0; // 默认10公里
            } else if (distance > 10) {
                finalDistance = 10.0; // 距离优先最多10公里
            } else {
                finalDistance = distance;
            }
        } else {
            finalDistance = distance;
        }

        // 先按距离排序获取所有数据（用于计算距离）
        queryWrapper.orderByAsc("dist");

        // 创建分页对象（先获取更多数据用于排序计算）
        IPage<StoreInfoVo> page = new Page<>(1, 1000); // 先获取足够多的数据
        IPage<StoreInfoVo> storeInfoIPage = storeInfoMapper.getPageForDistance(page, lon + "," + lat, queryWrapper);
        List<StoreInfoVo> storeInfoVoList = storeInfoIPage.getRecords();

        // 如果指定了距离范围，进行距离筛选
        if (finalDistance != null && finalDistance > 0) {
            storeInfoVoList = storeInfoVoList.stream()
                    .filter(store -> {
                        String distStr = store.getDist();
                        if (distStr == null || distStr.isEmpty()) {
                            return false;
                        }
                        try {
                            double storeDistance = Double.parseDouble(distStr);
                            return storeDistance <= finalDistance;
                        } catch (NumberFormatException e) {
                            return false;
                        }
                    })
                    .collect(Collectors.toList());
        }

        // 计算时间范围
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime sevenDaysAgo = now.minusDays(7);
        LocalDateTime thirtyDaysAgo = now.minusDays(30);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String sevenDaysAgoStr = sevenDaysAgo.format(formatter);
        String thirtyDaysAgoStr = thirtyDaysAgo.format(formatter);

        // 提取所有门店ID
        List<Integer> storeIds = storeInfoVoList.stream().map(StoreInfoVo::getId).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(storeIds)) {
            // 如果没有符合条件的店铺，返回空结果
            IPage<StoreInfoVo> emptyPage = new Page<>(pageNum, pageSize);
            emptyPage.setRecords(new ArrayList<>());
            emptyPage.setTotal(0);
            return emptyPage;
        }

        // 查询近7天销量（订单数）
        Map<Integer, Long> sales7DaysMap = new HashMap<>();
        if (finalSortType == 1) { // 智能排序需要销量数据
            LambdaQueryWrapper<LifeUserOrder> orderWrapper = new LambdaQueryWrapper<>();
            orderWrapper.in(LifeUserOrder::getStoreId, storeIds)
                    .and(w -> w.and(w1 -> w1.eq(LifeUserOrder::getStatus, 7)
                                    .ge(LifeUserOrder::getFinishTime, sevenDaysAgoStr))
                            .or(w2 -> w2.eq(LifeUserOrder::getStatus, 1)
                                    .ge(LifeUserOrder::getPayTime, sevenDaysAgoStr)))
                    .eq(LifeUserOrder::getDeleteFlag, 0);
            List<LifeUserOrder> orders7Days = lifeUserOrderMapper.selectList(orderWrapper);
            Map<Integer, Long> tempSalesMap = orders7Days.stream()
                    .filter(order -> order.getStoreId() != null)
                    .collect(Collectors.groupingBy(
                            order -> Integer.parseInt(order.getStoreId()),
                            Collectors.counting()));
            sales7DaysMap.putAll(tempSalesMap);
        }

        // 查询近30天好评数（score >= 4.5）
        Map<Integer, Long> goodComment30DaysMap = new HashMap<>();
        // 查询近7天评论数
        Map<Integer, Long> comment7DaysMap = new HashMap<>();
        // 查询总评论数
        Map<Integer, Long> totalCommentMap = new HashMap<>();

        if (finalSortType == 2) { // 好评优先需要评论数据
            // 近30天好评数
            LambdaQueryWrapper<StoreComment> goodCommentWrapper = new LambdaQueryWrapper<>();
            goodCommentWrapper.in(StoreComment::getStoreId, storeIds)
                    .eq(StoreComment::getBusinessType, 5)
                    .eq(StoreComment::getDeleteFlag, 0)
                    .isNull(StoreComment::getReplyId)
                    .ge(StoreComment::getScore, 4.5)
                    .ge(StoreComment::getCreatedTime, thirtyDaysAgoStr);
            List<StoreComment> goodComments30Days = storeCommentMapper.selectList(goodCommentWrapper);
            Map<Integer, Long> tempGoodCommentMap = goodComments30Days.stream()
                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
            goodComment30DaysMap.putAll(tempGoodCommentMap);

            // 近7天评论数
            LambdaQueryWrapper<StoreComment> comment7DaysWrapper = new LambdaQueryWrapper<>();
            comment7DaysWrapper.in(StoreComment::getStoreId, storeIds)
                    .eq(StoreComment::getBusinessType, 5)
                    .eq(StoreComment::getDeleteFlag, 0)
                    .isNull(StoreComment::getReplyId)
                    .ge(StoreComment::getCreatedTime, sevenDaysAgoStr);
            List<StoreComment> comments7Days = storeCommentMapper.selectList(comment7DaysWrapper);
            Map<Integer, Long> tempComment7DaysMap = comments7Days.stream()
                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
            comment7DaysMap.putAll(tempComment7DaysMap);

            // 总评论数
            LambdaQueryWrapper<StoreComment> totalCommentWrapper = new LambdaQueryWrapper<>();
            totalCommentWrapper.in(StoreComment::getStoreId, storeIds)
                    .eq(StoreComment::getBusinessType, 5)
                    .eq(StoreComment::getDeleteFlag, 0)
                    .isNull(StoreComment::getReplyId);
            List<StoreComment> totalComments = storeCommentMapper.selectList(totalCommentWrapper);
            Map<Integer, Long> tempTotalCommentMap = totalComments.stream()
                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
            totalCommentMap.putAll(tempTotalCommentMap);
        }

        // 获取全部店铺的评分
        Map<String, List<Map<String, Object>>> avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream()
                .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
        Map<String, List<Map<String, Object>>> avgPriceMap = lifeUserOrderMapper.allStoreAvgPrice().stream()
                .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));

        // 计算综合得分并排序
        List<StoreInfoVo> sortedList = storeInfoVoList.stream()
                .map(store -> {
                    // 获取基础评分（score_avg × 2，标准化为0-10分）
                    Double scoreAvg = store.getScoreAvg() != null ? store.getScoreAvg() : 0.0;
                    double baseScore = Math.min(scoreAvg * 2, 10.0); // 基础评分，最高10分

                    // 获取距离
                    double storeDistance = 999999;
                    try {
                        String distStr = store.getDist();
                        if (distStr != null && !distStr.isEmpty()) {
                            storeDistance = Double.parseDouble(distStr);
                        }
                    } catch (NumberFormatException e) {
                        // 忽略
                    }

                    double finalScore = 0.0;

                    if (finalSortType == 1) {
                        // 智能排序：综合评分×50% + 近7天销量×30% + 距离得分×20%
                        // 综合评分（基础评分）
                        double scorePart = baseScore * 0.5;

                        // 近7天销量（需要标准化，假设最大销量为100）
                        long sales7Days = sales7DaysMap.getOrDefault(store.getId(), 0L);
                        double salesScore = Math.min(sales7Days / 100.0 * 10, 10.0); // 标准化到0-10
                        double salesPart = salesScore * 0.3;

                        // 距离得分（距离越近得分越高，10公里内计算）
                        double distanceScore = storeDistance <= 10 ? (10 - storeDistance) / 10.0 * 10 : 0;
                        double distancePart = distanceScore * 0.2;

                        finalScore = scorePart + salesPart + distancePart;
                    } else if (finalSortType == 2) {
                        // 好评优先：综合评分×50% + 近30天好评数×35% + 近7天新评占比×15%
                        double scorePart = baseScore * 0.5;

                        // 近30天好评数（需要标准化，假设最大好评数为50）
                        long goodComment30Days = goodComment30DaysMap.getOrDefault(store.getId(), 0L);
                        double goodCommentScore = Math.min(goodComment30Days / 50.0 * 10, 10.0);
                        double goodCommentPart = goodCommentScore * 0.35;

                        // 近7天新评占比
                        long comment7Days = comment7DaysMap.getOrDefault(store.getId(), 0L);
                        long totalComment = totalCommentMap.getOrDefault(store.getId(), 1L); // 避免除0
                        double newCommentRatio = (double) comment7Days / totalComment;
                        double newCommentPart = newCommentRatio * 10 * 0.15; // 占比转换为0-10分

                        finalScore = scorePart + goodCommentPart + newCommentPart;
                    } else if (finalSortType == 3) {
                        // 距离优先：距离得分 = (10 - 实际距离) × 80% + 基础评分 × 20%（10公里内计算）
                        if (storeDistance <= 10) {
                            double distanceScore = (10 - storeDistance) / 10.0 * 10; // 标准化到0-10
                            double distancePart = distanceScore * 0.8;
                            double scorePart = baseScore * 0.2;
                            finalScore = distancePart + scorePart;
                        } else {
                            finalScore = -1; // 超出范围，不展示
                        }
                    }

                    // 设置综合得分（用于排序）
                    store.setDistance(storeDistance);
                    // 使用反射或扩展字段存储finalScore，这里我们使用一个临时字段
                    // 由于StoreInfoVo没有finalScore字段，我们使用distance字段临时存储，排序后再恢复
                    return new Object[]{store, finalScore};
                })
                .filter(item -> {
                    // 距离优先模式：过滤掉超出范围的
                    if (finalSortType == 3) {
                        return ((Double) item[1]) >= 0;
                    }
                    return true;
                })
                .sorted((a, b) -> Double.compare((Double) b[1], (Double) a[1])) // 按得分降序
                .map(item -> (StoreInfoVo) item[0])
                .collect(Collectors.toList());

        // 分页处理
        long total = sortedList.size();
        int start = (pageNum - 1) * pageSize;
        int end = Math.min(start + pageSize, sortedList.size());
        List<StoreInfoVo> pagedList;
        if (start < sortedList.size()) {
            pagedList = sortedList.subList(start, end);
        } else {
            pagedList = new ArrayList<>();
        }

        // 查询每个店铺的最新代金券（只显示一个，最新创建的）
        Map<Integer, LifeCoupon> latestCouponMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(pagedList)) {
            List<Integer> pagedStoreIds = pagedList.stream().map(StoreInfoVo::getId).collect(Collectors.toList());
            // 查询所有店铺的代金券，按创建时间降序
            LambdaQueryWrapper<LifeCoupon> couponWrapper = new LambdaQueryWrapper<>();
            couponWrapper.in(LifeCoupon::getStoreId, pagedStoreIds.stream().map(String::valueOf).collect(Collectors.toList()))
                    .eq(LifeCoupon::getStatus, CouponStatusEnum.ONGOING.getCode())
                    .eq(LifeCoupon::getType, 1) // 代金券类型
                    .eq(LifeCoupon::getDeleteFlag, 0)
                    .orderByDesc(LifeCoupon::getCreatedTime);
            List<LifeCoupon> allCoupons = lifeCouponMapper.selectList(couponWrapper);

            // 为每个店铺只保留最新创建的一个代金券
            for (LifeCoupon coupon : allCoupons) {
                if (coupon.getStoreId() != null) {
                    try {
                        Integer storeId = Integer.parseInt(coupon.getStoreId());
                        // 如果该店铺还没有代金券，或者当前代金券更新，则更新
                        if (!latestCouponMap.containsKey(storeId)) {
                            latestCouponMap.put(storeId, coupon);
                        }
                    } catch (NumberFormatException e) {
                        // 忽略无效的storeId
                    }
                }
            }
        }

        // 设置评分、平均消费和代金券
        for (StoreInfoVo store : pagedList) {
            if (avgScoreMap.containsKey(String.valueOf(store.getId()))) {
                store.setAvgScore(new BigDecimal(avgScoreMap.get(String.valueOf(store.getId())).get(0).get("avg_score").toString())
                        .setScale(1, RoundingMode.HALF_UP).toString());
                store.setTotalNum(avgScoreMap.get(String.valueOf(store.getId())).get(0).get("total_num").toString());
            } else {
                store.setAvgScore("0");
                store.setTotalNum("0");
            }

            if (avgPriceMap.containsKey(String.valueOf(store.getId()))) {
                store.setAvgPrice(avgPriceMap.get(String.valueOf(store.getId())).get(0).get("avg_price").toString());
            } else {
                store.setAvgPrice("0");
            }

            // 设置最新代金券（只显示一个）
            if (latestCouponMap.containsKey(store.getId())) {
                LifeCoupon latestCoupon = latestCouponMap.get(store.getId());
                LifeCouponVo couponVo = new LifeCouponVo();
                BeanUtils.copyProperties(latestCoupon, couponVo);
                // 只设置一个代金券到列表中
                List<LifeCouponVo> couponList = new ArrayList<>();
                couponList.add(couponVo);
                store.setCouponList(couponList);
            } else {
                // 如果没有代金券，设置为空列表
                store.setCouponList(new ArrayList<>());
            }
        }

        // 创建分页对象
        IPage<StoreInfoVo> resultPage = new Page<>(pageNum, pageSize);
        resultPage.setRecords(pagedList);
        resultPage.setTotal(total);
        resultPage.setCurrent(pageNum);
        resultPage.setSize(pageSize);
        resultPage.setPages((total + pageSize - 1) / pageSize);

        return resultPage;
    }

    @Override
    public List<StoreDictionary> getAllBusinessSection() {
        // 查询所有经营种类数据
        LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(StoreDictionary::getTypeName, "business_section", "business_type", "business_classify");
        queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
        queryWrapper.orderByAsc(StoreDictionary::getSortId);
        List<StoreDictionary> storeDictionaryList = storeDictionaryMapper.selectList(queryWrapper);

        // 构建三级树形结构
        return buildTreeOptimized(storeDictionaryList);
    }

    @Override
    public List<StoreDictionary> getAllBusinessSection(String businessSection) {
        // 如果没有传入一级分类参数，返回所有分类
        if (businessSection == null || businessSection.trim().isEmpty()) {
            return getAllBusinessSection();
        }

        // 1. 根据dictId查询一级分类
        StoreDictionary firstLevelDict = storeDictionaryMapper.selectOne(
                new LambdaQueryWrapper<StoreDictionary>()
                        .eq(StoreDictionary::getDictId, businessSection.trim())
                        .eq(StoreDictionary::getTypeName, "business_section")
                        .eq(StoreDictionary::getDeleteFlag, 0)
        );

        if (firstLevelDict == null) {
            log.warn("未找到一级分类，businessSection={}", businessSection);
            return new ArrayList<>();
        }

        // 2. 查询该一级分类下的所有二级分类（business_type）
        List<StoreDictionary> secondLevelDicts = storeDictionaryMapper.selectList(
                new LambdaQueryWrapper<StoreDictionary>()
                        .eq(StoreDictionary::getTypeName, "business_type")
                        .eq(StoreDictionary::getParentId, firstLevelDict.getId())
                        .eq(StoreDictionary::getDeleteFlag, 0)
                        .orderByAsc(StoreDictionary::getSortId)
        );

        if (secondLevelDicts.isEmpty()) {
            // 如果没有二级分类，只返回一级分类
            firstLevelDict.setStoreDictionaryList(new ArrayList<>());
            return Collections.singletonList(firstLevelDict);
        }

        // 3. 获取所有二级分类的ID
        List<Integer> secondLevelIds = secondLevelDicts.stream()
                .map(StoreDictionary::getId)
                .collect(Collectors.toList());

        // 4. 查询这些二级分类下的所有三级分类（business_classify）
        List<StoreDictionary> thirdLevelDicts = storeDictionaryMapper.selectList(
                new LambdaQueryWrapper<StoreDictionary>()
                        .eq(StoreDictionary::getTypeName, "business_classify")
                        .in(StoreDictionary::getParentId, secondLevelIds)
                        .eq(StoreDictionary::getDeleteFlag, 0)
                        .orderByAsc(StoreDictionary::getSortId)
        );

        // 5. 构建树形结构
        // 将一级分类、二级分类、三级分类合并
        List<StoreDictionary> allDicts = new ArrayList<>();
        allDicts.add(firstLevelDict);
        allDicts.addAll(secondLevelDicts);
        allDicts.addAll(thirdLevelDicts);

        // 构建树形结构
        return buildTreeOptimized(allDicts);
    }


    /**
     * web-分页查询店铺信息
     *
     * @return IPage<StoreInfoVo>
     */
    @Override
    public List<StoreInfoVo> getMoreRecommendedStores(Double lon, Double lat, String businessSection, String businessTypes, String businessClassify, Integer storeId) {
        // 参数校验
        if (lon == null || lat == null) {
            log.warn("获取更多推荐店铺失败，经纬度为空");
            return Collections.emptyList();
        }

        // 获取当前时刻
        Date currentDate = new Date();
        // 获取当前日期和时间
        Calendar calendar = Calendar.getInstance();
        // 将时间设置为 0 点
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        // 加上 30 天
        calendar.add(Calendar.DAY_OF_MONTH, 30);
        // 构建position参数（格式：经度,纬度）
        String position = lon + "," + lat;

        // 先查询当前用户好友店铺ID（互相关注的商户）
        Set<Integer> friendStoreIds = new HashSet<>();
        try {
            // 从上下文获取当前登录用户ID -> 查询手机号 -> 组装粉丝ID
            JSONObject currentUserInfo = JwtUtil.getCurrentUserInfo();
            if (currentUserInfo != null) {
                Integer currentUserId = currentUserInfo.getInteger("userId");
                if (currentUserId != null) {
                    LifeUser currentUser = lifeUserMapper.selectById(currentUserId);
                    if (currentUser != null && StringUtils.isNotEmpty(currentUser.getUserPhone())) {
                        String myFansId = "user_" + currentUser.getUserPhone();

                        // 我关注的店铺
                        LifeFansIdentityQuery.Scope myScope = LifeFansIdentityQuery.resolve(myFansId, typeUtil);
                        LambdaQueryWrapper<LifeFans> myFollowWrapper = new LambdaQueryWrapper<>();
                        myFollowWrapper.eq(LifeFans::getDeleteFlag, 0);
                        LifeFansIdentityQuery.applyFansSide(myFollowWrapper, myScope);
                        myFollowWrapper.eq(LifeFans::getFollowedUserType, 2);
                        List<LifeFans> myFollows = lifeFansMapper.selectList(myFollowWrapper);

                        // 过滤出互相关注（店铺也关注我）的店铺phoneId：store_xxx
                        Set<String> mutualStorePhones = new HashSet<>();
                        if (!CollectionUtils.isEmpty(myFollows)) {
                            List<String> followedStoreIds = myFollows.stream()
                                    .map(LifeFans::getFollowedId)
                                    .filter(Objects::nonNull)
                                    .collect(Collectors.toList());

                            if (!followedStoreIds.isEmpty()) {
                                List<Integer> fanStoreRefIds = followedStoreIds.stream()
                                        .map(id -> LifeFansIdentityQuery.resolve(id, typeUtil))
                                        .filter(LifeFansIdentityQuery.Scope::hasTypeRef)
                                        .filter(scope -> Integer.valueOf(2).equals(scope.getUserType()))
                                        .map(LifeFansIdentityQuery.Scope::getRefId)
                                        .collect(Collectors.toList());
                                if (!fanStoreRefIds.isEmpty()) {
                                // 查询这些店铺是否关注我
                                LambdaQueryWrapper<LifeFans> reciprocalWrapper = new LambdaQueryWrapper<>();
                                reciprocalWrapper.eq(LifeFans::getDeleteFlag, 0);
                                LifeFansIdentityQuery.applyFollowedSide(reciprocalWrapper, myScope);
                                reciprocalWrapper.eq(LifeFans::getFansUserType, 2)
                                        .in(LifeFans::getFansRefId, fanStoreRefIds);
                                List<LifeFans> reciprocals = lifeFansMapper.selectList(reciprocalWrapper);
                                Set<String> reciprocalFansIds = reciprocals.stream()
                                        .map(LifeFans::getFansId)
                                        .filter(Objects::nonNull)
                                        .collect(Collectors.toSet());

                                // 互相关注的店铺 phoneId（store_开头）
                                for (String followedId : followedStoreIds) {
                                    if (reciprocalFansIds.contains(followedId)) {
                                        mutualStorePhones.add(followedId);
                                    }
                                }
                                }
                            }
                        }

                        if (!mutualStorePhones.isEmpty()) {
                            // 提取店铺手机号
                            Set<String> storePhones = mutualStorePhones.stream()
                                    .map(pid -> {
                                        int idx = pid.indexOf('_');
                                        return idx != -1 ? pid.substring(idx + 1) : pid;
                                    })
                                    .collect(Collectors.toSet());

                            // 根据店铺手机号查询 store_user，提取 store_id
                            LambdaQueryWrapper<StoreUser> storeUserWrapper = new LambdaQueryWrapper<>();
                            storeUserWrapper.in(StoreUser::getPhone, storePhones)
                                    .eq(StoreUser::getDeleteFlag, 0);
                            List<StoreUser> storeUsers = storeUserMapper.selectList(storeUserWrapper);
                            friendStoreIds = storeUsers.stream()
                                    .map(StoreUser::getStoreId)
                                    .filter(Objects::nonNull)
                                    .collect(Collectors.toSet());
                        }
                    }
                }
            }
        } catch (Exception e) {
            // 好友优先不影响主流程
            log.warn("更多推荐-好友店铺优先排序失败，忽略该步骤。error={}", e.getMessage());
        }

        // 查询好友店铺（不限制 business_section）
        List<StoreInfoVo> friendStoreList = Collections.emptyList();
        if (!friendStoreIds.isEmpty()) {
            QueryWrapper<StoreInfoVo> friendQueryWrapper = new QueryWrapper<>();
            friendQueryWrapper.eq("a.delete_flag", 0).eq("b.delete_flag", 0);
            friendQueryWrapper.and(w -> w.isNull("a.expiration_time")
                    .or()
                    .gt("a.expiration_time", currentDate));
            friendQueryWrapper.and(w -> w.isNull("a.food_licence_expiration_time")
                    .or()
                    .gt("a.food_licence_expiration_time", currentDate));
            if (storeId != null && storeId > 0) {
                friendQueryWrapper.ne("a.id", storeId);
            }
            friendQueryWrapper.in("a.id", friendStoreIds);
            friendStoreList = storeInfoMapper.getMoreRecommendedStores(friendQueryWrapper, position);
        }

        // 查询当前类型店铺（仅按 business_section）
        QueryWrapper<StoreInfoVo> currentTypeQueryWrapper = new QueryWrapper<>();
        currentTypeQueryWrapper.eq("a.delete_flag", 0).eq("b.delete_flag", 0);
        currentTypeQueryWrapper.and(w -> w.isNull("a.expiration_time")
                .or()
                .gt("a.expiration_time", currentDate));
        currentTypeQueryWrapper.and(w -> w.isNull("a.food_licence_expiration_time")
                .or()
                .gt("a.food_licence_expiration_time", currentDate));
        if (StringUtils.isNotEmpty(businessSection)) {
            currentTypeQueryWrapper.eq("a.business_section", businessSection);
        }
        if (storeId != null && storeId > 0) {
            currentTypeQueryWrapper.ne("a.id", storeId);
        }
        List<StoreInfoVo> currentTypeStoreList = storeInfoMapper.getMoreRecommendedStores(currentTypeQueryWrapper, position);

        // 合并：好友店铺在前，当前类型店铺在后；按店铺ID去重
        Map<Integer, StoreInfoVo> mergedMap = new LinkedHashMap<>();
        if (!CollectionUtils.isEmpty(friendStoreList)) {
            for (StoreInfoVo vo : friendStoreList) {
                mergedMap.put(vo.getId(), vo);
            }
        }
        if (!CollectionUtils.isEmpty(currentTypeStoreList)) {
            for (StoreInfoVo vo : currentTypeStoreList) {
                mergedMap.putIfAbsent(vo.getId(), vo);
            }
        }
        List<StoreInfoVo> storeInfoVoList = new ArrayList<>(mergedMap.values());
        if (CollectionUtils.isEmpty(storeInfoVoList)) {
            return Collections.emptyList();
        }

        // 好友店铺 + 当前类型店铺，最多回显30个
        if (storeInfoVoList.size() > 30) {
            storeInfoVoList = new ArrayList<>(storeInfoVoList.subList(0, 30));
        }
        // 提前查询所有需要的字典数据
        List<StoreInfoVo> collect = storeInfoVoList.stream().filter(record -> StringUtils.isNotEmpty(record.getStoreType())).collect(Collectors.toList());
        Set<String> allTypes = collect.stream().map(StoreInfoVo::getStoreType).flatMap(type -> Arrays.stream(type.split(","))).collect(Collectors.toSet());

        List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(new LambdaQueryWrapper<StoreDictionary>().eq(StoreDictionary::getTypeName, "storeType").isNull(StoreDictionary::getParentId).in(!allTypes.isEmpty(), StoreDictionary::getDictId, allTypes));
        Map<String, String> typeMap = storeDictionaries.stream().collect(Collectors.toMap(StoreDictionary::getDictId, StoreDictionary::getDictDetail));


        // 平均分仍取自历史聚合（store_comment）；评价条数 totalNum 在循环内按 common_rating 统计，与 getStoreMainInfo 口径一致
        Map<String, List<Map<String, Object>>> avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream()
                .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));

        // 查询入口头图
        List<Integer> storeIds = storeInfoVoList.stream()
                .map(StoreInfoVo::getId)  // 假设 StoreImg 有 getStoreUrl() 方法
                .collect(Collectors.toList());

        List<StoreImg> storeImgList = storeImgMapper.selectList(new QueryWrapper<StoreImg>().in("store_id", storeIds).eq("img_type", 1));
        Map<Integer, List<StoreImg>> storeCollect = storeImgList.stream()
                .collect(Collectors.groupingBy(StoreImg::getStoreId));


        for (StoreInfoVo record : storeInfoVoList) {
            //处理类型
            if (StringUtils.isNotEmpty(record.getStoreType())) {
                String[] types = record.getStoreType().split(",");
                List<String> typeDetails = Arrays.stream(types).map(typeMap::get).filter(Objects::nonNull).collect(Collectors.toList());
                record.setStoreTypeStr(String.join(",", typeDetails));
                record.setStoreTypeList(Arrays.asList(types));
            }


            // 加入头图
            if (!CollectionUtils.isEmpty(storeCollect) && storeCollect.containsKey(record.getId())) {
                List<StoreImg> storeImgs = storeCollect.get(record.getId());
                if (!CollectionUtils.isEmpty(storeImgs)) {
                    record.setEntranceImage(storeImgs.get(0).getImgUrl());
                }
            }

            //写经纬度
            String[] split = record.getStorePosition().split(",");
            record.setStorePositionLongitude(split[0]);
            record.setStorePositionLatitude(split[1]);
            // 格式化距离，移除无意义的小数位
            if (!StringUtils.isEmpty(record.getDistance3())) {
                try {
                    BigDecimal distanceValue = new BigDecimal(record.getDistance3());
                    record.setDistance3(distanceValue.stripTrailingZeros().toPlainString());
                } catch (NumberFormatException ex) {
                    log.warn("店铺距离格式化失败, storeId: {}, distance3: {}", record.getId(), record.getDistance3(), ex);
                }
            }
            //处理一下到期状态
            Date expirationTime = record.getExpirationTime();
            if (expirationTime != null) {
                // 获取当前时间
                Calendar now = Calendar.getInstance();
                Date nowCurrentDate = now.getTime();
                // 计算 30 天后的时间
                now.add(Calendar.DAY_OF_YEAR, 30);
                Date thirtyDaysLater = now.getTime();
                // 比较两个日期
                if (expirationTime.after(currentDate)) {
                    record.setExpiredState("0");
                    if ((expirationTime.after(nowCurrentDate) || expirationTime.equals(nowCurrentDate)) && expirationTime.before(thirtyDaysLater)) {
                        record.setExpiredState("1");
                    }
                } else {
                    record.setExpiredState("2");
                }

                // 获取当前时间
                LocalDate nowLocal = LocalDate.now();
                // 将 expirationTime 转换为 LocalDate
                LocalDate expDate = expirationTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                // 计算距离到期的天数
                long daysToExpire = ChronoUnit.DAYS.between(nowLocal, expDate);
                record.setDaysToExpire(daysToExpire);
            }

            // 设置店铺得分；评价条数取自 common_rating（商铺评价 business_type=1），不含已废弃的 store_comment
            if (avgScoreMap.containsKey(String.valueOf(record.getId()))) {
                record.setAvgScore(String.valueOf(avgScoreMap.get(String.valueOf(record.getId())).get(0).get("avg_score")));
            } else {
                record.setAvgScore("0");
            }
            String ratingCountStr = "0";
            try {
                long n = commonRatingMapper.selectCount(new QueryWrapper<CommonRating>()
                        .eq("business_type", 1)
                        .eq("business_id", record.getId())
                        .eq("delete_flag", 0)
                        .and(w -> w.in("audit_status", 0, 1).or().isNull("audit_status")));
                ratingCountStr = String.valueOf(n);
            } catch (Exception e) {
                log.warn("更多推荐-店铺评价条数(common_rating)计算失败, storeId={}", record.getId(), e);
            }
            record.setTotalNum(ratingCountStr);
            record.setCommitCount(ratingCountStr);

        }

        // SQL已经实现了距离过滤和排序，直接返回结果
        return storeInfoVoList;
    }

    /**
     * 根据店铺ID获取推荐店铺列表（用户端）
     * <p>
     * 只使用store_id查询，不包含其他筛选条件（经营板块、经营分类、分类、经纬度等）
     * </p>
     *
     * @param storeId 店铺ID，必填，必须大于0
     * @return 推荐店铺列表
     */
    @Override
    public List<StoreInfoVo> getRecommendedStoresByStoreId(Integer storeId) {
        log.info("根据店铺ID获取推荐店铺列表，storeId={}", storeId);
        
        // 参数校验
        if (storeId == null || storeId <= 0) {
            log.warn("获取推荐店铺列表失败，店铺ID无效：{}", storeId);
            return Collections.emptyList();
        }
        
        try {
            QueryWrapper<StoreInfoVo> queryWrapper = new QueryWrapper<>();
            // 基础条件：未删除、已启用
            queryWrapper.eq("a.delete_flag", 0)
                    .eq("b.delete_flag", 0)
                    .ne("a.business_status", 99) // 过滤永久关门的店铺
                    .ne("a.store_status", 0); // 过滤禁用的店铺
            
            // 排除当前店铺
            queryWrapper.eq("a.id", storeId);
            
            // 过期时间判断
            Date currentDate = new Date();
            // 如果 expiration_time 为空则不做过期判断；如果不为空则要求大于当前时间
            queryWrapper.and(w -> w.isNull("a.expiration_time")
                    .or()
                    .gt("a.expiration_time", currentDate));
            
            // 如果 food_licence_expiration_time 为空则不做过期判断；如果不为空则要求大于当前时间
            queryWrapper.and(w -> w.isNull("a.food_licence_expiration_time")
                    .or()
                    .gt("a.food_licence_expiration_time", currentDate));
            
            // 查询店铺列表（限制20条）
            queryWrapper.last("limit 20");
            
            List<StoreInfoVo> storeInfoVoList = storeInfoMapper.getStoreInfoVoList(queryWrapper);
            
            if (CollectionUtils.isEmpty(storeInfoVoList)) {
                return Collections.emptyList();
            }
            
            // 提前查询所有需要的字典数据
            List<StoreInfoVo> collect = storeInfoVoList.stream()
                    .filter(record -> StringUtils.isNotEmpty(record.getStoreType()))
                    .collect(Collectors.toList());
            Set<String> allTypes = collect.stream()
                    .map(StoreInfoVo::getStoreType)
                    .flatMap(type -> Arrays.stream(type.split(",")))
                    .collect(Collectors.toSet());
            
            List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(
                    new LambdaQueryWrapper<StoreDictionary>()
                            .eq(StoreDictionary::getTypeName, "storeType")
                            .isNull(StoreDictionary::getParentId)
                            .in(!allTypes.isEmpty(), StoreDictionary::getDictId, allTypes));
            Map<String, String> typeMap = storeDictionaries.stream()
                    .collect(Collectors.toMap(StoreDictionary::getDictId, StoreDictionary::getDictDetail));
            
            // 计算平均分和评价
            Map<String, List<Map<String, Object>>> avgScoreMap = new HashMap<>();
            Map<Integer, List<StoreComment>> commentMap = new HashMap<>();
            
            // 注意：需要将store_id转换为String类型，与后续containsKey判断保持一致
            avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream()
                    .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
            List<StoreComment> storeComments = storeCommentMapper.selectList(
                    new QueryWrapper<StoreComment>()
                            .eq("business_type", "5")
                            .eq("delete_flag", 0));
            commentMap = storeComments.stream()
                    .filter(comment -> comment.getStoreId() != null)
                    .collect(Collectors.groupingBy(StoreComment::getStoreId));
            
            // 查询入口头图
            List<Integer> storeIds = storeInfoVoList.stream()
                    .map(StoreInfoVo::getId)
                    .collect(Collectors.toList());
            
            List<StoreImg> storeImgList = storeImgMapper.selectList(
                    new QueryWrapper<StoreImg>()
                            .in("store_id", storeIds)
                            .eq("img_type", 1));
            Map<Integer, List<StoreImg>> storeCollect = storeImgList.stream()
                    .collect(Collectors.groupingBy(StoreImg::getStoreId));
            
            // 处理每个店铺的数据
            for (StoreInfoVo record : storeInfoVoList) {
                // 处理类型
                if (StringUtils.isNotEmpty(record.getStoreType())) {
                    String[] types = record.getStoreType().split(",");
                    List<String> typeDetails = Arrays.stream(types)
                            .map(typeMap::get)
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList());
                    record.setStoreTypeStr(String.join(",", typeDetails));
                    record.setStoreTypeList(Arrays.asList(types));
                }
                
                // 加入头图
                if (!CollectionUtils.isEmpty(storeCollect) && storeCollect.containsKey(record.getId())) {
                    List<StoreImg> storeImgs = storeCollect.get(record.getId());
                    if (!CollectionUtils.isEmpty(storeImgs)) {
                        record.setEntranceImage(storeImgs.get(0).getImgUrl());
                    }
                }
                
                // 处理经纬度
                if (StringUtils.isNotEmpty(record.getStorePosition())) {
                    String[] split = record.getStorePosition().split(",");
                    if (split.length >= 2) {
                        record.setStorePositionLongitude(split[0]);
                        record.setStorePositionLatitude(split[1]);
                    }
                }
                
                // 处理到期状态
                Date expirationTime = record.getExpirationTime();
                if (expirationTime != null) {
                    Calendar now = Calendar.getInstance();
                    Date nowCurrentDate = now.getTime();
                    now.add(Calendar.DAY_OF_YEAR, 30);
                    Date thirtyDaysLater = now.getTime();
                    
                    if (expirationTime.after(currentDate)) {
                        record.setExpiredState("0");
                        if ((expirationTime.after(nowCurrentDate) || expirationTime.equals(nowCurrentDate))
                                && expirationTime.before(thirtyDaysLater)) {
                            record.setExpiredState("1");
                        }
                    } else {
                        record.setExpiredState("2");
                    }
                    
                    LocalDate nowLocal = LocalDate.now();
                    LocalDate expDate = expirationTime.toInstant()
                            .atZone(ZoneId.systemDefault())
                            .toLocalDate();
                    long daysToExpire = ChronoUnit.DAYS.between(nowLocal, expDate);
                    record.setDaysToExpire(daysToExpire);
                }
                
                // 设置店铺得分
                if (!CollectionUtils.isEmpty(avgScoreMap) && avgScoreMap.containsKey(String.valueOf(record.getId()))) {
                    record.setAvgScore(String.valueOf(avgScoreMap.get(String.valueOf(record.getId())).get(0).get("avg_score")));
                } else {
                    record.setAvgScore("0");
                }
                
                // 设置总评论数
                if (!CollectionUtils.isEmpty(commentMap) && commentMap.containsKey(record.getId())) {
                    record.setTotalNum(String.valueOf(commentMap.get(record.getId()).size()));
                } else {
                    record.setTotalNum("0");
                }
            }
            
            log.info("根据店铺ID获取推荐店铺列表成功，storeId={}，返回店铺数量：{}", storeId, storeInfoVoList.size());
            return storeInfoVoList;
        } catch (Exception e) {
            log.error("根据店铺ID获取推荐店铺列表异常，storeId={}，异常信息：{}", storeId, e.getMessage(), e);
            throw new RuntimeException("获取推荐店铺列表失败：" + e.getMessage(), e);
        }
    }

    @Override
    public int uploadEntertainmentLicence(StoreImg storeImg) {
        storeImgMapper.delete(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 24).eq(StoreImg::getStoreId, storeImg.getStoreId()));
        storeImg.setImgType(24);
        storeImg.setImgDescription("娱乐经营许可证审核通过前图片");
        storeImgMapper.insert(storeImg);

        //更新店铺
        StoreInfo storeInfo = new StoreInfo();
        storeInfo.setEntertainmentLicenceStatus(2);
        storeInfo.setId(storeImg.getStoreId());
        storeInfo.setUpdateEntertainmentLicenceTime(new Date());

        // 从OCR识别记录中获取娱乐经营许可证到期时间（复用营业执照OCR类型，数据库中ocr_type存的是BUSINESS_LICENSE）
        if (StringUtils.isNotEmpty(storeImg.getImgUrl())) {
            OcrImageUpload entertainmentLicenceOcr = ocrImageUploadMapper.selectOne(
                    new LambdaQueryWrapper<OcrImageUpload>()
                            .eq(OcrImageUpload::getImageUrl, storeImg.getImgUrl())
                            .eq(OcrImageUpload::getOcrType, OcrTypeEnum.BUSINESS_LICENSE.getCode())
                            .orderByDesc(OcrImageUpload::getCreateTime)
                            .last("limit 1")
            );
            if (entertainmentLicenceOcr != null && StringUtils.isNotEmpty(entertainmentLicenceOcr.getOcrResult())) {
                try {
                    com.alibaba.fastjson2.JSONObject ocrResult = com.alibaba.fastjson2.JSONObject.parseObject(entertainmentLicenceOcr.getOcrResult());
                    // 解析娱乐经营许可证到期时间（优先validToDate，其次validPeriod）
                    Date expirationTime = parseEntertainmentLicenceExpirationDate(ocrResult);
                    if (expirationTime != null) {
                        storeInfo.setEntertainmentLicenceExpirationTime(expirationTime);
                        log.info("娱乐经营许可证OCR数据解析成功，门店ID：{}，到期时间：{}", storeImg.getStoreId(), expirationTime);
                    }
                } catch (Exception e) {
                    log.error("解析娱乐经营许可证OCR数据失败，门店ID：{}", storeImg.getStoreId(), e);
                }
            }
        }

        return storeInfoMapper.updateById(storeInfo);
    }

    @Override
    public Map<String, Object> getStoreEntertainmentLicenceStatus(int id) {
        Map<String, Object> map = new HashMap<>();
        StoreInfo storeInfo = storeInfoMapper.selectOne(new LambdaQueryWrapper<StoreInfo>().eq(StoreInfo::getId, id));
        //审核通过给前台反显未提交
        if (storeInfo.getEntertainmentLicenceStatus() == 1) {
            map.put("entertainmentLicenceStatus", 0);
        } else {
            map.put("entertainmentLicenceStatus", storeInfo.getEntertainmentLicenceStatus());
        }
        //娱乐经营许可证照片列表
        List<StoreImg> storeImgList = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, id).eq(StoreImg::getImgType, 24));
        if (!CollectionUtils.isEmpty(storeImgList)) {
            map.put("entertainmentLicenceImgList", storeImgList);
        } else {
            map.put("entertainmentLicenceImgList", "");
        }
        if (storeInfo.getEntertainmentLicenceReason() != null) {
            map.put("entertainmentLicenceReason", storeInfo.getEntertainmentLicenceReason());
        } else {
            map.put("entertainmentLicenceReason", "");
        }
        return map;
    }

    @Override
    public int entertainmentLicenceType(int id) {
        //删除原娱乐经营许可证照片
        LambdaUpdateWrapper<StoreImg> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(StoreImg::getStoreId, id);
        lambdaUpdateWrapper.eq(StoreImg::getImgType, 26);
        lambdaUpdateWrapper.set(StoreImg::getDeleteFlag, 1);
        storeImgMapper.update(null, lambdaUpdateWrapper);
        //修改娱乐经营许可证类型为审核通过类型
        List<StoreImg> storeImgList = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, id).eq(StoreImg::getImgType, 24));
        List<Integer> imgList = storeImgList.stream().map(StoreImg::getId).collect(Collectors.toList());
        LambdaUpdateWrapper<StoreImg> imgLambdaUpdateWrapper = new LambdaUpdateWrapper();
        imgLambdaUpdateWrapper.in(StoreImg::getId, imgList).set(StoreImg::getImgType, 26).set(StoreImg::getImgDescription, "娱乐经营许可证审核通过图片");
        int num = storeImgMapper.update(null, imgLambdaUpdateWrapper);
        return num;
    }

    /**
     * 解析食品经营许可证OCR结果中的到期时间
     * 食品经营许可证OCR返回字段：validToDate、standardizedValidToDate
     *
     * @param ocrResult OCR识别结果JSON对象
     * @return 到期日期，如果解析失败则返回null
     */
    private Date parseFoodLicenceExpirationDate(com.alibaba.fastjson2.JSONObject ocrResult) {
        if (ocrResult == null) {
            return null;
        }

        // 优先使用validToDate字段（格式可能为空或yyyyMMdd）
        String validToDate = ocrResult.getString("validToDate");
        if (StringUtils.isNotEmpty(validToDate)) {
            Date date = parseDateString(validToDate);
            if (date != null) {
                return date;
            }
        }

        // 其次使用standardizedValidToDate字段
        String standardizedValidToDate = ocrResult.getString("standardizedValidToDate");
        if (StringUtils.isNotEmpty(standardizedValidToDate)) {
            Date date = parseDateString(standardizedValidToDate);
            if (date != null) {
                return date;
            }
        }

        log.warn("食品经营许可证OCR结果中未找到有效的到期时间，validToDate={}，standardizedValidToDate={}", validToDate, standardizedValidToDate);
        return null;
    }

    /**
     * 解析娱乐经营许可证OCR结果中的到期时间（复用营业执照OCR类型）
     * 娱乐经营许可证OCR返回字段：validToDate(格式"20220903")、validPeriod(格式"2020年09月04日至2022年09月03日")
     *
     * @param ocrResult OCR识别结果JSON对象
     * @return 到期日期，如果解析失败则返回null
     */
    private Date parseEntertainmentLicenceExpirationDate(com.alibaba.fastjson2.JSONObject ocrResult) {
        if (ocrResult == null) {
            return null;
        }

        // 优先使用validToDate字段（格式为yyyyMMdd，如"20220903"）
        String validToDate = ocrResult.getString("validToDate");
        if (StringUtils.isNotEmpty(validToDate)) {
            Date date = parseDateString(validToDate);
            if (date != null) {
                return date;
            }
        }

        // 其次使用validPeriod字段（格式为"2020年09月04日至2022年09月03日"）
        String validPeriod = ocrResult.getString("validPeriod");
        if (StringUtils.isNotEmpty(validPeriod)) {
            Date date = parseValidPeriodEndDate(validPeriod);
            if (date != null) {
                return date;
            }
        }

        log.warn("娱乐经营许可证OCR结果中未找到有效的到期时间，validToDate={}，validPeriod={}", validToDate, validPeriod);
        return null;
    }


    /**
     * 解析营业执照OCR结果中的到期时间（复用营业执照OCR类型）
     * 营业执照OCR返回字段：validToDate(格式"20241217"或空)、validPeriod(可能为空)
     * 注意：营业执照的validToDate可能为空，表示长期有效
     *
     * @param ocrResult OCR识别结果JSON对象
     * @return 到期日期，如果解析失败或为长期有效则返回null
     */
    private Date parseBusinessLicenseExpirationDate(com.alibaba.fastjson2.JSONObject ocrResult) {
        if (ocrResult == null) {
            return null;
        }

        // 优先使用validToDate字段（格式为yyyyMMdd，如"20241217"，可能为空表示长期有效）
        String validToDate = ocrResult.getString("validToDate");
        if (StringUtils.isNotEmpty(validToDate)) {
            Date date = parseDateString(validToDate);
            if (date != null) {
                return date;
            }
        }

        // 其次使用validPeriod字段（格式为"2020年09月04日至2022年09月03日"，可能为空）
        String validPeriod = ocrResult.getString("validPeriod");
        if (StringUtils.isNotEmpty(validPeriod)) {
            Date date = parseValidPeriodEndDate(validPeriod);
            if (date != null) {
                return date;
            }
        }

        log.info("营业执照OCR结果中未找到有效的到期时间，validToDate={}，validPeriod={}，可能为长期有效", validToDate, validPeriod);
        return null;
    }

    /**
     * 解析日期字符串
     * 支持的格式：yyyyMMdd、yyyy-MM-dd、yyyy/MM/dd、yyyy年MM月dd日
     *
     * @param dateStr 日期字符串
     * @return 日期对象，如果解析失败则返回null
     */
    private Date parseDateString(String dateStr) {
        if (StringUtils.isEmpty(dateStr)) {
            return null;
        }

        // 处理"长期"或"永久"情况
        if (dateStr.contains("长期") || dateStr.contains("永久")) {
            return null;
        }

        String normalizedDateStr = dateStr.trim();

        // 如果包含中文年月日，转换格式
        if (normalizedDateStr.contains("年")) {
            normalizedDateStr = normalizedDateStr.replaceAll("[年月]", "-").replaceAll("日", "").trim();
        }

        // 尝试多种日期格式解析
        String[] dateFormats = {"yyyyMMdd", "yyyy-MM-dd", "yyyy/MM/dd"};
        for (String format : dateFormats) {
            try {
                SimpleDateFormat sdf = new SimpleDateFormat(format);
                sdf.setLenient(false);
                return sdf.parse(normalizedDateStr);
            } catch (Exception ignored) {
                // 尝试下一个格式
            }
        }

        log.warn("无法解析日期字符串: {}", dateStr);
        return null;
    }

    /**
     * 解析有效期字符串，获取结束日期
     * 支持的格式：
     * - "2020年09月04日至2022年09月03日"
     * - "2020-01-01至2025-12-31"
     * - "长期" 或 "永久" 返回null（表示长期有效）
     *
     * @param validPeriod 有效期字符串
     * @return 结束日期，如果解析失败或为长期有效则返回null
     */
    private Date parseValidPeriodEndDate(String validPeriod) {
        if (StringUtils.isEmpty(validPeriod)) {
            return null;
        }

        // 处理"长期"或"永久"情况
        if (validPeriod.contains("长期") || validPeriod.contains("永久")) {
            return null;
        }

        String endDateStr = validPeriod;

        // 如果包含"至"，取后半部分作为结束日期
        if (validPeriod.contains("至")) {
            String[] parts = validPeriod.split("至");
            if (parts.length >= 2) {
                endDateStr = parts[1].trim();
            }
        }

        return parseDateString(endDateStr);
    }

    /**
     * 保存身份证正反面图片到store_img表，并解析OCR结果设置过期时间和状态
     *
     * @param storeId   门店ID
     * @param storeUserId 店铺用户ID
     * @param storeInfo 门店信息对象（用于设置身份证状态和过期时间）
     */
    private void saveIdCardImages(Integer storeId, String storeUserId, StoreInfo storeInfo) {
        try {
            // 查询身份证OCR识别记录（根据storeUserId和ocrType=ID_CARD）
            List<OcrImageUpload> idCardOcrList = ocrImageUploadMapper.selectList(
                    new LambdaQueryWrapper<OcrImageUpload>()
                            .eq(OcrImageUpload::getStoreUserId, storeUserId)
                            .eq(OcrImageUpload::getOcrType, OcrTypeEnum.ID_CARD.getCode())
                            .orderByDesc(OcrImageUpload::getCreateTime)
            );

            if (CollectionUtils.isEmpty(idCardOcrList)) {
                log.info("未找到身份证OCR记录，storeUserId={}", storeUserId);
                // 没有OCR记录时，初始化状态为"未提交"（字典值0）
                storeInfo.setIdCardStatus(0);
                return;
            }

            String idCardFrontUrl = null;
            String idCardBackUrl = null;
            Date idCardExpirationTime = null;

            // 遍历OCR记录，区分正面和反面
            for (OcrImageUpload ocrRecord : idCardOcrList) {
                if (StringUtils.isEmpty(ocrRecord.getOcrResult())) {
                    continue;
                }

                try {
                    // 解析OCR结果JSON
                    com.alibaba.fastjson2.JSONObject ocrResultJson = com.alibaba.fastjson2.JSONObject.parseObject(ocrRecord.getOcrResult());

                    // 检查是正面还是反面
                    if (ocrResultJson.containsKey("face")) {
                        // 身份证正面
                        idCardFrontUrl = ocrRecord.getImageUrl();
                        log.info("找到身份证正面图片，URL={}", idCardFrontUrl);
                    } else if (ocrResultJson.containsKey("back")) {
                        // 身份证反面
                        idCardBackUrl = ocrRecord.getImageUrl();
                        log.info("找到身份证反面图片，URL={}", idCardBackUrl);

                        // 从反面OCR结果中提取有效期限
                        com.alibaba.fastjson2.JSONObject backData = ocrResultJson.getJSONObject("back");
                        if (backData != null) {
                            com.alibaba.fastjson2.JSONObject data = backData.getJSONObject("data");
                            if (data != null) {
                                String validPeriod = data.getString("validPeriod");
                                if (StringUtils.isNotEmpty(validPeriod)) {
                                    idCardExpirationTime = parseIdCardExpirationDate(validPeriod);
                                    if (idCardExpirationTime != null) {
                                        log.info("解析身份证有效期限成功，过期时间：{}", idCardExpirationTime);
                                    }
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    log.error("解析身份证OCR结果失败，ocrRecordId={}", ocrRecord.getId(), e);
                }
            }

            // 保存身份证正面图片到store_img表（img_type=33）
            if (StringUtils.isNotEmpty(idCardFrontUrl)) {
                StoreImg frontImg = new StoreImg();
                frontImg.setStoreId(storeId);
                frontImg.setImgType(33);
                frontImg.setImgSort(1);
                frontImg.setImgDescription("身份证正面");
                frontImg.setImgUrl(idCardFrontUrl);
                storeImgMapper.insert(frontImg);
                log.info("保存身份证正面图片成功，storeId={}, imgUrl={}", storeId, idCardFrontUrl);
            }

            // 保存身份证反面图片到store_img表（img_type=34）
            if (StringUtils.isNotEmpty(idCardBackUrl)) {
                StoreImg backImg = new StoreImg();
                backImg.setStoreId(storeId);
                backImg.setImgType(34);
                backImg.setImgSort(2);
                backImg.setImgDescription("身份证反面");
                backImg.setImgUrl(idCardBackUrl);
                storeImgMapper.insert(backImg);
                log.info("保存身份证反面图片成功，storeId={}, imgUrl={}", storeId, idCardBackUrl);
            }

            // 设置身份证状态和过期时间
            if (StringUtils.isNotEmpty(idCardFrontUrl) || StringUtils.isNotEmpty(idCardBackUrl)) {
                // 有身份证图片时，设置状态为"待审核"（字典值2，使用foodLicenceStatus字典）
                storeInfo.setIdCardStatus(2);
                storeInfo.setUpdateIdCardTime(new Date());
                if (idCardExpirationTime != null) {
                    storeInfo.setIdCardExpirationTime(idCardExpirationTime);
                }
                log.info("设置身份证状态为待审核，过期时间：{}", idCardExpirationTime);
            } else {
                // 没有身份证图片时，初始化状态为"未提交"（字典值0）
                storeInfo.setIdCardStatus(0);
            }

        } catch (Exception e) {
            log.error("保存身份证图片失败，storeId={}, storeUserId={}", storeId, storeUserId, e);
            // 发生异常时，初始化状态为"未提交"（字典值0）
            storeInfo.setIdCardStatus(0);
        }
    }

    /**
     * 解析身份证有效期限
     * 身份证OCR返回格式：validPeriod="2023.05.29-2033.05.29"
     *
     * @param validPeriod 有效期限字符串，格式："2023.05.29-2033.05.29"
     * @return 到期日期，如果解析失败则返回null
     */
    private Date parseIdCardExpirationDate(String validPeriod) {
        if (StringUtils.isEmpty(validPeriod)) {
            return null;
        }

        // 处理"长期"或"永久"情况
        if (validPeriod.contains("长期") || validPeriod.contains("永久")) {
            return null;
        }

        try {
            // 身份证格式：2023.05.29-2033.05.29，提取结束日期
            if (validPeriod.contains("-")) {
                String[] parts = validPeriod.split("-");
                if (parts.length >= 2) {
                    String endDateStr = parts[1].trim();
                    // 将 "2023.05.29" 格式转换为 "2023-05-29"
                    endDateStr = endDateStr.replace(".", "-");
                    return parseDateString(endDateStr);
                }
            }

            // 如果格式不匹配，尝试直接解析
            String normalizedDateStr = validPeriod.replace(".", "-");
            return parseDateString(normalizedDateStr);
        } catch (Exception e) {
            log.warn("解析身份证有效期限失败，validPeriod={}", validPeriod, e);
            return null;
        }
    }

    @Override
    public StoreInfoVo getClientStoreDetail(String storeId, String userId, String jingdu, String weidu) {
        StoreInfoVo result = new StoreInfoVo();
        StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
        if (storeInfo == null) {
            return null;
        }
        BeanUtils.copyProperties(storeInfo, result);
        //将经营板块和种类拆分成集合
        String businessTypes = storeInfo.getBusinessTypes();
        if (StringUtils.isNotEmpty(businessTypes)) {
            String[] split = businessTypes.split(",");
            List<String> list = Arrays.asList(split);
            result.setBusinessTypesList(list);
        }
        //存入用户账户
        StoreUser storeUser = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, storeId));
        if (storeUser != null) {
            result.setUserAccount(storeUser.getId().toString());
            result.setStorePhone(storeUser.getPhone());
            result.setStoreUserName(storeUser.getName());
            result.setIdCard(storeUser.getIdCard());
            result.setImgUrl(storeUser.getHeadImg());

        }
//        //存入执照图片地址
//        List<StoreImg> storeImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 14));
//        List<String> storeImgPaths = new ArrayList<>();
//        for (StoreImg storeImg : storeImgs) {
//            storeImgPaths.add(storeImg.getImgUrl());
//        }
//        result.setBusinessLicenseAddress(storeImgPaths);
//        //存入合同图片地址
//        List<StoreImg> storeContractImageImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 15));
//        List<String> storeContractImagePathImgs = new ArrayList<>();
//        for (StoreImg storeImg : storeContractImageImgs) {
//            storeContractImagePathImgs.add(storeImg.getImgUrl());
//        }
//        result.setContractImageList(storeContractImagePathImgs);
//        //存入续签合同地址
//        List<StoreImg> renewContractImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 22));
//        List<String> renewContractImagePathImgs = new ArrayList<>();
//        for (StoreImg storeImg : renewContractImgs) {
//            renewContractImagePathImgs.add(storeImg.getImgUrl());
//        }
//        result.setRenewContractImageList(renewContractImagePathImgs);
//        //存入经营许可证通过地址
//        List<StoreImg> foodLicenceImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 25));
//        List<String> foodLicenceImgsPathImgs = new ArrayList<>();
//        for (StoreImg storeImg : foodLicenceImgs) {
//            foodLicenceImgsPathImgs.add(storeImg.getImgUrl());
//        }
//        result.setFoodLicenceImageList(foodLicenceImgsPathImgs);
//        //存入经营许可证未通过地址
//        List<StoreImg> notPassFoodLicenceImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 24));
//        List<String> notPassFoodLicenceList = new ArrayList<>();
//        for (StoreImg storeImg : notPassFoodLicenceImgs) {
//            notPassFoodLicenceList.add(storeImg.getImgUrl());
//        }
//        result.setNotPassFoodLicenceImageList(notPassFoodLicenceList);
        // 存放商家入口图
        List<StoreImg> storeEntranceImageImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 1));
        if (!storeEntranceImageImgs.isEmpty()) {
            result.setEntranceImage(storeEntranceImageImgs.get(0).getImgUrl());
        } else {
            result.setEntranceImage("null");
        }
        // 存放商家头像
//        List<StoreImg> storeImgs1 = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 10));
//        if (!storeImgs1.isEmpty()) {
//            result.setImgUrl(storeImgs1.get(0).getImgUrl());
//        } else {
//            result.setImgUrl("null");
//        }

        // 获取店铺相册
        List<StoreImg> storeAlbumList = new ArrayList<>();
//        if (storeInfo.getImgMode() != null && storeInfo.getImgMode() == 0) {
//            storeAlbumList = storeImgService.getStoreImg(Integer.parseInt(storeId), 20);
//        } else {
//            storeAlbumList = storeImgService.getStoreImg(Integer.parseInt(storeId), 21);
//        }
         storeAlbumList = storeImgService.getStoreImg(Integer.parseInt(storeId), 38);

        if (!CollectionUtils.isEmpty(storeAlbumList)) {
            List<String> storeAlbumUrlList = storeAlbumList.stream().map(StoreImg::getImgUrl)  // 假设 StoreImg 有 getStoreUrl() 方法
                    .filter(url -> url != null && !url.trim().isEmpty())  // 过滤空值
                    .collect(Collectors.toList());
            // 相册首项为视频时，在列表首位插入商家入口图，供客户端展示封面
            String firstAlbumUrl = storeAlbumUrlList.get(0);
            if (isVideoUrl(firstAlbumUrl)) {
                String image = firstAlbumUrl + "?x-oss-process=video/snapshot,t_0,f_jpg,w_800,h_600,m_fast,ar_auto";
                storeAlbumUrlList.add(image);
            }
            result.setStoreAlbumUrlList(storeAlbumUrlList);
        } else {
            result.setStoreAlbumUrlList(new ArrayList<>());
        }

        // 设置经纬度
        result.setStorePositionLongitude(result.getStorePosition().split(",")[0]);
        result.setStorePositionLatitude(result.getStorePosition().split(",")[1]);
        // 设置距离
        if ((jingdu != null && !jingdu.isEmpty()) && (weidu != null && !weidu.isEmpty())) {
            /*double storeJing = Double.parseDouble(result.getStorePosition().split(",")[0]);
            double storeWei = Double.parseDouble(result.getStorePosition().split(",")[1]);
            double storeDistance = DistanceUtil.haversineCalculateDistance(Double.parseDouble(jingdu), Double.parseDouble(weidu), storeJing, storeWei);*/

            Double distance = storeInfoMapper.getStoreDistance(jingdu + "," + weidu, result.getId());

            result.setDistance(distance);
        }
        // 计算店铺到最近地铁站的距离
        JSONObject nearbySubway = gaoDeMapUtil.getNearbySubway(result.getStorePosition().split(",")[0], result.getStorePosition().split(",")[1]);
        // 地铁名
        String subWayName = nearbySubway.getString("name");
        result.setSubwayName(subWayName);
        // 地铁站经纬度
        String subWayJing = nearbySubway.getString("location") == null ? null : nearbySubway.getString("location").split(",")[0];
        String subWayWei = nearbySubway.getString("location") == null ? null : nearbySubway.getString("location").split(",")[1];
        if ((subWayJing != null && !subWayJing.isEmpty()) && (subWayWei != null && !subWayWei.isEmpty())) {
            double storeJing = Double.parseDouble(result.getStorePosition().split(",")[0]);
            double storeWei = Double.parseDouble(result.getStorePosition().split(",")[1]);
            double storeDistance2 = DistanceUtil.haversineCalculateDistance(Double.parseDouble(subWayJing), Double.parseDouble(subWayWei), storeJing, storeWei);
            result.setDistance2(storeDistance2);
        } else {
            result.setDistance2(0);
        }
        // 当前登录用户是否收藏
        LambdaUpdateWrapper<LifeCollect> shouCangWrapper = new LambdaUpdateWrapper<>();
        LifeCollectIdentityQuery.applyUserSide(shouCangWrapper, LifeCollectIdentityQuery.resolve(userId, typeUtil));
        shouCangWrapper.eq(LifeCollect::getStoreId, storeId);
        List<LifeCollect> shouCangList = lifeCollectMapper.selectList(shouCangWrapper);
        if (null == shouCangList || shouCangList.isEmpty()) {
            result.setCollection(0);
        } else {
            result.setCollection(1);
        }

        // 当前登录用户是否关注该店铺
        if (StringUtils.isNotEmpty(userId) && storeUser != null && StringUtils.isNotEmpty(storeUser.getPhone())) {
            try {
                // userId是用户ID（数字），查询用户信息获取手机号
                Integer userIdInt = Integer.parseInt(userId);
                LifeUser lifeUser = lifeUserMapper.selectById(userIdInt);
                
                if (lifeUser != null && StringUtils.isNotEmpty(lifeUser.getUserPhone())) {
                    // 构造关注关系：followed_id = "store_" + 店铺手机号，fans_id = "user_" + 用户手机号
                    String followedId = "store_" + storeUser.getPhone();
                    String fansId = "user_" + lifeUser.getUserPhone();

                    // 查询关注关系
                    LifeFansIdentityQuery.Scope fanScope = LifeFansIdentityQuery.resolve(fansId, typeUtil);
                    LifeFansIdentityQuery.Scope followedScope = LifeFansIdentityQuery.resolve(followedId, typeUtil);
                    LambdaQueryWrapper<LifeFans> fansWrapper = new LambdaQueryWrapper<>();
                    LifeFansIdentityQuery.applyPairWithDeleteFlag(fansWrapper, fanScope, followedScope);
                    LifeFans lifeFans = lifeFansMapper.selectOne(fansWrapper.last("LIMIT 1"));

                    if (lifeFans != null) {
                        result.setIsFollowed(1); // 已关注
                    } else {
                        result.setIsFollowed(0); // 未关注
                    }
                } else {
                    result.setIsFollowed(0); // 无法获取用户手机号，默认未关注
                }
            } catch (NumberFormatException e) {
                log.error("用户ID格式错误 - userId: {}, storeId: {}, error: {}", userId, storeId, e.getMessage());
                result.setIsFollowed(0); // 用户ID格式错误，默认未关注
            } catch (Exception e) {
                log.error("查询用户关注状态失败 - userId: {}, storeId: {}, error: {}", userId, storeId, e.getMessage(), e);
                result.setIsFollowed(0); // 查询失败，默认未关注
            }
        } else {
            result.setIsFollowed(0); // 用户ID或店铺信息为空，默认未关注
        }

        // 该用户的打卡记录（仅审核通过 check_flag=2）
        LambdaQueryWrapper<StoreClockIn> clockInWrapper = new LambdaQueryWrapper<>();
        clockInWrapper.eq(StoreClockIn::getUserId, userId);
//        clockInWrapper.eq(StoreClockIn::getCheckFlag, 2);
        List<StoreClockIn> clockInList = storeClockInMapper.selectList(clockInWrapper);

        List<StoreClockIn> clockStoreList = clockInList.stream().filter(item -> item.getStoreId() == Integer.parseInt(storeId)).collect(Collectors.toList());
        // 该用户是否在该店铺打过卡
        if (!clockStoreList.isEmpty()) {
            result.setClockInStore(1);
        } else {
            result.setClockInStore(0);
        }

        // 今天在该店铺是否打过卡
//        int today = (int) clockStoreList.stream().filter(item -> item.getCreatedTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().equals(LocalDate.now())).count();
        int today = clockStoreList.stream()
                .filter(item -> item.getCreatedTime() != null)
                .max(Comparator.comparing(StoreClockIn::getCreatedTime))
                .map(item -> Duration.between(item.getCreatedTime().toInstant(), Instant.now())
                        .compareTo(Duration.ofHours(24)) > 0 ? 1 : 0)
                .orElse(0);

        result.setClockInStoreToday(today);

        Integer totalCount = 0;
        Object ratingObj =  commonRatingService.getRatingCount(storeInfo.getId(), 1);
        if (ratingObj != null) {
            Map<String, Object> ratingMap = (Map<String, Object>) ratingObj;
            Object totalCountObj = ratingMap.get("totalCount");
            if (totalCountObj != null) {
                // 安全转换为整数
                try {
                    totalCount = Integer.parseInt(totalCountObj.toString().trim());
                } catch (NumberFormatException e) {
                    totalCount = 0; // 转换失败时默认值
                }
            } else {
                totalCount = 0;
            }
        }

        result.setCommitCount(totalCount.toString());

        // 在该店铺的打卡次数
        result.setClockInStoreNum(clockStoreList.size());

        // 该用户打卡的所有店铺次数（一个店铺只算一次）
        int clockInNum = (int) clockInList.stream().map(StoreClockIn::getStoreId).distinct().count();
        result.setClockInNum(clockInNum);

//        // 获取店铺动态列表
//        QueryWrapper<LifeUserDynamics> dynamicsWrapper = new QueryWrapper<>();
//        dynamicsWrapper.eq("phone_id", "store_" + result.getStorePhone()).orderByDesc("lud.created_time");
//        dynamicsWrapper.eq("lud.delete_flag", 0);
//
//        LambdaQueryWrapper<LifeBlacklist> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
//        lambdaQueryWrapper1.eq(LifeBlacklist :: getBlockerId, userId);
//        lambdaQueryWrapper1.eq(LifeBlacklist :: getBlockedPhoneId, "store_" + result.getStorePhone());
//        LifeBlacklist blacklist = lifeBlacklistMapper.selectOne(lambdaQueryWrapper1);
//        List<LifeUserDynamicsVo> storeDynamicslist = new ArrayList<>();

//        //判断没有拉黑当前门店账户 查出门店动态
//        if(blacklist == null){
//            storeDynamicslist = lifeUserDynamicsMapper.getStoreDynamicslist(userId, "store_" + result.getStorePhone());
//        }
//
//        List<String> followList = new ArrayList<>();
//        List<String> fansList = new ArrayList<>();

//        if (StringUtils.isNotEmpty(userId)) {
//            LifeUser lifeUser = lifeUserMapper.selectById(userId);
//            if (lifeUser != null && StringUtils.isNotEmpty(lifeUser.getUserPhone())) {
//                // 查询我的关注信息，构建关注者ID列表
//                LambdaQueryWrapper<LifeFans> lifeFansWrapper = new LambdaQueryWrapper<>();
//                lifeFansWrapper.eq(LifeFans::getFansId, "user_" + result.getStorePhone());
//                List<LifeFans> lifeFansList = lifeFansMapper.selectList(lifeFansWrapper);
//                if (!CollectionUtils.isEmpty(lifeFansList)) {
//                    followList = lifeFansList.stream().map(LifeFans::getFollowedId).collect(Collectors.toList());
//                }
//
//                // 查询我的粉丝信息，构建粉丝ID列表
//                lifeFansWrapper = new LambdaQueryWrapper<>();
//                lifeFansWrapper.eq(LifeFans::getFollowedId, "user_" + result.getStorePhone());
//                lifeFansList = lifeFansMapper.selectList(lifeFansWrapper);
//                if (!CollectionUtils.isEmpty(lifeFansList)) {
//                    fansList = lifeFansList.stream().map(LifeFans::getFansId).collect(Collectors.toList());
//                }
//            }
//        }

//        for (LifeUserDynamicsVo vo : storeDynamicslist) {
//            if (followList.contains(vo.getPhoneId())) {
//                vo.setIsFollowThis("1");
//            } else {
//                vo.setIsFollowThis("0");
//            }
//            if (fansList.contains(vo.getPhoneId())) {
//                vo.setIsFollowMe("1");
//            } else {
//                vo.setIsFollowMe("0");
//            }
//        }

//        // 返回动态最新的5条
//        List<LifeUserDynamicsVo> storeDynamicslist2 = storeDynamicslist.stream()
//                .limit(5).collect(Collectors.toList());
//        result.setDynamicsList(storeDynamicslist2);
//        //设置动态条数
//        Integer dynamicsNum = storeDynamicslist2.size();
//        result.setDynamicsNum(dynamicsNum);
//
//        // 获取店铺动态总数
//        result.setTotalDynamicsNum(storeDynamicslist.size());

        //营业时间（通过 getStoreInfoBusinessHours 方法获取，包含节假日信息）
        List<StoreBusinessInfoVo> storeBusinessInfoVos = this.getStoreInfoBusinessHours(Integer.parseInt(storeId));
        // 设置包含节假日信息的营业时间列表
        result.setStoreBusinessInfoVos(storeBusinessInfoVos);
        // 转换为 List<StoreBusinessInfo> 用于后续判断（StoreBusinessInfoVo 继承自 StoreBusinessInfo）
        List<StoreBusinessInfo> storeBusinessInfos = new ArrayList<>(storeBusinessInfoVos);
        // 回显所有营业时间信息（特殊营业时间和正常营业时间，包含节假日信息）
        if (ObjectUtils.isNotEmpty(storeBusinessInfos)) {
            result.setStoreBusinessInfo(storeBusinessInfos.get(0));
            result.setStoreBusinessInfos(storeBusinessInfos);
        }
        if(storeInfo.getBusinessStatus() == 0){
            // 调用提取的营业时间判断方法
            calculateBusinessStatus(storeId, storeBusinessInfos, result);
        } else {
            log.info("店铺营业状态不为0，不判断营业时间 - businessStatus: {}", storeInfo.getBusinessStatus());
        }

//        List<StoreBusinessInfo> storeBusinessInfos = storeBusinessInfoMapper.selectList(new LambdaQueryWrapper<StoreBusinessInfo>().eq(StoreBusinessInfo::getStoreId, storeId).eq(StoreBusinessInfo::getDeleteFlag, 0));
//        if (ObjectUtils.isNotEmpty(storeBusinessInfos)) {
//            result.setStoreBusinessInfo(storeBusinessInfos.get(0));
//            result.setStoreBusinessInfos(storeBusinessInfos);
//            StoreBusinessInfo storeBusinessInfo = result.getStoreBusinessInfos().stream().filter(item -> item.getBusinessType() == 1).findFirst().orElse(null);
//            if (ObjectUtils.isNotEmpty(storeBusinessInfo)) {
//
//                Calendar calendar = Calendar.getInstance(); // 获取Calendar实例
//                int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); // 获取星期几，注意Calendar中的DAY_OF_WEEK是从1（代表星期天）开始的
//                String[] days = {"7", "1", "2", "3", "4", "5", "6"};
//                String day = days[dayOfWeek - 1];
//                if (storeBusinessInfo.getBusinessDate().contains(day)) {
//                    if (StringUtils.isNotEmpty(storeBusinessInfo.getStartTime()) && StringUtils.isNotEmpty(storeBusinessInfo.getEndTime())) {
//                        LocalTime now = LocalTime.now();
//                        List<String> startList = Arrays.asList(storeBusinessInfo.getStartTime().split(":"));
//                        List<String> endList = Arrays.asList(storeBusinessInfo.getEndTime().split(":"));
//                        LocalTime start = LocalTime.of(Integer.parseInt(startList.get(0)), Integer.parseInt(startList.get(1)));
//                        LocalTime end = LocalTime.of(Integer.parseInt(endList.get(0)), Integer.parseInt(startList.get(1)));
//                        if (now.isAfter(start) && now.isBefore(end)) {
//                            result.setYyFlag(1);
//                        } else {
//                            result.setYyFlag(0);
//                        }
//                    }
//                } else {
//                    result.setYyFlag(0);
//                }
//            }
//        }
        LambdaQueryWrapper<StoreDictionary> storeDictionaryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        storeDictionaryLambdaQueryWrapper.eq(StoreDictionary::getTypeName, "businessStatus")
                .eq(StringUtils.isNotEmpty(result.getBusinessStatus().toString()), StoreDictionary::getDictId, result.getBusinessStatus());
        List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(storeDictionaryLambdaQueryWrapper);
        if (!storeDictionaries.isEmpty()) {
            result.setBusinessStatusStr(storeDictionaries.get(0).getDictDetail());
        }
        return result;
    }

    @Override
    public StoreInfoVo getStoreInfoVoWithDistanceFields(Integer storeId, String jingdu, String weidu) {
        if (storeId == null) {
            return null;
        }
        StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
        if (storeInfo == null) {
            return null;
        }
        StoreInfoVo result = new StoreInfoVo();
        BeanUtils.copyProperties(storeInfo, result);
        String storePosition = result.getStorePosition();
        if (StringUtils.isNotEmpty(storePosition) && storePosition.contains(",")) {
            String[] pos = storePosition.split(",");
            result.setStorePositionLongitude(pos[0]);
            result.setStorePositionLatitude(pos[1]);
            result.setLongitude(pos[0]);
            result.setLatitude(pos[1]);
        }
        // 用户经纬度存在时设置与用户距离（与 getClientStoreDetail 一致）
        if ((jingdu != null && !jingdu.isEmpty()) && (weidu != null && !weidu.isEmpty())) {
            Double distance = storeInfoMapper.getStoreDistance(jingdu + "," + weidu, result.getId());
            result.setDistance(distance != null ? distance : 0);
        }
        // 店铺到最近地铁站距离及地铁名（与 getClientStoreDetail 一致）
        if (StringUtils.isNotEmpty(storePosition) && storePosition.contains(",")) {
            String[] pos = storePosition.split(",");
            JSONObject nearbySubway = gaoDeMapUtil.getNearbySubway(pos[0], pos[1]);
            String subWayName = nearbySubway != null ? nearbySubway.getString("name") : null;
            result.setSubwayName(subWayName);
            String subWayJing = null;
            String subWayWei = null;
            if (nearbySubway != null && nearbySubway.getString("location") != null) {
                String[] loc = nearbySubway.getString("location").split(",");
                if (loc.length >= 2) {
                    subWayJing = loc[0];
                    subWayWei = loc[1];
                }
            }
            if (subWayJing != null && !subWayJing.isEmpty() && subWayWei != null && !subWayWei.isEmpty()) {
                double storeJing = Double.parseDouble(pos[0]);
                double storeWei = Double.parseDouble(pos[1]);
                double storeDistance2 = DistanceUtil.haversineCalculateDistance(Double.parseDouble(subWayJing), Double.parseDouble(subWayWei), storeJing, storeWei);
                result.setDistance2(storeDistance2);
            } else {
                result.setDistance2(0);
            }
        } else {
            result.setSubwayName(null);
            result.setDistance2(0);
        }
        // 门店位置/地址（与 getClientStoreDetail 及 LifeUserStoreService 一致）
        result.setStoreLocation(result.getStoreAddress());
        return result;
    }

    @Override
    public StoreBusinessStatusVo getStoreBusinessStatus(String storeId) {
        log.info("StoreInfoServiceImpl.getStoreBusinessStatus?storeId={}", storeId);
        StoreBusinessStatusVo result = new StoreBusinessStatusVo();
        
        StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
        if (storeInfo == null) {
            log.warn("店铺不存在，storeId={}", storeId);
            return result;
        }
        
        result.setBusinessStatus(storeInfo.getBusinessStatus());
        
        // 查询营业时间
        List<StoreBusinessInfo> storeBusinessInfos = storeBusinessInfoMapper.selectList(
                new LambdaQueryWrapper<StoreBusinessInfo>()
                        .eq(StoreBusinessInfo::getStoreId, storeId)
                        .eq(StoreBusinessInfo::getDeleteFlag, 0)
        );
        
        // 回显所有营业时间信息（特殊营业时间和正常营业时间）
        if (ObjectUtils.isNotEmpty(storeBusinessInfos)) {
            result.setStoreBusinessInfo(storeBusinessInfos.get(0));
            result.setStoreBusinessInfos(storeBusinessInfos);
        }
        
        // 判断营业状态
        if (storeInfo.getBusinessStatus() == 0) {
            // 调用提取的营业时间判断方法
            calculateBusinessStatus(storeId, storeBusinessInfos, result);
        } else {
            log.info("店铺营业状态不为0，不判断营业时间 - businessStatus: {}", storeInfo.getBusinessStatus());
            result.setYyFlag(0);
        }
        
        return result;
    }

    /**
     * 计算店铺营业状态
     * 判断当前时间是否在营业时间内，并设置营业状态和排序后的营业时间列表
     *
     * @param storeId 店铺ID
     * @param storeBusinessInfos 营业时间列表
     * @param result 结果对象（StoreInfoVo或StoreBusinessStatusVo）
     */
    private void calculateBusinessStatus(String storeId, List<StoreBusinessInfo> storeBusinessInfos, Object result) {
        // 优先判断当前时间是否是特殊日期
        LocalDate currentDate = LocalDate.now();
        LocalTime currentTime = LocalTime.now();

        log.info("开始判断营业状态 - 当前日期: {}, 当前时间: {}, 店铺ID: {}", currentDate, currentTime, storeId);

        // 标记当前是否是特殊营业时间
        boolean isCurrentSpecialBusinessTime = false;

        // 查找特殊营业时间（businessType == 2）
        StoreBusinessInfo specialBusinessInfo = storeBusinessInfos.stream()
                .filter(item -> item.getBusinessType() != null && item.getBusinessType() == 2)
                .filter(item -> {
                    // 判断当前日期是否匹配特殊日期
                    if (StringUtils.isEmpty(item.getBusinessDate())) {
                        return false;
                    }
                    try {
                        String businessDate = item.getBusinessDate().trim();

                        // 移除开头的数字和空格（如 "2 元旦、春节、儿童节" -> "元旦、春节、儿童节"）
                        String holidayNames = businessDate.replaceAll("^\\d+\\s*", "").trim();

                        // 判断是否包含节假日名称（支持所有特殊日期：元旦、春节、情人节、元宵节、清明节、劳动节、儿童节、端午节、七夕、中秋节、国庆节、冬至、平安夜、圣诞节）
                        boolean isHolidayName = holidayNames.contains("元旦") || holidayNames.contains("春节") ||
                            holidayNames.contains("情人节") || holidayNames.contains("元宵") ||
                            holidayNames.contains("七夕") || holidayNames.contains("冬至") ||
                            holidayNames.contains("平安夜") || holidayNames.contains("圣诞") ||
                            holidayNames.contains("清明") || holidayNames.contains("劳动") ||
                            holidayNames.contains("端午") || holidayNames.contains("中秋") ||
                            holidayNames.contains("国庆") || holidayNames.contains("儿童");

                        if (isHolidayName) {

                            List<LocalDate[]> holidayRanges = getHolidayDateRanges(currentDate.getYear(), holidayNames);
                            for (LocalDate[] range : holidayRanges) {
                                if (range != null && range.length == 2) {
                                    LocalDate startDate = range[0];
                                    LocalDate endDate = range[1];
                                    if (!currentDate.isBefore(startDate) && !currentDate.isAfter(endDate)) {
                                        log.info("特殊日期判断（节假日） - 节假日: {}, 日期范围: {}至{}, 当前日期: {}, 是否在范围内: true",
                                                holidayNames, startDate, endDate, currentDate);
                                        return true;
                                    }
                                }
                            }
                            log.info("特殊日期判断（节假日） - 节假日: {}, 当前日期: {}, 是否在范围内: false",
                                    holidayNames, currentDate);
                            return false;
                        }

                        // 如果不是节假日名称，尝试解析日期格式（兼容旧格式）
                        String[] dateFormats = {"yyyy-MM-dd", "yyyy/MM/dd", "yyyyMMdd"};

                        // 先检查是否包含"至"（日期范围）
                        if (businessDate.contains("至")) {
                            String[] dateRange = businessDate.split("至");
                            if (dateRange.length >= 2) {
                                try {
                                    LocalDate startDate = null;
                                    LocalDate endDate = null;
                                    for (String format : dateFormats) {
                                        try {
                                            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
                                            startDate = LocalDate.parse(dateRange[0].trim(), formatter);
                                            endDate = LocalDate.parse(dateRange[1].trim(), formatter);
                                            break;
                                        } catch (Exception ignored) {
                                        }
                                    }
                                    if (startDate != null && endDate != null) {
                                        boolean inRange = !currentDate.isBefore(startDate) && !currentDate.isAfter(endDate);
                                        log.info("特殊日期范围判断 - 日期范围: {}至{}, 当前日期: {}, 是否在范围内: {}",
                                                startDate, endDate, currentDate, inRange);
                                        return inRange;
                                    }
                                } catch (Exception e) {
                                    log.warn("解析特殊日期范围失败: {}", businessDate, e);
                                }
                            }
                        } else {
                            // 尝试解析单个日期格式
                            for (String format : dateFormats) {
                                try {
                                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
                                    LocalDate specialDate = LocalDate.parse(businessDate, formatter);
                                    boolean matches = specialDate.equals(currentDate);
                                    log.info("特殊日期判断 - 特殊日期: {}, 当前日期: {}, 是否匹配: {}",
                                            specialDate, currentDate, matches);
                                    if (matches) {
                                        return true;
                                    }
                                } catch (Exception ignored) {
                                    // 继续尝试下一个格式
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.warn("解析特殊日期失败: {}", item.getBusinessDate(), e);
                    }
                    return false;
                })
                .findFirst()
                .orElse(null);

        // 如果找到匹配的特殊日期，判断是否在营业时间内
        if (specialBusinessInfo != null) {
            log.info("找到匹配的特殊日期营业时间 - 开始时间: {}, 结束时间: {}",
                    specialBusinessInfo.getStartTime(), specialBusinessInfo.getEndTime());
            if (StringUtils.isNotEmpty(specialBusinessInfo.getStartTime())
                    && StringUtils.isNotEmpty(specialBusinessInfo.getEndTime())) {
                try {
                    String[] startArr = specialBusinessInfo.getStartTime().split(":");
                    String[] endArr = specialBusinessInfo.getEndTime().split(":");
                    if (startArr.length >= 2 && endArr.length >= 2) {
                        LocalTime start = LocalTime.of(
                                Integer.parseInt(startArr[0]),
                                Integer.parseInt(startArr[1])
                        );
                        LocalTime end = LocalTime.of(
                                Integer.parseInt(endArr[0]),
                                Integer.parseInt(endArr[1])
                        );

                        boolean isInBusiness;
                        // 判断是否是全天营业（00:00到00:00）
                        LocalTime midnight = LocalTime.of(0, 0);
                        if (start.equals(midnight) && end.equals(midnight)) {
                            // 全天营业
                            isInBusiness = true;
                            log.info("特殊日期营业时间判断 - 全天营业（00:00-00:00），当前时间: {}，是否在营业时间内: true", currentTime);
                        } else {
                            // 处理跨天营业
                            if (start.isBefore(end) || start.equals(end)) {
                                // 同一天营业：包含边界值
                                isInBusiness = (currentTime.isAfter(start) || currentTime.equals(start))
                                        && (currentTime.isBefore(end) || currentTime.equals(end));
                            } else {
                                // 跨天营业：包含边界值
                                isInBusiness = (currentTime.isAfter(start) || currentTime.equals(start))
                                        || (currentTime.isBefore(end) || currentTime.equals(end));
                            }
                            log.info("特殊日期营业时间判断 - 开始时间: {}, 结束时间: {}, 当前时间: {}, 是否在营业时间内: {}",
                                    start, end, currentTime, isInBusiness);
                        }

                        setYyFlag(result, isInBusiness ? 1 : 0);
                        isCurrentSpecialBusinessTime = isInBusiness;
                    } else {
                        log.warn("特殊日期营业时间格式错误 - 开始时间: {}, 结束时间: {}",
                                specialBusinessInfo.getStartTime(), specialBusinessInfo.getEndTime());
                        setYyFlag(result, 0);
                        isCurrentSpecialBusinessTime = false;
                    }
                } catch (NumberFormatException e) {
                    log.warn("解析特殊日期营业时间失败 - 开始时间: {}, 结束时间: {}",
                            specialBusinessInfo.getStartTime(), specialBusinessInfo.getEndTime(), e);
                    setYyFlag(result, 0);
                    isCurrentSpecialBusinessTime = false;
                }
            } else {
                log.warn("特殊日期营业时间为空 - 开始时间: {}, 结束时间: {}",
                        specialBusinessInfo.getStartTime(), specialBusinessInfo.getEndTime());
                setYyFlag(result, 0);
                isCurrentSpecialBusinessTime = false;
            }
        } else {
            // 如果不是特殊日期，判断正常营业时间（businessType == 1）
            StoreBusinessInfo normalBusinessInfo = storeBusinessInfos.stream()
                    .filter(item -> item.getBusinessType() != null && item.getBusinessType() == 1)
                    .findFirst()
                    .orElse(null);

            if (normalBusinessInfo != null) {
                log.info("判断正常营业时间 - 营业日期: {}, 开始时间: {}, 结束时间: {}",
                        normalBusinessInfo.getBusinessDate(),
                        normalBusinessInfo.getStartTime(),
                        normalBusinessInfo.getEndTime());
                // 获取当前星期并转换为业务格式
                Calendar calendar = Calendar.getInstance();
                int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); // 1=周日，2=周一...7=周六
                // 映射数组：索引对应dayOfWeek-1，值为中文星期
                String[] weekDaysCN = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
                String day = weekDaysCN[dayOfWeek - 1];

                log.info("当前星期: {}, 转换后: {}", dayOfWeek, day);

                // 判断当前日期是否在营业日期范围内
                if (StringUtils.isNotEmpty(normalBusinessInfo.getBusinessDate())
                        && normalBusinessInfo.getBusinessDate().contains(day)) {
                    log.info("当前星期在营业日期范围内");
                    if (StringUtils.isNotEmpty(normalBusinessInfo.getStartTime())
                            && StringUtils.isNotEmpty(normalBusinessInfo.getEndTime())) {
                        try {
                            String[] startArr = normalBusinessInfo.getStartTime().split(":");
                            String[] endArr = normalBusinessInfo.getEndTime().split(":");
                            if (startArr.length >= 2 && endArr.length >= 2) {
                                LocalTime start = LocalTime.of(
                                        Integer.parseInt(startArr[0]),
                                        Integer.parseInt(startArr[1])
                                );
                                LocalTime end = LocalTime.of(
                                        Integer.parseInt(endArr[0]),
                                        Integer.parseInt(endArr[1])
                                );

                                boolean isInBusiness;
                                // 判断是否是全天营业（00:00到00:00）
                                LocalTime midnight = LocalTime.of(0, 0);
                                if (start.equals(midnight) && end.equals(midnight)) {
                                    // 全天营业
                                    isInBusiness = true;
                                    log.info("正常营业时间判断 - 全天营业（00:00-00:00），当前时间: {}，是否在营业时间内: true", currentTime);
                                } else {
                                    // 处理跨天营业
                                    if (start.isBefore(end) || start.equals(end)) {
                                        // 同一天营业：包含边界值
                                        isInBusiness = (currentTime.isAfter(start) || currentTime.equals(start))
                                                && (currentTime.isBefore(end) || currentTime.equals(end));
                                    } else {
                                        // 跨天营业：包含边界值
                                        isInBusiness = (currentTime.isAfter(start) || currentTime.equals(start))
                                                || (currentTime.isBefore(end) || currentTime.equals(end));
                                    }
                                    log.info("正常营业时间判断 - 开始时间: {}, 结束时间: {}, 当前时间: {}, 是否在营业时间内: {}",
                                            start, end, currentTime, isInBusiness);
                                }

                                setYyFlag(result, isInBusiness ? 1 : 0);
                            } else {
                                log.warn("正常营业时间格式错误 - 开始时间: {}, 结束时间: {}",
                                        normalBusinessInfo.getStartTime(), normalBusinessInfo.getEndTime());
                                setYyFlag(result, 0);
                            }
                        } catch (NumberFormatException e) {
                            log.warn("解析正常营业时间失败 - 开始时间: {}, 结束时间: {}",
                                    normalBusinessInfo.getStartTime(), normalBusinessInfo.getEndTime(), e);
                            setYyFlag(result, 0);
                        }
                    } else {
                        log.warn("正常营业时间为空 - 开始时间: {}, 结束时间: {}",
                                normalBusinessInfo.getStartTime(), normalBusinessInfo.getEndTime());
                        setYyFlag(result, 0);
                    }
                } else {
                    log.info("当前星期不在营业日期范围内 - 营业日期: {}, 当前星期: {}",
                            normalBusinessInfo.getBusinessDate(), day);
                    setYyFlag(result, 0);
                }
            } else {
                log.warn("没有找到正常营业时间配置");
                setYyFlag(result, 0);
            }
        }
        
        Integer yyFlag = getYyFlag(result);
        log.info("最终营业状态 - yyFlag: {}", yyFlag);

        // 根据当前是否是特殊营业时间，对storeBusinessInfos进行排序
        if (ObjectUtils.isNotEmpty(storeBusinessInfos)) {
            final boolean isSpecial = isCurrentSpecialBusinessTime;
            List<StoreBusinessInfo> sortedBusinessInfos = storeBusinessInfos.stream()
                    .sorted((a, b) -> {
                        Integer typeA = a.getBusinessType() != null ? a.getBusinessType() : 0;
                        Integer typeB = b.getBusinessType() != null ? b.getBusinessType() : 0;

                        // 如果当前是特殊营业时间，businessType == 2 排在前面
                        if (isSpecial) {
                            if (typeA == 2 && typeB != 2) {
                                return -1; // a排在前面
                            } else if (typeA != 2 && typeB == 2) {
                                return 1; // b排在前面
                            }
                        } else {
                            // 如果当前不是特殊营业时间，businessType == 1 排在前面
                            if (typeA == 1 && typeB != 1) {
                                return -1; // a排在前面
                            } else if (typeA != 1 && typeB == 1) {
                                return 1; // b排在前面
                            }
                        }
                        // 相同类型，保持原有顺序
                        return 0;
                    })
                    .collect(Collectors.toList());

            // 重新设置排序后的列表
            setStoreBusinessInfos(result, sortedBusinessInfos);
            if (!sortedBusinessInfos.isEmpty()) {
                setStoreBusinessInfo(result, sortedBusinessInfos.get(0));
            }

            log.info("营业时间列表排序完成 - 当前是特殊营业时间: {}, 排序后第一个businessType: {}",
                    isSpecial, sortedBusinessInfos.isEmpty() ? "无" : sortedBusinessInfos.get(0).getBusinessType());
        }
    }

    /**
     * 设置yyFlag（支持StoreInfoVo和StoreBusinessStatusVo）
     */
    private void setYyFlag(Object result, Integer yyFlag) {
        if (result instanceof StoreInfoVo) {
            ((StoreInfoVo) result).setYyFlag(yyFlag);
        } else if (result instanceof StoreBusinessStatusVo) {
            ((StoreBusinessStatusVo) result).setYyFlag(yyFlag);
        }
    }

    /**
     * 获取yyFlag（支持StoreInfoVo和StoreBusinessStatusVo）
     */
    private Integer getYyFlag(Object result) {
        if (result instanceof StoreInfoVo) {
            return ((StoreInfoVo) result).getYyFlag();
        } else if (result instanceof StoreBusinessStatusVo) {
            return ((StoreBusinessStatusVo) result).getYyFlag();
        }
        return 0;
    }

    /**
     * 设置storeBusinessInfo（支持StoreInfoVo和StoreBusinessStatusVo）
     */
    private void setStoreBusinessInfo(Object result, StoreBusinessInfo storeBusinessInfo) {
        if (result instanceof StoreInfoVo) {
            ((StoreInfoVo) result).setStoreBusinessInfo(storeBusinessInfo);
        } else if (result instanceof StoreBusinessStatusVo) {
            ((StoreBusinessStatusVo) result).setStoreBusinessInfo(storeBusinessInfo);
        }
    }

    /**
     * 设置storeBusinessInfos（支持StoreInfoVo和StoreBusinessStatusVo）
     */
    private void setStoreBusinessInfos(Object result, List<StoreBusinessInfo> storeBusinessInfos) {
        if (result instanceof StoreInfoVo) {
            ((StoreInfoVo) result).setStoreBusinessInfos(storeBusinessInfos);
        } else if (result instanceof StoreBusinessStatusVo) {
            ((StoreBusinessStatusVo) result).setStoreBusinessInfos(storeBusinessInfos);
        }
    }

    @Override
    public List<LifeCouponVo> getStoreCouponList(String storeId) {
        // 获取店铺代金券列表
        LambdaUpdateWrapper<LifeCoupon> quanWrapper = new LambdaUpdateWrapper<>();
        quanWrapper.eq(LifeCoupon::getStoreId, storeId).eq(LifeCoupon::getStatus, CouponStatusEnum.ONGOING.getCode()).eq(LifeCoupon::getType, 1);
        List<LifeCoupon> quanList = lifeCouponMapper.selectList(quanWrapper);
        List<LifeCouponVo> quanVoList = new ArrayList<>();
        List<String> collect = quanList.stream().map(LifeCoupon::getId).collect(Collectors.toList());
        // 设置已售数量
        // 定义需要的订单状态集合
        Set<Integer> excludeStatuses = new HashSet<>(Arrays.asList(
                OrderStatusEnum.WAIT_PAY.getStatus(),
                OrderStatusEnum.WAIT_USE.getStatus(),
                OrderStatusEnum.USED.getStatus()
        ));
        if (!collect.isEmpty()) {
            List<LifeUserOrderVo> quanCount = lifeUserOrderMapper.getQuanCount(new QueryWrapper<LifeUserOrderVo>()
                    .eq("luo.store_id", storeId)
                    .eq("luo.coupon_type", CouponTypeEnum.COUPON.getCode())
                    .eq("luo.delete_flag", 0)
                    .in("ocm.status", excludeStatuses)
                    .groupBy("ocm.coupon_id"));
            quanList.forEach(a -> {
                LifeCouponVo lifeCouponVo = new LifeCouponVo();
                BeanUtils.copyProperties(a, lifeCouponVo);
                quanCount.forEach(item -> {
                    if (a.getId().equals(item.getCouponId().toString())) {
                        lifeCouponVo.setCount(item.getCount());
                    }
                });
                quanVoList.add(lifeCouponVo);
            });
        }
        return quanVoList;
    }

    @Override
    public StoreInfoVo getNewStoreDetail(String storeId) {

        StoreInfoVo result = new StoreInfoVo();
        StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
        if (storeInfo == null) {
            return null;
        }
        BeanUtils.copyProperties(storeInfo, result);
        //将经营板块和种类拆分成集合
        String businessTypes = storeInfo.getBusinessTypes();
        if (StringUtils.isNotEmpty(businessTypes)) {
            String[] split = businessTypes.split(",");
            List<String> list = Arrays.asList(split);
            result.setBusinessTypesList(list);
        }
        //存入用户账户
        StoreUser storeUser = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, storeId));
        if (storeUser != null) {
            result.setUserAccount(storeUser.getId().toString());
            result.setStorePhone(storeUser.getPhone());
            result.setStoreUserName(storeUser.getName());
            result.setIdCard(storeUser.getIdCard());
        }
        //存入执照图片地址
        List<StoreImg> storeImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 14));
        List<String> storeImgPaths = new ArrayList<>();
        for (StoreImg storeImg : storeImgs) {
            storeImgPaths.add(storeImg.getImgUrl());
        }
        result.setBusinessLicenseAddress(storeImgPaths);
        //存入合同图片地址
        List<StoreImg> storeContractImageImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 15));
        List<String> storeContractImagePathImgs = new ArrayList<>();
        for (StoreImg storeImg : storeContractImageImgs) {
            storeContractImagePathImgs.add(storeImg.getImgUrl());
        }
        result.setContractImageList(storeContractImagePathImgs);
        //存入续签合同地址
        List<StoreImg> renewContractImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 22));
        List<String> renewContractImagePathImgs = new ArrayList<>();
        for (StoreImg storeImg : renewContractImgs) {
            renewContractImagePathImgs.add(storeImg.getImgUrl());
        }
        result.setRenewContractImageList(renewContractImagePathImgs);
        //存入经营许可证通过地址
        List<StoreImg> foodLicenceImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 25));
        List<String> foodLicenceImgsPathImgs = new ArrayList<>();
        for (StoreImg storeImg : foodLicenceImgs) {
            foodLicenceImgsPathImgs.add(storeImg.getImgUrl());
        }
        result.setFoodLicenceImageList(foodLicenceImgsPathImgs);
        //存入经营许可证未通过地址
        List<StoreImg> notPassFoodLicenceImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 24));
        List<String> notPassFoodLicenceList = new ArrayList<>();
        for (StoreImg storeImg : notPassFoodLicenceImgs) {
            notPassFoodLicenceList.add(storeImg.getImgUrl());
        }
        result.setNotPassFoodLicenceImageList(notPassFoodLicenceList);
        // 存放商家入口图
        List<StoreImg> storeEntranceImageImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 1));
        if (!storeEntranceImageImgs.isEmpty()) {
            result.setEntranceImage(storeEntranceImageImgs.get(0).getImgUrl());
        } else {
            result.setEntranceImage("null");
        }
        // 存放商家头像
        List<StoreImg> storeImgs1 = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getStoreId, storeId).eq(StoreImg::getImgType, 10));
        if (!storeImgs1.isEmpty()) {
            result.setImgUrl(storeImgs1.get(0).getImgUrl());
        } else {
            result.setImgUrl("null");
        }


        // 店铺平均分
        /*Map<Object, List<Map<String, Object>>> avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream().collect(Collectors.groupingBy(o -> o.get("store_id")));
        if (avgScoreMap.containsKey(String.valueOf(result.getId()))) {
            result.setScore(Double.parseDouble(avgScoreMap.get(String.valueOf(result.getId())).get(0).get("avg_score").toString()));
        }*/

//        Map<String, Object> commitCountAndScore = storeCommentService.getCommitCountAndScore(null, 5, Integer.parseInt(storeId), null, null);
//        result.setScore(Double.parseDouble(commitCountAndScore.get("score").toString()));
//        result.setCommitCount(commitCountAndScore.get("commitCount").toString());
//


        //营业时间
        List<StoreBusinessInfo> storeBusinessInfos = storeBusinessInfoMapper.selectList(new LambdaQueryWrapper<StoreBusinessInfo>().eq(StoreBusinessInfo::getStoreId, storeId).eq(StoreBusinessInfo::getDeleteFlag, 0));
        if (ObjectUtils.isNotEmpty(storeBusinessInfos)) {
            result.setStoreBusinessInfo(storeBusinessInfos.get(0));
            result.setStoreBusinessInfos(storeBusinessInfos);
            //StoreBusinessInfo storeBusinessInfo = result.getStoreBusinessInfo();
            StoreBusinessInfo storeBusinessInfo = result.getStoreBusinessInfos().stream().filter(item -> item.getBusinessType() == 1).findFirst().orElse(null);
            if (ObjectUtils.isNotEmpty(storeBusinessInfo)) {

                Calendar calendar = Calendar.getInstance(); // 获取Calendar实例
                int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); // 获取星期几，注意Calendar中的DAY_OF_WEEK是从1（代表星期天）开始的
                String[] days = {"7", "1", "2", "3", "4", "5", "6"};
                String day = days[dayOfWeek - 1];
                if (storeBusinessInfo.getBusinessDate().contains(day)) {
                    if (StringUtils.isNotEmpty(storeBusinessInfo.getStartTime()) && StringUtils.isNotEmpty(storeBusinessInfo.getEndTime())) {
                        LocalTime now = LocalTime.now();
                        List<String> startList = Arrays.asList(storeBusinessInfo.getStartTime().split(":"));
                        List<String> endList = Arrays.asList(storeBusinessInfo.getEndTime().split(":"));
                        LocalTime start = LocalTime.of(Integer.parseInt(startList.get(0)), Integer.parseInt(startList.get(1)));
                        LocalTime end = LocalTime.of(Integer.parseInt(endList.get(0)), Integer.parseInt(startList.get(1)));
                        if (now.isAfter(start) && now.isBefore(end)) {
                            result.setYyFlag(1);
                        } else {
                            result.setYyFlag(0);
                        }
                    }
                } else {
                    result.setYyFlag(0);
                }
            }
        }
        LambdaQueryWrapper<StoreDictionary> storeDictionaryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        storeDictionaryLambdaQueryWrapper.eq(StoreDictionary::getTypeName, "businessStatus")
                .eq(StringUtils.isNotEmpty(result.getBusinessStatus().toString()), StoreDictionary::getDictId, result.getBusinessStatus());
        List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(storeDictionaryLambdaQueryWrapper);
        if (!storeDictionaries.isEmpty()) {
            result.setBusinessStatusStr(storeDictionaries.get(0).getDictDetail());
        }
        // TODO 之后修改********** 正常OcrType由前端传存储ocr表要加新字段。传参要由前端传。
        // 查询并设置各类证件OCR信息
        // 检查storeUser是否为null，避免空指针异常
        if (storeUser != null && storeUser.getId() != null) {
            result.setJyxkz(convertOcrResultToJson(storeUser.getId(), "BUSINESS_LICENSE", "营业执照", true));
            result.setIdcardFace(convertOcrResultToJson(storeUser.getId(), "ID_CARD", "face", true));
            result.setIdcardBack(convertOcrResultToJson(storeUser.getId(), "ID_CARD", "back", true));
            result.setFoodLicence(convertOcrResultToJson(storeUser.getId(), "FOOD_MANAGE_LICENSE", null, true));
            result.setEntertainmentLicence(convertOcrResultToJson(storeUser.getId(), "BUSINESS_LICENSE", "娱乐", false));
        }
        return result;
    }

    @Override
    public StoreInfoVo editNewStoreInfo(StoreInfoDto storeInfoDto) {

        //获取经营板块id
        Integer businessSection = storeInfoDto.getBusinessSection();
        //查询经营板块名称
        StoreDictionary businessSectionName = storeDictionaryMapper.selectOne(new LambdaQueryWrapper<StoreDictionary>().eq(StoreDictionary::getDictId, businessSection).eq(StoreDictionary::getTypeName, "business_section"));
        //查询经营种类
        List<String> businessTypes = storeInfoDto.getBusinessTypes();
        List<String> businessTypeNames = new ArrayList<>();
        //获取经营种类名称
        for (String businessType : businessTypes) {
            StoreDictionary storeDictionary = storeDictionaryMapper.selectOne(new LambdaQueryWrapper<StoreDictionary>().eq(StoreDictionary::getDictId, businessType).eq(StoreDictionary::getParentId, businessSectionName.getId()));
            businessTypeNames.add(storeDictionary.getDictDetail());
        }

        StoreInfoVo result = new StoreInfoVo();
        StoreInfo storeInfo = new StoreInfo();
        BeanUtils.copyProperties(storeInfoDto, storeInfo);
//        List<String> storeTypeList = storeInfoDto.getStoreTypeList();
//        String storeType = String.join(",", storeTypeList);
        //存入营运类型
//        storeInfo.setStoreType(storeType);

        //板块及类型
        storeInfo.setBusinessSection(businessSection);
        storeInfo.setBusinessSectionName(businessSectionName.getDictDetail());
        storeInfo.setBusinessTypes(String.join(",", businessTypes));
        storeInfo.setBusinessTypesName(String.join(",", businessTypeNames));

        //处理分类信息
        List<String> businessClassify = storeInfoDto.getBusinessClassify();
        if (!CollectionUtils.isEmpty(businessClassify)) {
            List<String> businessClassifyNames = new ArrayList<>();
            //批量查询分类名称
            List<StoreDictionary> classifyDicts = storeDictionaryMapper.selectList(
                    new LambdaQueryWrapper<StoreDictionary>()
                            .in(StoreDictionary::getDictId, businessClassify)
                            .eq(StoreDictionary::getTypeName, "business_classify")
                            .eq(StoreDictionary::getDeleteFlag, 0)
            );
            //转为Map方便快速获取
            Map<String, StoreDictionary> classifyDictMap = classifyDicts.stream()
                    .collect(Collectors.toMap(
                            dict -> dict.getDictId().toString(),
                            Function.identity(),
                            (existing, replacement) -> existing
                    ));
            //提取分类名称
            for (String classifyId : businessClassify) {
                StoreDictionary dict = classifyDictMap.get(classifyId);
                if (Objects.nonNull(dict)) {
                    businessClassifyNames.add(dict.getDictDetail());
                } else {
                    log.warn("无效的分类id：" + classifyId);
                }
            }
            storeInfo.setBusinessClassify(String.join(",", businessClassify));
            storeInfo.setBusinessClassifyName(String.join(",", businessClassifyNames));
        }

        storeInfoMapper.updateById(storeInfo);
        return result;
    }

    @Override
    public List<StoreDictionaryVo> getBusinessClassifyData(Integer parentId) {
        // 构建查询条件
        LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<StoreDictionary>()
                .eq(StoreDictionary::getTypeName, "business_classify")
                .eq(StoreDictionary::getDeleteFlag, 0)
                .orderByAsc(StoreDictionary::getDictId);

        // 如果指定了parentId，则只查询该父分类下的子分类
        if (parentId != null) {
            queryWrapper.eq(StoreDictionary::getParentId, parentId);
        } else {
            // 如果没有指定parentId，则查询所有子分类（parentId不为0或null的分类）
            queryWrapper.isNotNull(StoreDictionary::getParentId)
                    .ne(StoreDictionary::getParentId, 0);
        }

        // 查询字典数据
        List<StoreDictionary> allClassifies = storeDictionaryMapper.selectList(queryWrapper);

        // 构建扁平化的结果列表（仅返回子分类，用于多选功能）
        List<StoreDictionaryVo> result = new ArrayList<>();

        for (StoreDictionary classify : allClassifies) {
            StoreDictionaryVo vo = new StoreDictionaryVo();
            BeanUtils.copyProperties(classify, vo);
            // 不设置subDataList，返回扁平化列表
            result.add(vo);
        }
        return result;
    }

    @Override
    public Map<String, Object> getBusinessLicenseStatus(int id) {
        Map<String, Object> map = new HashMap<>();
        StoreInfo storeInfo = storeInfoMapper.selectOne(new LambdaQueryWrapper<StoreInfo>().eq(StoreInfo::getId, id));
        if (storeInfo == null) {
            return map;
        }
        
        // 审核通过给前台反显未提交
        if (storeInfo.getBusinessLicenseStatus() != null && storeInfo.getBusinessLicenseStatus() == 1) {
            map.put("businessLicenseStatus", 0);
        } else {
            map.put("businessLicenseStatus", storeInfo.getBusinessLicenseStatus() != null ? storeInfo.getBusinessLicenseStatus() : 0);
        }
        
        // 营业执照图片列表（img_type=14）
        List<StoreImg> businessLicenseImgList = storeImgMapper.selectList(
                new LambdaQueryWrapper<StoreImg>()
                        .eq(StoreImg::getStoreId, id)
                        .eq(StoreImg::getImgType, 14)
                        .eq(StoreImg::getDeleteFlag, 0)
                        .orderByAsc(StoreImg::getImgSort)
        );
        if (!CollectionUtils.isEmpty(businessLicenseImgList)) {
            map.put("businessLicenseImgList", businessLicenseImgList);
        } else {
            map.put("businessLicenseImgList", new ArrayList<>());
        }
        
        // 营业执照到期时间
        if (storeInfo.getBusinessLicenseExpirationTime() != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
            map.put("businessLicenseExpirationTime", sdf.format(storeInfo.getBusinessLicenseExpirationTime()));
        } else {
            map.put("businessLicenseExpirationTime", null);
        }
        
        // 拒绝原因
        if (StringUtils.isNotEmpty(storeInfo.getBusinessLicenseReason())) {
            map.put("businessLicenseReason", storeInfo.getBusinessLicenseReason());
        } else {
            map.put("businessLicenseReason", "");
        }
        
        return map;
    }

    @Override
    public int uploadBusinessLicense(StoreImg storeImg) {
        // 不再立即删除旧的营业执照图片，改为在审核通过后再删除
        // LambdaUpdateWrapper<StoreImg> deleteWrapper = new LambdaUpdateWrapper<>();
        // deleteWrapper.eq(StoreImg::getStoreId, storeImg.getStoreId())
        //         .eq(StoreImg::getImgType, 14)
        //         .set(StoreImg::getDeleteFlag, 1);
        // storeImgMapper.update(null, deleteWrapper);
        
        // 不再立即插入新的营业执照图片，等审核通过后再插入
        // 插入营业执照历史记录（licenseStatus=1表示营业执照，licenseExecuteStatus=2表示审核中）
        StoreLicenseHistory licenseHistory = new StoreLicenseHistory();
        licenseHistory.setStoreId(storeImg.getStoreId());
        licenseHistory.setLicenseStatus(1); // 1-营业执照
        licenseHistory.setLicenseExecuteStatus(2); // 2-审核中
        licenseHistory.setImgUrl(storeImg.getImgUrl());
        licenseHistory.setDeleteFlag(0);
        licenseHistoryMapper.insert(licenseHistory);
        
        // 更新店铺信息
        StoreInfo storeInfo = new StoreInfo();
        storeInfo.setId(storeImg.getStoreId());
        storeInfo.setBusinessLicenseStatus(2); // 2-待审核
        storeInfo.setUpdateBusinessLicenseTime(new Date());
        
        storeInfoMapper.updateById(storeInfo);
        
        // 异步调用证照审核AI接口并处理审核结果
        if (StringUtils.isNotEmpty(storeImg.getImgUrl())) {
            licenseAuditAsyncService.validateLicenseExpiryAndUpdate(storeImg.getStoreId(), 1, storeImg.getImgUrl());
        }
        
        return 1;
    }

    @Override
    public List<StoreLicenseHistory> getBusinessLicenseHistory(Integer storeId) {
        // 查询营业执照变更记录
        // 包括审核中的记录（licenseExecuteStatus=2）和已删除的记录
        return licenseHistoryMapper.selectList(
                new LambdaQueryWrapper<StoreLicenseHistory>()
                        .eq(StoreLicenseHistory::getStoreId, storeId)
                        .eq(StoreLicenseHistory::getLicenseStatus, 1) // 1-营业执照
                        .and(wrapper -> wrapper
                                // .eq(StoreLicenseHistory::getLicenseExecuteStatus, 2) // 审核中
                                // .or()
                                .eq(StoreLicenseHistory::getDeleteFlag, 0) // 未删除的记录
                        )
                        .orderByDesc(StoreLicenseHistory::getCreatedTime)
        );
    }

    @Override
    public Map<String, Object> getOtherQualificationStatus(int id) {
        Map<String, Object> map = new HashMap<>();
        StoreInfo storeInfo = storeInfoMapper.selectOne(new LambdaQueryWrapper<StoreInfo>().eq(StoreInfo::getId, id));
        if (storeInfo == null) {
            return map;
        }
        
        // 其他资质证明图片列表（img_type=35）
        List<StoreImg> otherQualificationImgList = storeImgMapper.selectList(
                new LambdaQueryWrapper<StoreImg>()
                        .eq(StoreImg::getStoreId, id)
                        .eq(StoreImg::getImgType, 35)
                        .eq(StoreImg::getDeleteFlag, 0)
                        .orderByAsc(StoreImg::getImgSort)
        );
        if (!CollectionUtils.isEmpty(otherQualificationImgList)) {
            map.put("otherQualificationImgList", otherQualificationImgList);
        } else {
            map.put("otherQualificationImgList", new ArrayList<>());
        }
        
        return map;
    }

    @Override
    public int uploadOtherQualification(List<StoreImg> storeImgList) {
        if (CollectionUtils.isEmpty(storeImgList)) {
            return 0;
        }
        
        // 获取门店ID
        Integer storeId = storeImgList.get(0).getStoreId();
        if (storeId == null) {
            throw new IllegalArgumentException("门店ID不能为空");
        }
        
        // 限制最多9张
        int maxCount = Math.min(storeImgList.size(), 9);
        
        // 不再立即删除旧的其他资质证明图片，等审核通过后再替换
        // LambdaUpdateWrapper<StoreImg> deleteWrapper = new LambdaUpdateWrapper<>();
        // deleteWrapper.eq(StoreImg::getStoreId, storeId)
        //         .eq(StoreImg::getImgType, 35)
        //         .set(StoreImg::getDeleteFlag, 1);
        // storeImgMapper.update(null, deleteWrapper);
        
        // 获取门店信息用于AI审核
        StoreInfo storeInfoForAi = storeInfoMapper.selectById(storeId);
        String merchantName = storeInfoForAi != null ? storeInfoForAi.getStoreName() : null;
        
        // 收集所有图片URL
        List<String> imgUrlList = new ArrayList<>();

        // 不再立即插入新的其他资质证明图片，等审核通过后再插入
        // 收集图片URL
        for (int i = 0; i < maxCount; i++) {
            StoreImg storeImg = storeImgList.get(i);
            if (StringUtils.isNotEmpty(storeImg.getImgUrl())) {
                imgUrlList.add(storeImg.getImgUrl());
            }
        }

        // 将所有图片URL合并存入一条store_license_history记录（用逗号分隔）
        if (!imgUrlList.isEmpty()) {
            String allImgUrls = String.join(",", imgUrlList);
            StoreLicenseHistory licenseHistory = new StoreLicenseHistory();
            licenseHistory.setStoreId(storeId);
            licenseHistory.setLicenseStatus(2); // 2-其他资质证明
            licenseHistory.setLicenseExecuteStatus(2); // 2-审核中
            licenseHistory.setImgUrl(allImgUrls);
            licenseHistory.setDeleteFlag(0);
            licenseHistoryMapper.insert(licenseHistory);
            
            // 异步调用证照审核AI接口并处理审核结果（每张图片都审核）
            for (String imgUrl : imgUrlList) {
                licenseAuditAsyncService.validateLicenseExpiryAndUpdate(storeId, 2, imgUrl);
            }
        }
        
        return maxCount;
    }

    @Override
    public List<StoreLicenseHistory> getOtherQualificationHistory(Integer storeId) {
        // 查询其他资质证明变更记录（licenseStatus=2表示其他资质证明）
        // 查询所有状态的记录：审核通过(1)、审核中(2)、审核拒绝(3)
        return licenseHistoryMapper.queryLicenceByStatusList(storeId, 2, 0);
    }

    @Override
    public StoreThreeLevelStructureVo getStoreThreeLevelStructure(Integer storeId) {
        // 1. 根据门店ID查询门店信息
        StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
        if (storeInfo == null) {
            log.warn("门店不存在，storeId={}", storeId);
            StoreThreeLevelStructureVo vo = new StoreThreeLevelStructureVo();
            vo.setStoreId(storeId);
            vo.setStoreName(null);
            vo.setThreeLevelStructure(new ArrayList<>());
            return vo;
        }

        // 2. 获取门店表里的三级分类信息
        Integer businessSection = storeInfo.getBusinessSection(); // 一级：经营板块ID
        String businessTypes = storeInfo.getBusinessTypes(); // 二级：经营种类IDs（逗号分隔，fine_food类型）
        String businessClassify = storeInfo.getBusinessClassify(); // 三级：分类IDs（逗号分隔）

        // 3. 查询一级分类（business_section - 经营板块）
        // business_section存储的是dictId（字符串），需要转换为String
        List<StoreDictionary> allDicts = new ArrayList<>();
        StoreDictionary firstLevelDict = null;
        if (businessSection != null) {
            firstLevelDict = storeDictionaryMapper.selectOne(
                    new LambdaQueryWrapper<StoreDictionary>()
                            .eq(StoreDictionary::getDictId, String.valueOf(businessSection))
                            .eq(StoreDictionary::getTypeName, "business_section")
                            .eq(StoreDictionary::getDeleteFlag, 0)
            );
            if (firstLevelDict != null) {
                allDicts.add(firstLevelDict);
                log.debug("查询到一级分类: id={}, dictId={}, dictDetail={}",
                        firstLevelDict.getId(), firstLevelDict.getDictId(), firstLevelDict.getDictDetail());
            } else {
                log.warn("未查询到一级分类，businessSection={}", businessSection);
            }
        }

        // 4. 查询二级分类（business_type - 根据门店表里的business_types字段，存储的是dictId）
        List<StoreDictionary> secondLevelDicts = new ArrayList<>();
        if (StringUtils.isNotEmpty(businessTypes) && firstLevelDict != null) {
            // 解析二级分类dictId列表（business_types存储的是dictId字符串）
            String[] typeDictIds = businessTypes.split(",");
            List<String> typeDictIdList = new ArrayList<>();
            for (String typeDictId : typeDictIds) {
                if (StringUtils.isNotEmpty(typeDictId.trim())) {
                    typeDictIdList.add(typeDictId.trim());
                }
            }

            // 查询二级分类，需要满足：
            // 1. dict_id 在门店配置的经营种类dictId列表中
            // 2. type_name = "business_type"
            // 3. parent_id = 一级分类的id（不是dictId）
            if (!typeDictIdList.isEmpty() && firstLevelDict != null) {
                LambdaQueryWrapper<StoreDictionary> secondLevelWrapper = new LambdaQueryWrapper<>();
                secondLevelWrapper.in(StoreDictionary::getDictId, typeDictIdList);
                secondLevelWrapper.eq(StoreDictionary::getTypeName, "business_type");
                secondLevelWrapper.eq(StoreDictionary::getParentId, firstLevelDict.getId());
                secondLevelWrapper.eq(StoreDictionary::getDeleteFlag, 0);
//                secondLevelWrapper.orderByAsc(StoreDictionary::getSortId);
                secondLevelDicts = storeDictionaryMapper.selectList(secondLevelWrapper);
                allDicts.addAll(secondLevelDicts);
                log.debug("查询到二级分类数量: {}, dictIds={}", secondLevelDicts.size(), typeDictIdList);
            } else {
                log.warn("无法查询二级分类: typeDictIdList为空或一级分类不存在, typeDictIdList={}, firstLevelDict={}",
                        typeDictIdList, firstLevelDict != null ? firstLevelDict.getId() : null);
            }
        }

        // 5. 查询三级分类（business_classify - 根据门店表里的business_classify字段，存储的是dictId）
        if (!secondLevelDicts.isEmpty() && StringUtils.isNotEmpty(businessClassify)) {
            // 解析三级分类dictId列表（business_classify存储的是dictId字符串）
            String[] classifyDictIds = businessClassify.split(",");
            List<String> classifyDictIdList = new ArrayList<>();
            for (String classifyDictId : classifyDictIds) {
                if (StringUtils.isNotEmpty(classifyDictId.trim())) {
                    classifyDictIdList.add(classifyDictId.trim());
                }
            }

            // 查询三级分类，需要满足：
            // 1. dict_id 在门店配置的分类dictId列表中
            // 2. parent_id 在二级分类的id列表中（不是dictId）
            // 3. type_name = "business_classify"
            if (!classifyDictIdList.isEmpty() && !secondLevelDicts.isEmpty()) {
                Set<Integer> secondLevelIds = secondLevelDicts.stream()
                        .map(StoreDictionary::getId)
                        .collect(Collectors.toSet());

                List<StoreDictionary> thirdLevelDicts = storeDictionaryMapper.selectList(
                        new LambdaQueryWrapper<StoreDictionary>()
                                .in(StoreDictionary::getDictId, classifyDictIdList)
                                .in(StoreDictionary::getParentId, secondLevelIds)
                                .eq(StoreDictionary::getTypeName, "business_classify")
                                .eq(StoreDictionary::getDeleteFlag, 0)
//                                .orderByAsc(StoreDictionary::getSortId)
                );
                allDicts.addAll(thirdLevelDicts);
                log.debug("查询到三级分类数量: {}, dictIds={}, parentIds={}",
                        thirdLevelDicts.size(), classifyDictIdList, secondLevelIds);
            } else {
                log.warn("无法查询三级分类: classifyDictIdList为空或二级分类为空, classifyDictIdList={}, secondLevelDicts.size={}",
                        classifyDictIdList, secondLevelDicts.size());
            }
        }

        // 6. 构建树形结构（根据parent_id关系组装）
        List<StoreDictionary> treeStructure = buildTreeOptimized(allDicts);

        // 7. 构建返回对象
        StoreThreeLevelStructureVo vo = new StoreThreeLevelStructureVo();
        vo.setStoreId(storeInfo.getId());
        vo.setStoreName(storeInfo.getStoreName());
        vo.setThreeLevelStructure(treeStructure);

        return vo;
    }


    /**
     * 查询七种类型店铺（酒吧、ktv、洗浴汗蒸、按摩足浴 、运动健身、丽人美发 、特色美食）并按距离筛选
     *
     * @param lon         经度
     * @param lat         纬度
     * @param distance    距离范围（单位：公里）
     * @param sortType    排序模式（1:智能排序，2:好评优先，3:距离优先）
     * @param businessType 店铺类型（KTV=3、洗浴汗蒸=4、按摩足浴=5，酒吧需要查询字典表），可选
     * @param categoryId  分类ID（二级或三级分类的dictId，从getAllBusinessSection接口获取），可选
     * @param storeName   店铺名称（模糊查询），可选
     * @param pageNum     页码
     * @param pageSize    页容
     * @return IPage<StoreInfoVo> 分页的门店信息列表
     */


    @Override
    public IPage<StoreInfoVo> getThreeCategoriesStoresByDistance(Double lon, Double lat, Double distance, Integer sortType, Integer businessType, Integer categoryId, String storeName,Integer storeType, int pageNum, int pageSize) {
        // 参数校验
        if (lon == null || lat == null) {
            throw new IllegalArgumentException("经纬度参数不能为空");
        }

        // 智能检测：如果参数可能传反了（lat超出范围但lon在范围内），给出提示
        if (Math.abs(lat) > 90 && Math.abs(lon) <= 90) {
            throw new IllegalArgumentException(
                    String.format("参数可能传反了！当前值: lon=%s, lat=%s。经度范围: [-180, 180]，纬度范围: [-90, 90]。请检查参数顺序。", lon, lat)
            );
        }

        // 校验经纬度范围：经度 [-180, 180]，纬度 [-90, 90]
        if (lon < -180 || lon > 180) {
            throw new IllegalArgumentException("经度参数超出有效范围 [-180, 180]，当前值: " + lon);
        }
        if (lat < -90 || lat > 90) {
            throw new IllegalArgumentException("纬度参数超出有效范围 [-90, 90]，当前值: " + lat);
        }
        final int finalSortType = (sortType == null || sortType < 1 || sortType > 3) ? 1 : sortType; // 默认智能排序
        if (pageNum <= 0) {
            pageNum = 1;
        }
        if (pageSize <= 0) {
            pageSize = 10;
        }

        // 构建查询条件
        QueryWrapper<StoreInfoVo> queryWrapper = new QueryWrapper<>();

        // 如果传入了dictId，根据字典id查询经营板块、经营种类、分类并匹配店铺
        if (categoryId != null) {
            // 根据categoryId查询字典表记录
            StoreDictionary dict = storeDictionaryMapper.selectById(categoryId);
            if (dict == null || dict.getDeleteFlag() == 1) {
                throw new IllegalArgumentException("字典id不存在或已删除: " + categoryId);
            }

            String typeName = dict.getTypeName();
            String dictIdStr = dict.getDictId();

            if ("business_section".equals(typeName)) {
                // 如果是经营板块，直接匹配business_section
                try {
                    Integer sectionId = Integer.parseInt(dictIdStr);
                    queryWrapper.eq("a.business_section", sectionId);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("经营板块dictId格式错误: " + dictIdStr);
                }
            } else if ("business_type".equals(typeName)) {
                // 如果是经营种类，需要：
                // 1. 向上查找父级（经营板块）
                // 2. 匹配business_section和business_types
                StoreDictionary parentDict = storeDictionaryMapper.selectById(dict.getParentId());
                if (parentDict == null || !"business_section".equals(parentDict.getTypeName())) {
                    throw new IllegalArgumentException("经营种类的父级不是经营板块，categoryId: " + categoryId);
                }

                try {
                    Integer sectionId = Integer.parseInt(parentDict.getDictId());
                    queryWrapper.eq("a.business_section", sectionId);
                    // 使用FIND_IN_SET匹配business_types字段（逗号分隔）
                    queryWrapper.apply("FIND_IN_SET({0}, a.business_types) > 0", dictIdStr);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("经营板块或经营种类dictId格式错误");
                }
            } else if ("business_classify".equals(typeName)) {
                // 如果是分类，需要：
                // 1. 向上查找父级（经营种类）
                // 2. 向上查找祖父级（经营板块）
                // 3. 匹配business_section、business_types和business_classify
                StoreDictionary parentDict = storeDictionaryMapper.selectById(dict.getParentId());
                if (parentDict == null || !"business_type".equals(parentDict.getTypeName())) {
                    throw new IllegalArgumentException("分类的父级不是经营种类，categoryId: " + categoryId);
                }

                StoreDictionary grandParentDict = storeDictionaryMapper.selectById(parentDict.getParentId());
                if (grandParentDict == null || !"business_section".equals(grandParentDict.getTypeName())) {
                    throw new IllegalArgumentException("经营种类的父级不是经营板块，categoryId: " + categoryId);
                }

                try {
                    Integer sectionId = Integer.parseInt(grandParentDict.getDictId());
                    queryWrapper.eq("a.business_section", sectionId);
                    // 使用FIND_IN_SET匹配business_types字段
                    queryWrapper.apply("FIND_IN_SET({0}, a.business_types) > 0", parentDict.getDictId());
                    // 使用FIND_IN_SET匹配business_classify字段
                    queryWrapper.apply("FIND_IN_SET({0}, a.business_classify) > 0", dictIdStr);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("经营板块、经营种类或分类dictId格式错误");
                }
            } else {
                throw new IllegalArgumentException("不支持的字典类型: " + typeName + ", categoryId: " + categoryId);
            }
        } else if (businessType != null) {
            // 如果指定了businessType，则根据传入的数值进行筛选
            // 直接使用传入的数值作为business_section进行筛选
            // KTV=3、洗浴汗蒸=4、按摩足浴=5，酒吧的数值未知（由调用方传入）
            queryWrapper.eq("a.business_section", businessType);
        } else {
            // 如果没有指定businessType，则查询所有四种类型的店铺
            // 需要查询字典表获取所有四种类型的dictId
//            List<String> storeTypeNames = Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足疗");
            List<String> storeTypeNames=new ArrayList<>();
            if (storeType !=null &&   storeType ==1 ){
                 storeTypeNames = Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足疗");
            } else if (storeType !=null &&   storeType==2) {
                 storeTypeNames = Arrays.asList("丽人美发", "运动健身");
            }else if ( storeType !=null && storeType==3) {
                 storeTypeNames = Arrays.asList("特色美食");
            }


            List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(
                    new LambdaQueryWrapper<StoreDictionary>()
                            .eq(StoreDictionary::getTypeName, "business_section")
                            .in(StoreDictionary::getDictDetail, storeTypeNames)
                            .eq(StoreDictionary::getDeleteFlag, 0)
            );

            List<Integer> businessSectionIds = storeDictionaries.stream()
                    .filter(d -> StringUtils.isNotEmpty(d.getDictId()))
                    .map(StoreDictionary::getDictId)
                    .map(dictIdStr -> {
                        try {
                            return Integer.parseInt(dictIdStr);
                        } catch (NumberFormatException e) {
                            return null;
                        }
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());

            // 使用business_section字段进行筛选
            queryWrapper.in("a.business_section", businessSectionIds);
        }

        // 过滤已删除的门店
        queryWrapper.eq("a.delete_flag", 0);
        // 过滤注销的门店
        queryWrapper.eq("a.logout_flag", 0);
        // 过滤禁用的门店
        queryWrapper.ne("a.store_status", 0);
        // 过滤永久关门的店铺
        queryWrapper.ne("a.business_status", 99);
        // 过滤过期的经营许可证
//        queryWrapper.ge("a.entertainment_licence_expiration_time", new Date());
        // 添加一个模糊查询，根据店铺名称进行查询
        if (StringUtils.isNotEmpty(storeName)) {
            queryWrapper.like("a.store_name", storeName);
        }

        // 距离优先模式：只显示10公里内且3.5星以上的店铺
        final Double finalDistance;
        if (finalSortType == 3) {
            queryWrapper.ge("a.score_avg", 3.5);
            if (distance == null || distance <= 0) {
                finalDistance = 10.0; // 默认10公里
            } else if (distance > 10) {
                finalDistance = 10.0; // 距离优先最多10公里
            } else {
                finalDistance = distance;
            }
        } else {
            finalDistance = distance;
        }

        // 先按距离排序获取所有数据（用于计算距离）
        queryWrapper.orderByAsc("dist");

        // 创建分页对象（先获取更多数据用于排序计算）
        IPage<StoreInfoVo> page = new Page<>(1, 1000); // 先获取足够多的数据
        IPage<StoreInfoVo> storeInfoIPage = storeInfoMapper.getPageForDistance(page, lon + "," + lat, queryWrapper);
        List<StoreInfoVo> storeInfoVoList = storeInfoIPage.getRecords();

        // 如果指定了距离范围，进行距离筛选
        if (finalDistance != null && finalDistance > 0) {
            storeInfoVoList = storeInfoVoList.stream()
                    .filter(store -> {
                        String distStr = store.getDist();
                        if (distStr == null || distStr.isEmpty()) {
                            return false;
                        }
                        try {
                            double storeDistance = Double.parseDouble(distStr);
                            return storeDistance <= finalDistance;
                        } catch (NumberFormatException e) {
                            return false;
                        }
                    })
                    .collect(Collectors.toList());
        }

        // 计算时间范围
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime sevenDaysAgo = now.minusDays(7);
        LocalDateTime thirtyDaysAgo = now.minusDays(30);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String sevenDaysAgoStr = sevenDaysAgo.format(formatter);
        String thirtyDaysAgoStr = thirtyDaysAgo.format(formatter);

        // 提取所有门店ID
        List<Integer> storeIds = storeInfoVoList.stream().map(StoreInfoVo::getId).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(storeIds)) {
            // 如果没有符合条件的店铺，返回空结果
            IPage<StoreInfoVo> emptyPage = new Page<>(pageNum, pageSize);
            emptyPage.setRecords(new ArrayList<>());
            emptyPage.setTotal(0);
            return emptyPage;
        }

        // 查询近7天销量（订单数）
        Map<Integer, Long> sales7DaysMap = new HashMap<>();
        if (finalSortType == 1) { // 智能排序需要销量数据
            LambdaQueryWrapper<LifeUserOrder> orderWrapper = new LambdaQueryWrapper<>();
            orderWrapper.in(LifeUserOrder::getStoreId, storeIds)
                    .and(w -> w.and(w1 -> w1.eq(LifeUserOrder::getStatus, 7)
                                    .ge(LifeUserOrder::getFinishTime, sevenDaysAgoStr))
                            .or(w2 -> w2.eq(LifeUserOrder::getStatus, 1)
                                    .ge(LifeUserOrder::getPayTime, sevenDaysAgoStr)))
                    .eq(LifeUserOrder::getDeleteFlag, 0);
            List<LifeUserOrder> orders7Days = lifeUserOrderMapper.selectList(orderWrapper);
            Map<Integer, Long> tempSalesMap = orders7Days.stream()
                    .filter(order -> order.getStoreId() != null)
                    .collect(Collectors.groupingBy(
                            order -> Integer.parseInt(order.getStoreId()),
                            Collectors.counting()));
            sales7DaysMap.putAll(tempSalesMap);
        }

        // 查询近30天好评数（score >= 4.5）
        Map<Integer, Long> goodComment30DaysMap = new HashMap<>();
        // 查询近7天评论数
        Map<Integer, Long> comment7DaysMap = new HashMap<>();
        // 查询总评论数
        Map<Integer, Long> totalCommentMap = new HashMap<>();

        if (finalSortType == 2) { // 好评优先需要评论数据
            // 近30天好评数
            LambdaQueryWrapper<StoreComment> goodCommentWrapper = new LambdaQueryWrapper<>();
            goodCommentWrapper.in(StoreComment::getStoreId, storeIds)
                    .eq(StoreComment::getBusinessType, 5)
                    .eq(StoreComment::getDeleteFlag, 0)
                    .isNull(StoreComment::getReplyId)
                    .ge(StoreComment::getScore, 4.5)
                    .ge(StoreComment::getCreatedTime, thirtyDaysAgoStr);
            List<StoreComment> goodComments30Days = storeCommentMapper.selectList(goodCommentWrapper);
            Map<Integer, Long> tempGoodCommentMap = goodComments30Days.stream()
                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
            goodComment30DaysMap.putAll(tempGoodCommentMap);

            // 近7天评论数
            LambdaQueryWrapper<StoreComment> comment7DaysWrapper = new LambdaQueryWrapper<>();
            comment7DaysWrapper.in(StoreComment::getStoreId, storeIds)
                    .eq(StoreComment::getBusinessType, 5)
                    .eq(StoreComment::getDeleteFlag, 0)
                    .isNull(StoreComment::getReplyId)
                    .ge(StoreComment::getCreatedTime, sevenDaysAgoStr);
            List<StoreComment> comments7Days = storeCommentMapper.selectList(comment7DaysWrapper);
            Map<Integer, Long> tempComment7DaysMap = comments7Days.stream()
                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
            comment7DaysMap.putAll(tempComment7DaysMap);

            // 总评论数
            LambdaQueryWrapper<StoreComment> totalCommentWrapper = new LambdaQueryWrapper<>();
            totalCommentWrapper.in(StoreComment::getStoreId, storeIds)
                    .eq(StoreComment::getBusinessType, 5)
                    .eq(StoreComment::getDeleteFlag, 0)
                    .isNull(StoreComment::getReplyId);
            List<StoreComment> totalComments = storeCommentMapper.selectList(totalCommentWrapper);
            Map<Integer, Long> tempTotalCommentMap = totalComments.stream()
                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
            totalCommentMap.putAll(tempTotalCommentMap);
        }

        // 获取全部店铺的评分
        Map<String, List<Map<String, Object>>> avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream()
                .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
        Map<String, List<Map<String, Object>>> avgPriceMap = lifeUserOrderMapper.allStoreAvgPrice().stream()
                .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));

        // 计算综合得分并排序
        List<StoreInfoVo> sortedList = storeInfoVoList.stream()
                .map(store -> {
                    // 获取基础评分（score_avg × 2，标准化为0-10分）
                    Double scoreAvg = store.getScoreAvg() != null ? store.getScoreAvg() : 0.0;
                    double baseScore = Math.min(scoreAvg * 2, 10.0); // 基础评分，最高10分

                    // 获取距离
                    double storeDistance = 999999;
                    try {
                        String distStr = store.getDist();
                        if (distStr != null && !distStr.isEmpty()) {
                            storeDistance = Double.parseDouble(distStr);
                        }
                    } catch (NumberFormatException e) {
                        // 忽略
                    }

                    double finalScore = 0.0;

                    if (finalSortType == 1) {
                        // 智能排序：综合评分×50% + 近7天销量×30% + 距离得分×20%
                        // 综合评分（基础评分）
                        double scorePart = baseScore * 0.5;

                        // 近7天销量（需要标准化，假设最大销量为100）
                        long sales7Days = sales7DaysMap.getOrDefault(store.getId(), 0L);
                        double salesScore = Math.min(sales7Days / 100.0 * 10, 10.0); // 标准化到0-10
                        double salesPart = salesScore * 0.3;

                        // 距离得分（距离越近得分越高，10公里内计算）
                        double distanceScore = storeDistance <= 10 ? (10 - storeDistance) / 10.0 * 10 : 0;
                        double distancePart = distanceScore * 0.2;

                        finalScore = scorePart + salesPart + distancePart;
                    } else if (finalSortType == 2) {
                        // 好评优先：综合评分×50% + 近30天好评数×35% + 近7天新评占比×15%
                        double scorePart = baseScore * 0.5;

                        // 近30天好评数（需要标准化，假设最大好评数为50）
                        long goodComment30Days = goodComment30DaysMap.getOrDefault(store.getId(), 0L);
                        double goodCommentScore = Math.min(goodComment30Days / 50.0 * 10, 10.0);
                        double goodCommentPart = goodCommentScore * 0.35;

                        // 近7天新评占比
                        long comment7Days = comment7DaysMap.getOrDefault(store.getId(), 0L);
                        long totalComment = totalCommentMap.getOrDefault(store.getId(), 1L); // 避免除0
                        double newCommentRatio = (double) comment7Days / totalComment;
                        double newCommentPart = newCommentRatio * 10 * 0.15; // 占比转换为0-10分

                        finalScore = scorePart + goodCommentPart + newCommentPart;
                    } else if (finalSortType == 3) {
                        // 距离优先：距离得分 = (10 - 实际距离) × 80% + 基础评分 × 20%（10公里内计算）
                        if (storeDistance <= 10) {
                            double distanceScore = (10 - storeDistance) / 10.0 * 10; // 标准化到0-10
                            double distancePart = distanceScore * 0.8;
                            double scorePart = baseScore * 0.2;
                            finalScore = distancePart + scorePart;
                        } else {
                            finalScore = -1; // 超出范围，不展示
                        }
                    }

                    // 设置综合得分（用于排序）
                    store.setDistance(storeDistance);
                    // 使用反射或扩展字段存储finalScore，这里我们使用一个临时字段
                    // 由于StoreInfoVo没有finalScore字段，我们使用distance字段临时存储，排序后再恢复
                    return new Object[]{store, finalScore};
                })
                .filter(item -> {
                    // 距离优先模式：过滤掉超出范围的
                    if (finalSortType == 3) {
                        return ((Double) item[1]) >= 0;
                    }
                    return true;
                })
                .sorted((a, b) -> Double.compare((Double) b[1], (Double) a[1])) // 按得分降序
                .map(item -> (StoreInfoVo) item[0])
                .collect(Collectors.toList());

        // 分页处理
        long total = sortedList.size();
        int start = (pageNum - 1) * pageSize;
        int end = Math.min(start + pageSize, sortedList.size());
        List<StoreInfoVo> pagedList;
        if (start < sortedList.size()) {
            pagedList = sortedList.subList(start, end);
        } else {
            pagedList = new ArrayList<>();
        }

        // 查询每个店铺的最新代金券（只显示一个，最新创建的）
        Map<Integer, LifeCoupon> latestCouponMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(pagedList)) {
            List<Integer> pagedStoreIds = pagedList.stream().map(StoreInfoVo::getId).collect(Collectors.toList());
            // 查询所有店铺的代金券，按创建时间降序
            LambdaQueryWrapper<LifeCoupon> couponWrapper = new LambdaQueryWrapper<>();
            couponWrapper.in(LifeCoupon::getStoreId, pagedStoreIds.stream().map(String::valueOf).collect(Collectors.toList()))
                    .eq(LifeCoupon::getStatus, CouponStatusEnum.ONGOING.getCode())
                    .eq(LifeCoupon::getType, 1) // 代金券类型
                    .eq(LifeCoupon::getDeleteFlag, 0)
                    .orderByDesc(LifeCoupon::getCreatedTime);
            List<LifeCoupon> allCoupons = lifeCouponMapper.selectList(couponWrapper);

            // 为每个店铺只保留最新创建的一个代金券
            for (LifeCoupon coupon : allCoupons) {
                if (coupon.getStoreId() != null) {
                    try {
                        Integer storeId = Integer.parseInt(coupon.getStoreId());
                        // 如果该店铺还没有代金券，或者当前代金券更新，则更新
                        if (!latestCouponMap.containsKey(storeId)) {
                            latestCouponMap.put(storeId, coupon);
                        }
                    } catch (NumberFormatException e) {
                        // 忽略无效的storeId
                    }
                }
            }
        }

        // 设置评分、平均消费和代金券
        for (StoreInfoVo store : pagedList) {
            if (avgScoreMap.containsKey(String.valueOf(store.getId()))) {
                store.setAvgScore(new BigDecimal(avgScoreMap.get(String.valueOf(store.getId())).get(0).get("avg_score").toString())
                        .setScale(1, RoundingMode.HALF_UP).toString());
                store.setTotalNum(avgScoreMap.get(String.valueOf(store.getId())).get(0).get("total_num").toString());
            } else {
                store.setAvgScore("0");
                store.setTotalNum("0");
            }

            if (avgPriceMap.containsKey(String.valueOf(store.getId()))) {
                store.setAvgPrice(avgPriceMap.get(String.valueOf(store.getId())).get(0).get("avg_price").toString());
            } else {
                store.setAvgPrice("0");
            }

            // 设置最新代金券（只显示一个）
            if (latestCouponMap.containsKey(store.getId())) {
                LifeCoupon latestCoupon = latestCouponMap.get(store.getId());
                LifeCouponVo couponVo = new LifeCouponVo();
                BeanUtils.copyProperties(latestCoupon, couponVo);
                // 只设置一个代金券到列表中
                List<LifeCouponVo> couponList = new ArrayList<>();
                couponList.add(couponVo);
                store.setCouponList(couponList);
            } else {
                // 如果没有代金券，设置为空列表
                store.setCouponList(new ArrayList<>());
            }
        }

        // 创建分页对象
        IPage<StoreInfoVo> resultPage = new Page<>(pageNum, pageSize);
        resultPage.setRecords(pagedList);
        resultPage.setTotal(total);
        resultPage.setCurrent(pageNum);
        resultPage.setSize(pageSize);
        resultPage.setPages((total + pageSize - 1) / pageSize);

        return resultPage;
    }

    /**
     * 根据节假日名称获取当前年度的日期范围
     *
     * @param year 年份
     * @param holidayNames 节假日名称，如"元旦、春节、儿童节"
     * @return 节假日日期范围列表，每个元素是一个数组[开始日期, 结束日期]
     */
    private List<LocalDate[]> getHolidayDateRanges(int year, String holidayNames) {
        List<LocalDate[]> ranges = new ArrayList<>();

        if (StringUtils.isEmpty(holidayNames)) {
            return ranges;
        }

        // 分割节假日名称（支持多种分隔符：、, ,）
        String[] holidays = holidayNames.split("[、,，]");

        for (String holiday : holidays) {
            String holidayName = holiday.trim();
            if (StringUtils.isEmpty(holidayName)) {
                continue;
            }

            LocalDate[] range = getHolidayDateRange(year, holidayName);
            if (range != null && range.length == 2) {
                ranges.add(range);
            }
        }

        return ranges;
    }

    /**
     * 根据单个节假日名称获取当前年度的日期范围
     *
     * @param year 年份
     * @param holidayName 节假日名称，如"元旦"、"春节"、"国庆"、"儿童节"等
     * @return 节假日日期范围 [开始日期, 结束日期]
     */
    private LocalDate[] getHolidayDateRange(int year, String holidayName) {
        String name = holidayName.trim();

        try {
            if (name.contains("元旦")) {
                return new LocalDate[]{
                    LocalDate.of(year, 1, 1),
                    LocalDate.of(year, 1, 3)
                };
            }

            if (name.contains("春节")) {
                if (year == 2028) {
                    return new LocalDate[]{
                        LocalDate.of(year, 1, 25),
                        LocalDate.of(year, 2, 2)
                    };
                } else if (year == 2027) {
                    return new LocalDate[]{
                        LocalDate.of(year, 2, 5),
                        LocalDate.of(year, 2, 13)
                    };
                } else if (year == 2026) {
                    return new LocalDate[]{
                        LocalDate.of(year, 2, 15),
                        LocalDate.of(year, 2, 23)
                    };
                } else {
                    return new LocalDate[]{
                        LocalDate.of(year, 2, 10),
                        LocalDate.of(year, 2, 16)
                    };
                }
            }

            if (name.contains("情人节")) {
                LocalDate date = LocalDate.of(year, 2, 14);
                return new LocalDate[]{date, date};
            }

            if (name.contains("元宵")) {
                if (year == 2028) {
                    LocalDate date = LocalDate.of(year, 2, 9);
                    return new LocalDate[]{date, date};
                } else if (year == 2027) {
                    LocalDate date = LocalDate.of(year, 2, 20);
                    return new LocalDate[]{date, date};
                } else if (year == 2026) {
                    LocalDate date = LocalDate.of(year, 3, 3);
                    return new LocalDate[]{date, date};
                } else {
                    LocalDate date = LocalDate.of(year, 2, 24);
                    return new LocalDate[]{date, date};
                }
            }

            if (name.contains("清明")) {
                return new LocalDate[]{
                    LocalDate.of(year, 4, 4),
                    LocalDate.of(year, 4, 6)
                };
            }

            if (name.contains("劳动") || name.contains("五一")) {
                return new LocalDate[]{
                    LocalDate.of(year, 5, 1),
                    LocalDate.of(year, 5, 5)
                };
            }

            if (name.contains("儿童")) {
                LocalDate date = LocalDate.of(year, 6, 1);
                return new LocalDate[]{date, date};
            }

            if (name.contains("端午")) {
                if (year == 2028) {
                    return new LocalDate[]{
                        LocalDate.of(year, 6, 27)
                    };
                } else if (year == 2027) {
                    return new LocalDate[]{
                        LocalDate.of(year, 6, 9)
                    };
                } else if (year == 2026) {
                    return new LocalDate[]{
                        LocalDate.of(year, 6, 19),
                        LocalDate.of(year, 6, 21)
                    };
                } else {
                    return new LocalDate[]{
                        LocalDate.of(year, 6, 10),
                        LocalDate.of(year, 6, 12)
                    };
                }
            }

            if (name.contains("七夕")) {
                if (year == 2028) {
                    LocalDate date = LocalDate.of(year, 8, 26);
                    return new LocalDate[]{date, date};
                } else if (year == 2027) {
                    LocalDate date = LocalDate.of(year, 8, 8);
                    return new LocalDate[]{date, date};
                } else if (year == 2026) {
                    LocalDate date = LocalDate.of(year, 8, 19);
                    return new LocalDate[]{date, date};
                } else {
                    LocalDate date = LocalDate.of(year, 8, 10);
                    return new LocalDate[]{date, date};
                }
            }

            if (name.contains("中秋")) {
                if (year == 2028) {
                    return new LocalDate[]{
                        LocalDate.of(year, 10, 3)
                    };
                } else if (year == 2027) {
                    return new LocalDate[]{
                        LocalDate.of(year, 9, 15)
                    };
                } else if (year == 2026) {
                    return new LocalDate[]{
                        LocalDate.of(year, 9, 25),
                        LocalDate.of(year, 9, 27)
                    };
                } else {
                    return new LocalDate[]{
                        LocalDate.of(year, 9, 29),
                        LocalDate.of(year, 10, 1)
                    };
                }
            }

            if (name.contains("国庆")) {
                return new LocalDate[]{
                    LocalDate.of(year, 10, 1),
                    LocalDate.of(year, 10, 7)
                };
            }

            if (name.contains("冬至")) {
                LocalDate date = LocalDate.of(year, 12, 22);
                return new LocalDate[]{date, date};
            }

            if (name.contains("平安夜")) {
                LocalDate date = LocalDate.of(year, 12, 24);
                return new LocalDate[]{date, date};
            }

            if (name.contains("圣诞")) {
                LocalDate date = LocalDate.of(year, 12, 25);
                return new LocalDate[]{date, date};
            }

        } catch (Exception e) {
            log.warn("计算节假日日期范围失败 - 年份: {}, 节假日: {}", year, holidayName, e);
        }

        return null;
    }

    public boolean isBusinessTime(LocalTime currentTime, LocalTime openTime, LocalTime closeTime) {
        if (openTime.isBefore(closeTime)) {
            // 正常时间段（不跨天）：09:00-18:00
            return !currentTime.isBefore(openTime) && currentTime.isBefore(closeTime);
        } else {
            // 跨天时间段：14:00-03:00
            return !currentTime.isBefore(openTime) || currentTime.isBefore(closeTime);
        }
    }

    /**
     * 判断 URL 是否为视频（按常见视频后缀，忽略查询参数）
     *
     * @param url 资源地址
     * @return 是否为视频
     */
    private boolean isVideoUrl(String url) {
        if (StringUtils.isEmpty(url)) {
            return false;
        }
        String path = url;
        int queryIndex = path.indexOf('?');
        if (queryIndex > 0) {
            path = path.substring(0, queryIndex);
        }
        String lowerPath = path.toLowerCase();
        return lowerPath.endsWith(".mp4")
                || lowerPath.endsWith(".avi")
                || lowerPath.endsWith(".flv")
                || lowerPath.endsWith(".mkv")
                || lowerPath.endsWith(".rmvb")
                || lowerPath.endsWith(".wmv")
                || lowerPath.endsWith(".3gp")
                || lowerPath.endsWith(".mov");
    }

}


