package shop.alien.store.service.impl;

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.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import shop.alien.entity.store.*;
import shop.alien.entity.store.dto.StoreStaffConfigListQueryDto;
import shop.alien.entity.store.excelVo.StoreStaffConfigExcelVo;
import shop.alien.entity.store.excelVo.util.ExcelGenerator;
import shop.alien.entity.result.R;
import shop.alien.entity.store.StoreStaffFitnessBase;
import shop.alien.entity.store.StoreStaffFitnessCertification;
import shop.alien.entity.store.StoreStaffFitnessCourse;
import shop.alien.entity.store.StoreStaffFitnessExperience;
import shop.alien.entity.store.vo.PerformanceScheduleVo;
import shop.alien.entity.store.StoreStaffReview;
import shop.alien.entity.store.StoreStaffTitle;
import shop.alien.entity.store.LifeLikeRecord;
import shop.alien.entity.store.vo.StaffTitleGroupVo;
import shop.alien.entity.store.vo.StoreStaffDetailVo;
import shop.alien.entity.store.vo.StoreStaffDetailWithPerformanceVo;
import shop.alien.entity.store.vo.StoreStaffFitnessDetailVo;
import shop.alien.entity.store.vo.StoreStaffPositionCountVo;
import shop.alien.mapper.*;
import shop.alien.mapper.LifeLikeRecordMapper;
import shop.alien.store.service.StoreStaffConfigService;
import shop.alien.store.service.StoreStaffFitnessBaseService;
import shop.alien.store.service.StoreStaffFitnessCertificationService;
import shop.alien.store.service.StoreStaffFitnessCourseService;
import shop.alien.store.service.StoreStaffFitnessExperienceService;
import shop.alien.store.util.CommonConstant;
import shop.alien.store.util.StoreLikeRecordIdentityHelper;
import shop.alien.store.util.StoreLikeRecordIdentityHelper.StoreLikerScope;
import shop.alien.util.ali.AliOSSUtil;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @Author: fcw
 * @CreateTime: 2025-04-11
 * @Description: 员工管理
 */

@Slf4j
@Service
@RequiredArgsConstructor
public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {

    private final StoreStaffConfigMapper storeStaffConfigMapper;

    private final StoreInfoMapper storeInfoMapper;

    private final AliOSSUtil aliOSSUtil;

    private final StoreStaffFitnessCourseService storeStaffFitnessCourseService;

    private final StoreStaffFitnessBaseService storeStaffFitnessBaseService;

    private final StoreStaffFitnessCertificationService storeStaffFitnessCertificationService;

    private final BarPerformanceMapper barPerformanceMapper;

    private final StoreStaffTitleMapper storeStaffTitleMapper;

    private final StoreStaffReviewMapper storeStaffReviewMapper;

    private final StoreStaffFitnessExperienceService storeStaffFitnessExperienceService;

    private final LifeLikeRecordMapper lifeLikeRecordMapper;

    private final StoreLikeRecordIdentityHelper lifeLikeIdentityHelper;

    private final StoreStaffAuditAsyncService storeStaffAuditAsyncService;

    /**
     * 认证类型：认证
     */
    private static final Integer CERTIFICATION_TYPE = 1;

    /**
     * 认证类型：荣誉
     */
    private static final Integer HONOR_TYPE = 2;

    @Value("${spring.web.resources.excel-path}")
    private String excelPath;
    @Value("${spring.web.resources.excel-clearing-receipt}")
    private String excelClearingReceipt;
    @Value("${spring.web.resources.excel-generate-path}")
    private String excelGeneratePath;
    @Value("${spring.web.resources.url}")
    private String fileUrl;

    @Override
    public IPage<StoreStaffConfig> getStaffConfigList(StoreStaffConfigListQueryDto query) {
        int page = (query == null || query.getPage() == null) ? 1 : query.getPage();
        int size = (query == null || query.getSize() == null) ? 10 : query.getSize();
        Integer storeId = query == null ? null : query.getStoreId();
        String status = query == null ? null : query.getStatus();
        Integer onlineStatus = query == null ? null : query.getOnlineStatus();
        String staffPosition = query == null ? null : query.getStaffPosition();
        String staffName = query == null ? null : query.getStaffName();
        Date startCreatedTime = query == null ? null : query.getStartCreatedTime();
        Date endCreatedTime = query == null ? null : query.getEndCreatedTime();

        IPage<StoreStaffConfig> storePage = new Page<>(page, size);
        if (storeId == null) {
            return storePage;
        }
        QueryWrapper<StoreStaffConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(null != status && !status.isEmpty(), "status", status);
        queryWrapper.eq(onlineStatus != null, "online_status", onlineStatus);
        queryWrapper.eq("store_id", storeId);
        queryWrapper.like(StringUtils.isNotEmpty(staffPosition), "staff_position", staffPosition);
        queryWrapper.like(StringUtils.isNotEmpty(staffName), "name", staffName);
        // 创建时间范围查询
        if (startCreatedTime != null) {
            queryWrapper.ge("created_time", startCreatedTime);
        }
        if (endCreatedTime != null) {
            queryWrapper.le("created_time", endCreatedTime);
        }
        // 只查询未删除的记录
        queryWrapper.eq("delete_flag", 0);
        // 排序规则：先按置顶状态降序（置顶的在前），再按置顶时间降序，最后按创建时间降序
        queryWrapper.orderByDesc("top_status", "top_time", "created_time");
        return storeStaffConfigMapper.selectPage(storePage, queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addOrUpdateStaffConfig(StoreStaffConfig storeStaffConfig) {
        if (storeStaffConfig == null) {
            return 0;
        }

        Integer id = storeStaffConfig.getId();
        boolean isCreate = (id == null || id == 0);
        StoreStaffConfig existing = null;

        if (!isCreate) {
            existing = storeStaffConfigMapper.selectById(id);
            // 传了id但库里不存在：按新增处理
            if (existing == null) {
                isCreate = true;
                storeStaffConfig.setId(null);
            }
        }

        // 新增默认值
        if (isCreate) {
            applyCreateDefaults(storeStaffConfig);
            // 新增员工时，检查门店是否有标题
            if (storeStaffConfig.getStoreId() != null) {
                StoreStaffTitle title = getTitleByStoreId(storeStaffConfig.getStoreId());
                if (title == null) {
                    throw new RuntimeException("该门店还没有创建标题，请先创建标题");
                }
                // 设置员工的标题ID
                storeStaffConfig.setTitleId(title.getId());
            }
        }

        // 先落库，再调用 AI 审核
        int affected = isCreate
                ? insertStaff(storeStaffConfig)
                : storeStaffConfigMapper.updateById(storeStaffConfig);

        if (affected <= 0) {
            return affected;
        }

        Integer staffId = isCreate ? storeStaffConfig.getId() : id;

        // 新增员工成功后，更新标题的员工数量和 staff_ids
        if (isCreate && storeStaffConfig.getTitleId() != null) {
            updateTitleStaffCount(storeStaffConfig.getTitleId());
        }

        // 处理视频封面生成
        if (affected > 0 && StringUtils.isNotEmpty(storeStaffConfig.getBackgroundUrl())) {
            processVideoCovers(storeStaffConfig);
        }

        // 异步调用AI审核
        storeStaffAuditAsyncService.auditStaffContentAsync(staffId, storeStaffConfig);

        return affected;
    }

    private int insertStaff(StoreStaffConfig staff) {
        // 新增时，确保id为null，让数据库自增
        staff.setId(null);
        return storeStaffConfigMapper.insert(staff);
    }

    private void applyCreateDefaults(StoreStaffConfig staff) {
        staff.setCreatedTime(new Date(System.currentTimeMillis()));
        if (staff.getDeleteFlag() == null) {
            staff.setDeleteFlag(0);
        }
        if (StringUtils.isEmpty(staff.getStatus())) {
            staff.setStatus("0"); // 待审核
        }
        if (staff.getOnlineStatus() == null) {
            staff.setOnlineStatus(0); // 默认上线
        }
    }

    @Override
    public Integer audit(Integer id, Integer status, String rejectionReason) {
        StoreStaffConfig storeStaffConfig = new StoreStaffConfig();
        storeStaffConfig.setId(id);
        storeStaffConfig.setStatus(String.valueOf(status));
        storeStaffConfig.setRejectionReason(rejectionReason);
        return storeStaffConfigMapper.updateById(storeStaffConfig);
    }

    @Override
    public StoreStaffConfig getStaffConfigDeatail(Integer id) {
        StoreStaffConfig staff = storeStaffConfigMapper.selectById(id);
        if (staff == null) {
            return null;
        }
        return staff;
    }

    @Override
    public String staffConfigExport(String status) throws IOException {
        QueryWrapper<StoreStaffConfig> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotEmpty(status), "status", status);
        wrapper.eq("delete_flag", 0);
        wrapper.orderByDesc("created_time");
        List<StoreStaffConfig> storeStaffConfig = storeStaffConfigMapper.selectList(wrapper);
        storeStaffConfig.forEach(item -> {
            if ("0".equals(item.getStatus())) {
                item.setStatus("待审核");
            } else if ("1".equals(item.getStatus())) {
                item.setStatus("审核通过");
            } else {
                item.setStatus("审核拒绝");
            }

        });
        List<StoreStaffConfigExcelVo> storeStaffConfigs = new ArrayList<>();
        int index = 1;
        for (StoreStaffConfig record : storeStaffConfig) {
            StoreStaffConfigExcelVo storeCouponStatusVo = new StoreStaffConfigExcelVo();
            BeanUtils.copyProperties(record, storeCouponStatusVo);
            storeCouponStatusVo.setId(index++); // 设置序号
            storeStaffConfigs.add(storeCouponStatusVo);
        }
        String fileName = UUID.randomUUID().toString().replace("-", "");
        String filePath = ExcelGenerator.generateExcel(excelPath + excelGeneratePath + fileName + ".xlsx", storeStaffConfigs, StoreStaffConfigExcelVo.class);
        return aliOSSUtil.uploadFile(new File(filePath), "excel/" + fileName + ".xlsx");
    }

    @Override
    public Integer deleteStaffConfig(Integer id) {
        // 使用 MyBatis-Plus 的逻辑删除，会自动将 deleteFlag 设置为 1
        // 因为实体类使用了 @TableLogic 注解
        StoreStaffConfig staff = storeStaffConfigMapper.selectById(id);
        int deleted = storeStaffConfigMapper.deleteById(id);

        // 删除员工后，更新标题的员工数量和 staff_ids
        if (deleted > 0 && staff != null && staff.getTitleId() != null) {
            updateTitleStaffCount(staff.getTitleId());
        }

        return deleted;
    }

    /**
     * 判断URL是否为视频
     *
     * @param url URL地址
     * @return 是否为视频
     */
    private boolean isVideoUrl(String url) {
        if (url == null || url.isEmpty()) {
            return false;
        }
        String lowerUrl = url.toLowerCase();
        return lowerUrl.endsWith(".mp4") ||
               lowerUrl.endsWith(".avi") ||
               lowerUrl.endsWith(".flv") ||
               lowerUrl.endsWith(".mkv") ||
               lowerUrl.endsWith(".rmvb") ||
               lowerUrl.endsWith(".wmv") ||
               lowerUrl.endsWith(".3gp") ||
               lowerUrl.endsWith(".mov");
    }

    @Override
    public Integer setTopStatus(Integer id, Integer topStatus) {
        if (id == null || topStatus == null) {
            return 0;
        }
        LambdaUpdateWrapper<StoreStaffConfig> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(StoreStaffConfig::getId, id);
        lambdaUpdateWrapper.set(StoreStaffConfig::getTopStatus, topStatus);
        if (topStatus == 0) {
            lambdaUpdateWrapper.set(StoreStaffConfig::getTopTime, null);
        } else {
            lambdaUpdateWrapper.set(StoreStaffConfig::getTopTime, new Date());
        }
        return storeStaffConfigMapper.update(null, lambdaUpdateWrapper);
    }

    @Override
    public Integer setOnlineStatus(Integer id, Integer onlineStatus) {
        if (id == null || onlineStatus == null) {
            return 0;
        }
        LambdaUpdateWrapper<StoreStaffConfig> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(StoreStaffConfig::getId, id);
        lambdaUpdateWrapper.set(StoreStaffConfig::getOnlineStatus, onlineStatus);
        return storeStaffConfigMapper.update(null, lambdaUpdateWrapper);
    }

    @Override
    public List<String> getStaffPositionList(Integer storeId) {
        log.info("查询员工职位列表，storeId={}", storeId);

        // 参数校验
        if (storeId == null || storeId <= 0) {
            log.warn("查询员工职位列表失败，店铺ID无效：storeId={}", storeId);
            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
        }

        // 构建查询条件：查询指定店铺下未删除的员工
        LambdaQueryWrapper<StoreStaffConfig> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StoreStaffConfig::getStoreId, storeId)
                .eq(StoreStaffConfig::getDeleteFlag, 0)
                .eq(StoreStaffConfig::getStatus, 1)
                // 只查询staff_position不为空的记录
                .isNotNull(StoreStaffConfig::getStaffPosition)
                .ne(StoreStaffConfig::getStaffPosition, "")
                .select(StoreStaffConfig::getStaffPosition);

        // 查询所有符合条件的员工
        List<StoreStaffConfig> staffList = storeStaffConfigMapper.selectList(queryWrapper);

        // 提取所有不重复的职位名称
        List<String> positionList = staffList.stream()
                .map(StoreStaffConfig::getStaffPosition)
                .filter(StringUtils::isNotEmpty)
                .distinct()
                .sorted()
                .collect(Collectors.toList());

        log.info("查询员工职位列表成功，storeId={}，职位数量：{}", storeId, positionList.size());
        return positionList;
    }

    /**
     * 根据门店ID查询标题（一个门店只能有一个标题）
     *
     * @param storeId 门店ID
     * @return 标题信息
     */
    private StoreStaffTitle getTitleByStoreId(Integer storeId) {
        if (storeId == null) {
            return null;
        }

        // 直接通过 store_id 查询标题
        LambdaQueryWrapper<StoreStaffTitle> titleWrapper = new LambdaQueryWrapper<>();
        titleWrapper.eq(StoreStaffTitle::getStoreId, storeId)
                .eq(StoreStaffTitle::getDeleteFlag, 0)
                .orderByDesc(StoreStaffTitle::getCreatedTime)
                .last("limit 1");
        return storeStaffTitleMapper.selectOne(titleWrapper);
    }

    /**
     * 更新标题的员工数量和 staff_ids
     *
     * @param titleId 标题ID
     */
    private void updateTitleStaffCount(Integer titleId) {
        if (titleId == null) {
            return;
        }

        // 查询该标题下的所有未删除员工
        LambdaQueryWrapper<StoreStaffConfig> staffWrapper = new LambdaQueryWrapper<>();
        staffWrapper.eq(StoreStaffConfig::getTitleId, titleId)
                .eq(StoreStaffConfig::getDeleteFlag, 0)
                .select(StoreStaffConfig::getId);
        List<StoreStaffConfig> staffList = storeStaffConfigMapper.selectList(staffWrapper);

        // 计算员工数量和 staff_ids
        int staffCount = staffList.size();
        String staffIds = staffList.stream()
                .map(staff -> String.valueOf(staff.getId()))
                .collect(Collectors.joining(","));

        // 更新标题
        LambdaUpdateWrapper<StoreStaffTitle> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(StoreStaffTitle::getId, titleId)
                .set(StoreStaffTitle::getStaffIds, staffIds)
                .set(StoreStaffTitle::getStaffCount, staffCount)
                .set(StoreStaffTitle::getUpdatedTime, new Date());

        storeStaffTitleMapper.update(null, updateWrapper);
        log.info("StoreStaffConfigServiceImpl.updateTitleStaffCount 更新成功，titleId={}, staffCount={}", titleId, staffCount);
    }

    /**
     * 员工列表查询（用户端）
     * <p>
     * 查询指定店铺的员工列表，支持按状态和职位筛选
     * 排序规则：先按置顶状态降序，再按置顶时间降序，最后按创建时间降序
     * 返回结果中包含员工基本信息和今日是否有演出标识
     * </p>
     *
     * @param page          分页页数，必须大于0
     * @param size          分页条数，必须大于0
     * @param storeId       店铺ID，必须大于0
     * @param status        员工状态，可选（0-待审核 1-审核通过 2-审核拒绝），为空时查询所有状态
     * @param staffPosition 员工职位，可选，为空时查询所有职位
     * @return 员工列表分页结果，包含员工基本信息和今日是否有演出标识
     * @throws IllegalArgumentException 当参数无效时抛出
     */
    @Override
    public IPage<StoreStaffConfig> queryStaffList(Integer page, Integer size, Integer storeId, String status, String staffPosition) {
        // 参数校验
        validateQueryParams(page, size, storeId);

        // 构建分页对象
        IPage<StoreStaffConfig> staffPage = new Page<>(page, size);

        // 构建查询条件
        LambdaQueryWrapper<StoreStaffConfig> queryWrapper = buildStaffListQueryWrapper(storeId, status, staffPosition);
        // 只查询上线的员工
        queryWrapper.eq(StoreStaffConfig::getOnlineStatus,"0");
        // 执行查询
        IPage<StoreStaffConfig> result = storeStaffConfigMapper.selectPage(staffPage, queryWrapper);

        // 批量填充今日是否有演出字段（性能优化：批量查询）
        fillHasPerformanceTodayBatch(result);

        return result;
    }

    /**
     * 校验查询参数
     *
     * @param page    分页页数
     * @param size    分页条数
     * @param storeId 店铺ID
     * @throws IllegalArgumentException 当参数无效时抛出
     */
    private void validateQueryParams(Integer page, Integer size, Integer storeId) {
        if (page == null || page < 1) {
            throw new IllegalArgumentException("分页页数不能为空且必须大于0");
        }
        if (size == null || size < 1) {
            throw new IllegalArgumentException("分页条数不能为空且必须大于0");
        }
        if (storeId == null || storeId <= 0) {
            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
        }
    }

    /**
     * 构建员工列表查询条件
     *
     * @param storeId       店铺ID
     * @param status        员工状态，可选
     * @param staffPosition 员工职位，可选
     * @return 查询条件包装器
     */
    private LambdaQueryWrapper<StoreStaffConfig> buildStaffListQueryWrapper(Integer storeId, String status, String staffPosition) {
        LambdaQueryWrapper<StoreStaffConfig> queryWrapper = new LambdaQueryWrapper<>();

        // 必须条件：店铺ID和未删除
        queryWrapper.eq(StoreStaffConfig::getStoreId, storeId)
                .eq(StoreStaffConfig::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE);

        // 可选条件：员工状态筛选
        if (StringUtils.isNotEmpty(status)) {
            queryWrapper.eq(StoreStaffConfig::getStatus, status);
        }

        // 可选条件：员工职位筛选
        if (StringUtils.isNotEmpty(staffPosition)) {
            queryWrapper.eq(StoreStaffConfig::getStaffPosition, staffPosition);
        }

        // 排序规则：先按置顶状态降序（置顶的在前），再按置顶时间降序，最后按创建时间降序
        queryWrapper.orderByDesc(StoreStaffConfig::getTopStatus)
                .orderByDesc(StoreStaffConfig::getTopTime)
                .orderByDesc(StoreStaffConfig::getCreatedTime);

        return queryWrapper;
    }

    /**
     * 批量填充员工今日是否有演出字段
     * <p>
     * 性能优化：批量查询所有员工的演出信息，避免N+1查询问题
     * </p>
     *
     * @param result 员工列表分页结果
     */
    private void fillHasPerformanceTodayBatch(IPage<StoreStaffConfig> result) {
        if (result == null || result.getRecords() == null || result.getRecords().isEmpty()) {
            return;
        }

        try {
            // 获取所有员工ID
            List<Integer> staffIds = result.getRecords().stream()
                    .map(StoreStaffConfig::getId)
                    .filter(id -> id != null && id > 0)
                    .distinct()
                    .collect(Collectors.toList());

            if (staffIds.isEmpty()) {
                return;
            }

            // 批量查询今日有演出的员工ID集合
            java.util.Set<Integer> staffIdsWithPerformanceToday = queryStaffIdsWithPerformanceToday(staffIds);

            // 填充字段
            for (StoreStaffConfig staff : result.getRecords()) {
                if (staff.getId() != null) {
                    Boolean hasPerformanceToday = staffIdsWithPerformanceToday.contains(staff.getId());
                    staff.setHasPerformanceToday(hasPerformanceToday);
                } else {
                    staff.setHasPerformanceToday(false);
                }
            }
        } catch (Exception e) {
            log.error("批量填充员工今日是否有演出字段异常，异常信息：{}", e.getMessage(), e);
            // 异常时设置为false，不影响主流程
            for (StoreStaffConfig staff : result.getRecords()) {
                staff.setHasPerformanceToday(false);
            }
        }
    }

    /**
     * 批量查询今日有演出的员工ID集合
     *
     * @param staffIds 员工ID列表
     * @return 今日有演出的员工ID集合
     */
    private java.util.Set<Integer> queryStaffIdsWithPerformanceToday(List<Integer> staffIds) {
        if (staffIds == null || staffIds.isEmpty()) {
            return new java.util.HashSet<>();
        }

        try {
            // 获取今天的开始和结束时间
            TodayTimeRange todayTimeRange = getTodayTimeRange();

            // 查询所有包含这些员工的演出
            LambdaQueryWrapper<BarPerformance> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BarPerformance::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE)
                    .eq(BarPerformance::getReviewStatus, CommonConstant.PERFORMANCE_REVIEW_STATUS_APPROVED)
                    .eq(BarPerformance::getOnlineStatus, CommonConstant.PERFORMANCE_ONLINE_STATUS_ONLINE);

            // 构建staffConfigIds的查询条件（使用OR连接多个LIKE条件）
            queryWrapper.and(wrapper -> {
                for (Integer staffId : staffIds) {
                    wrapper.or(w -> w.like(BarPerformance::getStaffConfigIds, staffId.toString()));
                }
            });

            List<BarPerformance> performances = barPerformanceMapper.selectList(queryWrapper);

            if (performances == null || performances.isEmpty()) {
                return new java.util.HashSet<>();
            }

            // 筛选出今日有演出的员工ID
            java.util.Set<Integer> staffIdsWithPerformance = new java.util.HashSet<>();
            for (BarPerformance performance : performances) {
                if (isPerformanceToday(performance, todayTimeRange)) {
                    // 解析staffConfigIds，提取员工ID
                    List<Integer> performanceStaffIds = parseStaffConfigIds(performance.getStaffConfigIds());
                    for (Integer staffId : performanceStaffIds) {
                        if (staffIds.contains(staffId)) {
                            staffIdsWithPerformance.add(staffId);
                        }
                    }
                }
            }

            return staffIdsWithPerformance;
        } catch (Exception e) {
            log.error("批量查询今日有演出的员工ID异常，异常信息：{}", e.getMessage(), e);
            return new java.util.HashSet<>();
        }
    }

    /**
     * 判断演出是否在今天
     *
     * @param performance    演出信息
     * @param todayTimeRange 今天的时间范围
     * @return true-今日有演出，false-今日无演出
     */
    private boolean isPerformanceToday(BarPerformance performance, TodayTimeRange todayTimeRange) {
        if (performance == null || todayTimeRange == null) {
            return false;
        }

        String frequency = performance.getPerformanceFrequency();
        if (StringUtils.isEmpty(frequency)) {
            return false;
        }

        switch (frequency) {
            case CommonConstant.PERFORMANCE_FREQUENCY_SINGLE:
                return isSinglePerformanceToday(performance, todayTimeRange);
            case CommonConstant.PERFORMANCE_FREQUENCY_DAILY:
                return isDailyPerformanceToday(performance, todayTimeRange);
            case CommonConstant.PERFORMANCE_FREQUENCY_WEEKLY:
                return isWeeklyPerformanceToday(performance, todayTimeRange);
            default:
                return false;
        }
    }

    /**
     * 判断单次演出是否在今天
     *
     * @param performance    演出信息
     * @param todayTimeRange 今天的时间范围
     * @return true-今日有演出，false-今日无演出
     */
    private boolean isSinglePerformanceToday(BarPerformance performance, TodayTimeRange todayTimeRange) {
        Date singleStart = performance.getSingleStartDatetime();
        Date singleEnd = performance.getSingleEndDatetime();
        if (singleStart == null || singleEnd == null) {
            return false;
        }
        // 判断：开始时间 <= 今天结束 AND 结束时间 >= 今天开始
        return !singleStart.after(todayTimeRange.getEnd()) && !singleEnd.before(todayTimeRange.getStart());
    }

    /**
     * 判断每天定时演出是否在今天
     *
     * @param performance    演出信息
     * @param todayTimeRange 今天的时间范围
     * @return true-今日有演出，false-今日无演出
     */
    private boolean isDailyPerformanceToday(BarPerformance performance, TodayTimeRange todayTimeRange) {
        Date dailyStart = performance.getDailyStartDate();
        Date dailyEnd = performance.getDailyEndDate();
        if (dailyStart == null || dailyEnd == null) {
            return false;
        }
        // 判断：开始日期 <= 今天 <= 结束日期
        return !dailyStart.after(todayTimeRange.getEnd()) && !dailyEnd.before(todayTimeRange.getStart());
    }

    /**
     * 判断每周定时演出是否在今天
     *
     * @param performance    演出信息
     * @param todayTimeRange 今天的时间范围
     * @return true-今日有演出，false-今日无演出
     */
    private boolean isWeeklyPerformanceToday(BarPerformance performance, TodayTimeRange todayTimeRange) {
        Date weeklyStart = performance.getDailyStartDate();
        Date weeklyEnd = performance.getDailyEndDate();
        String performanceWeek = performance.getPerformanceWeek();
        if (weeklyStart == null || weeklyEnd == null || StringUtils.isEmpty(performanceWeek)) {
            return false;
        }
        // 判断：开始日期 <= 今天 <= 结束日期 且 演出日期包含今天对应的星期几
        boolean dateInRange = !weeklyStart.after(todayTimeRange.getEnd()) && !weeklyEnd.before(todayTimeRange.getStart());
        boolean weekDayMatch = performanceWeek.contains(todayTimeRange.getTodayWeekDayStr());
        return dateInRange && weekDayMatch;
    }

    /**
     * 解析员工配置ID字符串（逗号分隔）
     *
     * @param staffConfigIds 员工配置ID字符串，格式：1,2,3
     * @return 员工ID列表
     */
    private List<Integer> parseStaffConfigIds(String staffConfigIds) {
        List<Integer> staffIds = new ArrayList<>();
        if (StringUtils.isEmpty(staffConfigIds)) {
            return staffIds;
        }

        try {
            String[] ids = staffConfigIds.split(",");
            for (String idStr : ids) {
                if (StringUtils.isNotEmpty(idStr)) {
                    idStr = idStr.trim();
                    try {
                        Integer staffId = Integer.parseInt(idStr);
                        if (staffId > 0) {
                            staffIds.add(staffId);
                        }
                    } catch (NumberFormatException e) {
                        log.warn("解析员工配置ID失败，无效的ID：{}", idStr);
                    }
                }
            }
        } catch (Exception e) {
            log.error("解析员工配置ID字符串异常，staffConfigIds={}，异常信息：{}", staffConfigIds, e.getMessage(), e);
        }

        return staffIds;
    }

    /**
     * 检查员工今日是否有演出
     *
     * @param staffId 员工ID
     * @return true-今日有演出，false-今日无演出
     */
    private Boolean checkHasPerformanceToday(Integer staffId) {
        if (staffId == null || staffId <= 0) {
            return false;
        }

        try {
            // 获取今天的时间范围
            TodayTimeRange todayTimeRange = getTodayTimeRange();

            // 查询包含该员工的所有演出
            LambdaQueryWrapper<BarPerformance> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BarPerformance::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE)
                    .eq(BarPerformance::getReviewStatus, CommonConstant.PERFORMANCE_REVIEW_STATUS_APPROVED)
                    .eq(BarPerformance::getOnlineStatus, CommonConstant.PERFORMANCE_ONLINE_STATUS_ONLINE)
                    .like(BarPerformance::getStaffConfigIds, staffId.toString());

            List<BarPerformance> performances = barPerformanceMapper.selectList(queryWrapper);

            if (performances == null || performances.isEmpty()) {
                return false;
            }

            // 判断是否有今日的演出
            for (BarPerformance performance : performances) {
                if (isPerformanceToday(performance, todayTimeRange)) {
                    return true;
                }
            }

            return false;
        } catch (Exception e) {
            log.error("检查员工今日是否有演出异常，staffId={}，异常信息：{}", staffId, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 获取今天的时间范围
     *
     * @return 今天的时间范围对象
     */
    private TodayTimeRange getTodayTimeRange() {
        Date now = new Date();
        java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.setTime(now);

        // 获取今天的开始时间（00:00:00）
        cal.set(java.util.Calendar.HOUR_OF_DAY, 0);
        cal.set(java.util.Calendar.MINUTE, 0);
        cal.set(java.util.Calendar.SECOND, 0);
        cal.set(java.util.Calendar.MILLISECOND, 0);
        Date todayStart = cal.getTime();

        // 获取今天是星期几（0-周一，1-周二，...，6-周日）
        int dayOfWeek = cal.get(java.util.Calendar.DAY_OF_WEEK);
        // Calendar中：1=周日，2=周一，...，7=周六
        // 转换为：0=周一，1=周二，...，6=周日
        int todayWeekDay = (dayOfWeek == 1) ? 6 : (dayOfWeek - 2);
        String todayWeekDayStr = String.valueOf(todayWeekDay);

        // 获取今天的结束时间（23:59:59.999）
        cal.set(java.util.Calendar.HOUR_OF_DAY, 23);
        cal.set(java.util.Calendar.MINUTE, 59);
        cal.set(java.util.Calendar.SECOND, 59);
        cal.set(java.util.Calendar.MILLISECOND, 999);
        Date todayEnd = cal.getTime();

        return new TodayTimeRange(todayStart, todayEnd, todayWeekDayStr);
    }

    /**
     * 今天的时间范围内部类
     */
    private static class TodayTimeRange {
        /**
         * 今天开始时间（00:00:00）
         */
        private final Date start;

        /**
         * 今天结束时间（23:59:59.999）
         */
        private final Date end;

        /**
         * 今天是星期几的字符串表示（0-周一，1-周二，...，6-周日）
         */
        private final String todayWeekDayStr;

        public TodayTimeRange(Date start, Date end, String todayWeekDayStr) {
            this.start = start;
            this.end = end;
            this.todayWeekDayStr = todayWeekDayStr;
        }

        public Date getStart() {
            return start;
        }

        public Date getEnd() {
            return end;
        }

        public String getTodayWeekDayStr() {
            return todayWeekDayStr;
        }
    }

    @Override
    public StoreStaffConfig queryStaffDetail(Integer id) {
        if (id == null || id <= 0) {
            return null;
        }
        QueryWrapper<StoreStaffConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        queryWrapper.eq("delete_flag", 0);
        return storeStaffConfigMapper.selectOne(queryWrapper);
    }

    /**
     * 员工详情查询（包含演出列表）（用户端）
     * <p>
     * 查询员工基本信息以及关联的演出安排列表
     * 演出安排列表包含未来30天内的所有演出时间
     * </p>
     *
     * @param id 员工主键ID，必须大于0
     * @return 员工详情（包含演出列表），如果员工不存在则返回null
     */
    @Override
    public StoreStaffDetailWithPerformanceVo queryStaffDetailWithPerformance(Integer id, String userId) {
        log.info("查询员工详情（包含演出列表），id={}，userId={}", id, userId);

        // 参数校验
        if (id == null || id <= 0) {
            log.warn("查询员工详情失败，员工ID无效：{}", id);
            return null;
        }

        try {
            // 查询员工基本信息
            StoreStaffConfig staffConfig = queryStaffDetail(id);
            if (staffConfig == null) {
                log.warn("查询员工详情失败，员工不存在：id={}", id);
                return null;
            }

            // 查询演出安排列表
            List<PerformanceScheduleVo> performanceScheduleList =
                    queryPerformanceScheduleList(id);

            // 判断今日是否有演出
            Boolean hasPerformanceToday = checkHasPerformanceToday(id);

            // 判断是否喜欢（根据userId查询点赞记录）
            Boolean isLiked = checkIsLiked(id, userId);

            // 查询店铺信息（店铺名称和店铺电话）
            String storeName = null;
            String storePhone = null;
            if (staffConfig.getStoreId() != null && staffConfig.getStoreId() > 0) {
                try {
                    StoreInfo storeInfo = storeInfoMapper.selectById(staffConfig.getStoreId());
                    if (storeInfo != null) {
                        storeName = storeInfo.getStoreName();
                        storePhone = storeInfo.getStoreTel();
                    } else {
                        log.warn("查询店铺信息失败，店铺不存在：storeId={}", staffConfig.getStoreId());
                    }
                } catch (Exception e) {
                    log.warn("查询店铺信息异常，storeId={}，异常信息：{}", staffConfig.getStoreId(), e.getMessage());
                    // 店铺信息查询失败不影响整体返回，设置为null即可
                }
            }

            // 构建返回对象
            StoreStaffDetailWithPerformanceVo result =
                    new StoreStaffDetailWithPerformanceVo();
            result.setStaffInfo(staffConfig);
            result.setPerformanceScheduleList(performanceScheduleList);
            result.setHasPerformanceToday(hasPerformanceToday);
            result.setIsLiked(isLiked);
            result.setStoreName(storeName);
            result.setStorePhone(storePhone);

            log.info("查询员工详情（包含演出列表）成功，id={}，演出安排数量：{}，今日是否有演出：{}，是否喜欢：{}，店铺名称：{}，店铺电话：{}",
                    id, performanceScheduleList != null ? performanceScheduleList.size() : 0, hasPerformanceToday, isLiked, storeName, storePhone);
            return result;
        } catch (Exception e) {
            log.error("查询员工详情（包含演出列表）异常，id={}，异常信息：{}", id, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 查询员工演出安排列表
     * <p>
     * 查询该员工关联的所有演出，并根据演出类型生成未来30天内的演出安排列表
     * </p>
     *
     * @param staffId 员工ID
     * @return 演出安排列表
     */
    private List<PerformanceScheduleVo> queryPerformanceScheduleList(Integer staffId) {
        List<PerformanceScheduleVo> scheduleList = new ArrayList<>();

        try {
            // 查询包含该员工的所有演出
            LambdaQueryWrapper<BarPerformance> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BarPerformance::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE)
                    .eq(BarPerformance::getReviewStatus, CommonConstant.PERFORMANCE_REVIEW_STATUS_APPROVED)
                    .eq(BarPerformance::getOnlineStatus, CommonConstant.PERFORMANCE_ONLINE_STATUS_ONLINE)
                    .like(BarPerformance::getStaffConfigIds, staffId.toString())
                    .orderByAsc(BarPerformance::getCreatedTime);

            List<BarPerformance> performances = barPerformanceMapper.selectList(queryWrapper);

            if (performances == null || performances.isEmpty()) {
                return scheduleList;
            }

            // 获取未来30天的日期范围
            Date now = new Date();
            java.util.Calendar cal = java.util.Calendar.getInstance();
            cal.setTime(now);
            cal.set(java.util.Calendar.HOUR_OF_DAY, 0);
            cal.set(java.util.Calendar.MINUTE, 0);
            cal.set(java.util.Calendar.SECOND, 0);
            cal.set(java.util.Calendar.MILLISECOND, 0);
            Date todayStart = cal.getTime();

            cal.add(java.util.Calendar.DAY_OF_MONTH, 30);
            Date futureEnd = cal.getTime();

            // 遍历演出，生成演出安排列表
            for (BarPerformance performance : performances) {
                String frequency = performance.getPerformanceFrequency();
                if (StringUtils.isEmpty(frequency)) {
                    continue;
                }

                switch (frequency) {
                    case CommonConstant.PERFORMANCE_FREQUENCY_SINGLE:
                        // 单次演出
                        generateSinglePerformanceSchedule(performance, todayStart, futureEnd, scheduleList);
                        break;
                    case CommonConstant.PERFORMANCE_FREQUENCY_DAILY:
                        // 每天定时
                        generateDailyPerformanceSchedule(performance, todayStart, futureEnd, scheduleList);
                        break;
                    case CommonConstant.PERFORMANCE_FREQUENCY_WEEKLY:
                        // 每周定时
                        generateWeeklyPerformanceSchedule(performance, todayStart, futureEnd, scheduleList);
                        break;
                    default:
                        break;
                }
            }

            // 按日期和时间排序
            scheduleList.sort((a, b) -> {
                // 先按日期排序，再按时间排序
                int dateCompare = a.getDateStr().compareTo(b.getDateStr());
                if (dateCompare != 0) {
                    return dateCompare;
                }
                return a.getTimeRange().compareTo(b.getTimeRange());
            });

            return scheduleList;
        } catch (Exception e) {
            log.error("查询员工演出安排列表异常，staffId={}，异常信息：{}", staffId, e.getMessage(), e);
            return scheduleList;
        }
    }

    /**
     * 生成单次演出安排
     *
     * @param performance 演出信息
     * @param todayStart  今天开始时间
     * @param futureEnd   未来结束时间
     * @param scheduleList 演出安排列表
     */
    private void generateSinglePerformanceSchedule(BarPerformance performance, Date todayStart, Date futureEnd,
                                                    List<PerformanceScheduleVo> scheduleList) {
        Date singleStart = performance.getSingleStartDatetime();
        Date singleEnd = performance.getSingleEndDatetime();
        if (singleStart == null || singleEnd == null) {
            return;
        }

        // 只处理未来30天内的演出
        if (singleStart.before(todayStart) || singleStart.after(futureEnd)) {
            return;
        }

        PerformanceScheduleVo schedule = buildPerformanceScheduleVo(
                performance, singleStart, singleEnd);
        scheduleList.add(schedule);
    }

    /**
     * 生成每天定时演出安排
     *
     * @param performance 演出信息
     * @param todayStart  今天开始时间
     * @param futureEnd   未来结束时间
     * @param scheduleList 演出安排列表
     */
    private void generateDailyPerformanceSchedule(BarPerformance performance, Date todayStart, Date futureEnd,
                                                   List<PerformanceScheduleVo> scheduleList) {
        Date dailyStart = performance.getDailyStartDate();
        Date dailyEnd = performance.getDailyEndDate();
        if (dailyStart == null || dailyEnd == null) {
            return;
        }

        // 获取演出时间（使用dailyStartTime和dailyEndTime）
        java.time.LocalTime dailyStartTime = performance.getDailyStartTime();
        java.time.LocalTime dailyEndTime = performance.getDailyEndTime();
        if (dailyStartTime == null || dailyEndTime == null) {
            return;
        }

        // 确定查询的起始日期（取今天和演出开始日期的较大者）
        Date queryStart = dailyStart.before(todayStart) ? todayStart : dailyStart;
        // 确定查询的结束日期（取未来30天和演出结束日期的较小者）
        Date queryEnd = dailyEnd.after(futureEnd) ? futureEnd : dailyEnd;

        if (queryStart.after(queryEnd)) {
            return;
        }

        // 从开始日期到结束日期，每天生成一条记录
        java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.setTime(queryStart);
        while (!cal.getTime().after(queryEnd)) {
            Date currentDate = cal.getTime();
            // 使用dailyStartTime和dailyEndTime
            Date scheduleStart = combineDateAndLocalTime(currentDate, dailyStartTime);
            Date scheduleEnd = combineDateAndLocalTime(currentDate, dailyEndTime);

            // 如果结束时间小于或等于开始时间，说明跨天了
            if (!scheduleEnd.after(scheduleStart)) {
                java.util.Calendar endCal = java.util.Calendar.getInstance();
                endCal.setTime(scheduleEnd);
                endCal.add(java.util.Calendar.DAY_OF_MONTH, 1);
                scheduleEnd = endCal.getTime();
            }

            PerformanceScheduleVo schedule = buildPerformanceScheduleVo(
                    performance, scheduleStart, scheduleEnd);
            scheduleList.add(schedule);

            cal.add(java.util.Calendar.DAY_OF_MONTH, 1);
        }
    }

    /**
     * 生成每周定时演出安排
     *
     * @param performance 演出信息
     * @param todayStart  今天开始时间
     * @param futureEnd   未来结束时间
     * @param scheduleList 演出安排列表
     */
    private void generateWeeklyPerformanceSchedule(BarPerformance performance, Date todayStart, Date futureEnd,
                                                    List<PerformanceScheduleVo> scheduleList) {
        Date weeklyStart = performance.getDailyStartDate();
        Date weeklyEnd = performance.getDailyEndDate();
        String performanceWeek = performance.getPerformanceWeek();
        if (weeklyStart == null || weeklyEnd == null || StringUtils.isEmpty(performanceWeek)) {
            return;
        }

        // 获取演出时间（使用dailyStartTime和dailyEndTime）
        java.time.LocalTime dailyStartTime = performance.getDailyStartTime();
        java.time.LocalTime dailyEndTime = performance.getDailyEndTime();
        if (dailyStartTime == null || dailyEndTime == null) {
            return;
        }

        // 确定查询的起始日期
        Date queryStart = weeklyStart.before(todayStart) ? todayStart : weeklyStart;
        // 确定查询的结束日期
        Date queryEnd = weeklyEnd.after(futureEnd) ? futureEnd : weeklyEnd;

        if (queryStart.after(queryEnd)) {
            return;
        }

        // 解析星期几列表
        java.util.Set<String> weekDaySet = new java.util.HashSet<>();
        String[] weekDays = performanceWeek.split(",");
        for (String weekDay : weekDays) {
            if (StringUtils.isNotEmpty(weekDay.trim())) {
                weekDaySet.add(weekDay.trim());
            }
        }

        // 从开始日期到结束日期，只生成符合星期几的日期
        java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.setTime(queryStart);
        while (!cal.getTime().after(queryEnd)) {
            // 获取当前日期是星期几（0-周一，1-周二，...，6-周日）
            int dayOfWeek = cal.get(java.util.Calendar.DAY_OF_WEEK);
            int todayWeekDay = (dayOfWeek == 1) ? 6 : (dayOfWeek - 2);
            String todayWeekDayStr = String.valueOf(todayWeekDay);

            if (weekDaySet.contains(todayWeekDayStr)) {
                Date currentDate = cal.getTime();
                // 使用dailyStartTime和dailyEndTime
                Date scheduleStart = combineDateAndLocalTime(currentDate, dailyStartTime);
                Date scheduleEnd = combineDateAndLocalTime(currentDate, dailyEndTime);

                // 如果结束时间小于或等于开始时间，说明跨天了
                if (!scheduleEnd.after(scheduleStart)) {
                    java.util.Calendar endCal = java.util.Calendar.getInstance();
                    endCal.setTime(scheduleEnd);
                    endCal.add(java.util.Calendar.DAY_OF_MONTH, 1);
                    scheduleEnd = endCal.getTime();
                }

                shop.alien.entity.store.vo.PerformanceScheduleVo schedule = buildPerformanceScheduleVo(
                        performance, scheduleStart, scheduleEnd);
                scheduleList.add(schedule);
            }

            cal.add(java.util.Calendar.DAY_OF_MONTH, 1);
        }
    }

    /**
     * 构建演出安排VO
     *
     * @param performance 演出信息
     * @param startTime   开始时间
     * @param endTime     结束时间
     * @return 演出安排VO
     */
    private PerformanceScheduleVo buildPerformanceScheduleVo(
            BarPerformance performance, Date startTime, Date endTime) {
        PerformanceScheduleVo schedule =
                new PerformanceScheduleVo();

        schedule.setPerformanceId(performance.getId());
        schedule.setPerformanceName(performance.getPerformanceName());

        // 格式化日期和时间
        java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("M月d日");
        java.text.SimpleDateFormat timeFormat = new java.text.SimpleDateFormat("HH:mm");

        String dateStr = dateFormat.format(startTime);
        String weekDayStr = getWeekDayStr(startTime);
        String startTimeStr = timeFormat.format(startTime);

        // 判断是否跨天
        String endTimeStr;
        java.util.Calendar startCal = java.util.Calendar.getInstance();
        startCal.setTime(startTime);
        java.util.Calendar endCal = java.util.Calendar.getInstance();
        endCal.setTime(endTime);

        boolean isNextDay = endCal.get(java.util.Calendar.DAY_OF_YEAR) > startCal.get(java.util.Calendar.DAY_OF_YEAR) ||
                endCal.get(java.util.Calendar.YEAR) > startCal.get(java.util.Calendar.YEAR);

        if (isNextDay) {
            endTimeStr = "次日" + timeFormat.format(endTime);
        } else {
            endTimeStr = timeFormat.format(endTime);
        }

        schedule.setDateStr(dateStr);
        schedule.setWeekDayStr(weekDayStr);
        schedule.setTimeRange(startTimeStr + "-" + endTimeStr);

        return schedule;
    }

    /**
     * 获取星期几的中文表示
     *
     * @param date 日期
     * @return 星期几的中文表示（周一、周二、...、周日）
     */
    private String getWeekDayStr(Date date) {
        java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.setTime(date);
        int dayOfWeek = cal.get(java.util.Calendar.DAY_OF_WEEK);
        // Calendar中：1=周日，2=周一，...，7=周六
        String[] weekDays = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
        return weekDays[dayOfWeek - 1];
    }

    /**
     * 合并日期和时间
     *
     * @param date 日期
     * @param timeSource 时间源（从中提取时间部分）
     * @return 合并后的日期时间
     */
    private Date combineDateAndTime(Date date, Date timeSource) {
        if (timeSource == null) {
            return date;
        }

        java.util.Calendar dateCal = java.util.Calendar.getInstance();
        dateCal.setTime(date);

        java.util.Calendar timeCal = java.util.Calendar.getInstance();
        timeCal.setTime(timeSource);

        dateCal.set(java.util.Calendar.HOUR_OF_DAY, timeCal.get(java.util.Calendar.HOUR_OF_DAY));
        dateCal.set(java.util.Calendar.MINUTE, timeCal.get(java.util.Calendar.MINUTE));
        dateCal.set(java.util.Calendar.SECOND, timeCal.get(java.util.Calendar.SECOND));
        dateCal.set(java.util.Calendar.MILLISECOND, timeCal.get(java.util.Calendar.MILLISECOND));

        return dateCal.getTime();
    }

    /**
     * 合并日期和LocalTime
     *
     * @param date 日期
     * @param localTime 时间（LocalTime类型）
     * @return 合并后的日期时间
     */
    private Date combineDateAndLocalTime(Date date, java.time.LocalTime localTime) {
        if (date == null || localTime == null) {
            return date;
        }

        try {
            // 将Date转换为LocalDateTime
            java.time.Instant instant = date.toInstant();
            java.time.ZoneId zoneId = java.time.ZoneId.systemDefault();
            java.time.LocalDate localDate = instant.atZone(zoneId).toLocalDate();

            // 合并日期和时间
            java.time.LocalDateTime localDateTime = localDate.atTime(localTime);

            // 转换回Date
            return Date.from(localDateTime.atZone(zoneId).toInstant());
        } catch (Exception e) {
            log.error("合并日期和LocalTime异常，date={}，localTime={}，异常信息：{}", date, localTime, e.getMessage(), e);
            return date;
        }
    }

    @Override
    public IPage<StoreStaffConfig> getFoodStaffConfigList(int page, int size, Integer storeId, String staffPosition, String status) {
        IPage<StoreStaffConfig> storePage = new Page<>(page, size);
        QueryWrapper<StoreStaffConfig> queryWrapper = new QueryWrapper<>();
        // 按照店铺ID查询
        if (storeId != null && storeId > 0) {
            queryWrapper.eq("store_id", storeId);
        }
        // 按照职位查询
        if (StringUtils.isNotEmpty(staffPosition)) {
            queryWrapper.eq("staff_position", staffPosition);
        }
        // 按照状态查询
        if (StringUtils.isNotEmpty(status)) {
            queryWrapper.eq("status", status);
        }
        // 只查询未删除的记录
        queryWrapper.eq("delete_flag", 0);
        // 排序规则：先按置顶状态降序（置顶的在前），再按置顶时间降序，最后按创建时间降序
        queryWrapper.orderByDesc("top_status", "top_time", "created_time");
        return storeStaffConfigMapper.selectPage(storePage, queryWrapper);
    }

    @Override
    public StoreStaffDetailVo getStaffDetailWithCourse(Integer id) {
        log.info("查询员工详情（包含课程信息），id={}", id);

        // 参数校验
        if (id == null || id <= 0) {
            log.warn("查询员工详情失败，员工ID无效：{}", id);
            return null;
        }

        try {
            // 查询员工基本信息
            LambdaQueryWrapper<StoreStaffConfig> staffWrapper = new LambdaQueryWrapper<>();
            staffWrapper.eq(StoreStaffConfig::getId, id)
                    .eq(StoreStaffConfig::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE);
            StoreStaffConfig staffConfig = storeStaffConfigMapper.selectOne(staffWrapper);

            if (staffConfig == null) {
                log.warn("查询员工详情失败，员工不存在：id={}", id);
                return null;
            }

            // 查询关联的课程信息
            List<StoreStaffFitnessCourse> courseList =
                    storeStaffFitnessCourseService.getListByStaffId(id);


            // 根据店铺ID查询店铺名称
            String storeName = null;
            if (staffConfig.getStoreId() != null && staffConfig.getStoreId() > 0) {
                try {
                    StoreInfo storeInfo = storeInfoMapper.selectById(staffConfig.getStoreId());
                    if (storeInfo != null) {
                        storeName = storeInfo.getStoreName();
                    } else {
                        log.warn("查询店铺信息失败，店铺不存在：storeId={}", staffConfig.getStoreId());
                    }
                } catch (Exception e) {
                    log.warn("查询店铺信息异常，storeId={}，异常信息：{}", staffConfig.getStoreId(), e.getMessage());
                    // 店铺信息查询失败不影响整体返回，设置为null即可
                }
            }

            // 构建返回对象
            StoreStaffDetailVo detailVo = new StoreStaffDetailVo();
            detailVo.setStaffInfo(staffConfig);
            detailVo.setCourseList(courseList);

            log.info("查询员工详情成功，id={}，课程数量：{}", id, courseList != null ? courseList.size() : 0);
            detailVo.setStoreName(storeName);

            log.info("查询员工详情成功，id={}，课程数量：{}，店铺名称：{}",
                    id,
                    courseList != null ? courseList.size() : 0,
                    storeName);
            return detailVo;
        } catch (Exception e) {
            log.error("查询员工详情异常，id={}，异常信息：{}", id, e.getMessage(), e);
            throw new RuntimeException("查询员工详情异常：" + e.getMessage(), e);
        }
    }

    @Override
    public StoreStaffFitnessDetailVo getFitnessCoachDetail(Integer id) {
        log.info("查询健身教练详情，id={}", id);

        // 参数校验
        if (id == null || id <= 0) {
            log.warn("查询健身教练详情失败，员工ID无效：{}", id);
            return null;
        }

        try {
            // 查询员工基本信息
            LambdaQueryWrapper<StoreStaffConfig> staffWrapper = new LambdaQueryWrapper<>();
            staffWrapper.eq(StoreStaffConfig::getId, id)
                    .eq(StoreStaffConfig::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE);
            StoreStaffConfig staffConfig = storeStaffConfigMapper.selectOne(staffWrapper);

            if (staffConfig == null) {
                log.warn("查询健身教练详情失败，员工不存在：id={}", id);
                return null;
            }

            // 查询员工基本信息（运动健身）
            StoreStaffFitnessBase baseInfo = null;
            try {
                R<StoreStaffFitnessBase> baseResult =
                        storeStaffFitnessBaseService.getByStaffId(id);
                if (baseResult != null && R.isSuccess(baseResult) && baseResult.getData() != null) {
                    baseInfo = baseResult.getData();
                }
            } catch (Exception e) {
                log.warn("查询员工基本信息失败，id={}，异常信息：{}", id, e.getMessage());
                // 基本信息查询失败不影响整体返回，设置为null即可
            }

            // 查询认证列表（type=1）
            List<StoreStaffFitnessCertification> certificationList =
                    storeStaffFitnessCertificationService.getListByStaffIdAndType(id, CERTIFICATION_TYPE);

            // 查询荣誉列表（type=2）
            List<StoreStaffFitnessCertification> honorList =
                    storeStaffFitnessCertificationService.getListByStaffIdAndType(id, HONOR_TYPE);


            // 查询从业经历列表
            List<StoreStaffFitnessExperience> experienceList = null;
            try {
                experienceList = storeStaffFitnessExperienceService.getListByStaffId(id);
            } catch (Exception e) {
                log.warn("查询从业经历列表失败，id={}，异常信息：{}", id, e.getMessage());
                // 从业经历查询失败不影响整体返回，设置为null即可
            }

            // 根据店铺ID查询店铺名称
            String storeName = null;
            if (staffConfig.getStoreId() != null && staffConfig.getStoreId() > 0) {
                try {
                    StoreInfo storeInfo = storeInfoMapper.selectById(staffConfig.getStoreId());
                    if (storeInfo != null) {
                        storeName = storeInfo.getStoreName();
                    } else {
                        log.warn("查询店铺信息失败，店铺不存在：storeId={}", staffConfig.getStoreId());
                    }
                } catch (Exception e) {
                    log.warn("查询店铺信息异常，storeId={}，异常信息：{}", staffConfig.getStoreId(), e.getMessage());
                    // 店铺信息查询失败不影响整体返回，设置为null即可
                }
            }

            // 构建返回对象
            StoreStaffFitnessDetailVo detailVo = new StoreStaffFitnessDetailVo();
            detailVo.setStaffInfo(staffConfig);
            detailVo.setBaseInfo(baseInfo);
            detailVo.setCertificationList(certificationList != null ? certificationList : new ArrayList<>());
            detailVo.setHonorList(honorList != null ? honorList : new ArrayList<>());
            detailVo.setExperienceList(experienceList != null ? experienceList : new ArrayList<>());
            detailVo.setStoreName(storeName);

            log.info("查询健身教练详情成功，id={}，认证数量：{}，荣誉数量：{}，从业经历数量：{}，店铺名称：{}",
                    id, 
                    certificationList != null ? certificationList.size() : 0,
                    honorList != null ? honorList.size() : 0,
                    experienceList != null ? experienceList.size() : 0,
                    storeName);
            return detailVo;
        } catch (Exception e) {
            log.error("查询健身教练详情异常，id={}，异常信息：{}", id, e.getMessage(), e);
            throw new RuntimeException("查询健身教练详情异常：" + e.getMessage(), e);
        }
    }

    @Override
    public List<StoreStaffPositionCountVo> getStaffPositionCount(Integer storeId) {
        log.info("查询员工职位统计，storeId={}", storeId);

        // 参数校验
        if (storeId == null || storeId <= 0) {
            log.warn("查询员工职位统计失败，店铺ID无效：storeId={}", storeId);
            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
        }

        // 构建查询条件：查询指定店铺下未删除的员工
        LambdaQueryWrapper<StoreStaffConfig> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StoreStaffConfig::getStoreId, storeId)
                .eq(StoreStaffConfig::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE)
                // 只查询staff_position不为空的记录
                .isNotNull(StoreStaffConfig::getStaffPosition)
                .ne(StoreStaffConfig::getStaffPosition, "");

        // 查询所有符合条件的员工
        List<StoreStaffConfig> staffList = storeStaffConfigMapper.selectList(queryWrapper);

        // 按职位分组统计（查询条件已过滤空值，此处直接分组即可）
        Map<String, Long> positionCountMap = staffList.stream()
                .collect(Collectors.groupingBy(
                        StoreStaffConfig::getStaffPosition,
                        Collectors.counting()
                ));

        // 转换为VO列表
        List<StoreStaffPositionCountVo> result = positionCountMap.entrySet().stream()
                .map(entry -> {
                    StoreStaffPositionCountVo vo = new StoreStaffPositionCountVo();
                    vo.setStaffPosition(entry.getKey());
                    vo.setCount(entry.getValue());
                    return vo;
                })
                .collect(Collectors.toList());

        log.info("查询员工职位统计成功，storeId={}，职位数量：{}", storeId, result.size());
        return result;
    }

    /**
     * 员工列表查询（按标题分组）（用户端）
     * <p>
     * 根据店铺ID查询store_staff_title表中的记录，并通过staff_ids关联出store_staff_config
     * 返回按标题分组的员工列表，每个标题下包含对应的员工信息
     * 保留原有逻辑：今日是否有演出、点赞数、好评数等
     * </p>
     *
     * @param storeId 店铺ID，必须大于0
     * @return 按标题分组的员工列表
     */
    @Override
    public List<StaffTitleGroupVo> queryStaffListByTitle(Integer storeId) {
        log.info("查询员工列表（按标题分组），参数：storeId={}", storeId);

        // 参数校验
        if (storeId == null || storeId <= 0) {
            log.warn("查询员工列表（按标题分组）失败，店铺ID无效：storeId={}", storeId);
            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
        }

        try {
            // 1. 查询store_staff_title表中的记录
            LambdaQueryWrapper<StoreStaffTitle> titleWrapper = new LambdaQueryWrapper<>();
            titleWrapper.eq(StoreStaffTitle::getStoreId, storeId)
                    .eq(StoreStaffTitle::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE)
                    .orderByAsc(StoreStaffTitle::getCreatedTime);

            List<StoreStaffTitle> titleList = storeStaffTitleMapper.selectList(titleWrapper);

            if (titleList == null || titleList.isEmpty()) {
                log.info("查询员工列表（按标题分组）成功，但未找到标题记录，storeId={}", storeId);
                return new ArrayList<>();
            }

            // 2. 收集所有员工ID
            List<Integer> allStaffIds = new ArrayList<>();
            for (StoreStaffTitle title : titleList) {
                if (StringUtils.isNotEmpty(title.getStaffIds())) {
                    List<Integer> staffIds = parseStaffConfigIds(title.getStaffIds());
                    allStaffIds.addAll(staffIds);
                }
            }

            if (allStaffIds.isEmpty()) {
                log.info("查询员工列表（按标题分组）成功，但未找到员工ID，storeId={}", storeId);
                return new ArrayList<>();
            }

            // 3. 批量查询员工信息
            List<StoreStaffConfig> allStaffList = storeStaffConfigMapper.selectBatchIds(allStaffIds);

            // 4. 构建员工ID到员工对象的映射
            // 过滤条件：未删除、属于当前店铺、status为1（审核通过）、online_status为0（上线）
            // 必须与 queryStaffListByTitleId 一致校验 storeId，避免 title.staff_ids 误配时串店展示
            Map<Integer, StoreStaffConfig> staffMap = allStaffList.stream()
                    .filter(staff -> staff != null
                            && storeId.equals(staff.getStoreId())
                            && CommonConstant.DELETE_FLAG_UNDELETE.equals(staff.getDeleteFlag())
                            && "1".equals(staff.getStatus())
                            && staff.getOnlineStatus() != null && staff.getOnlineStatus() == 0)
                    .collect(Collectors.toMap(StoreStaffConfig::getId, staff -> staff, (a, b) -> a));

            // 5. 批量查询今日有演出的员工ID集合（性能优化）
            Set<Integer> staffIdsWithPerformanceToday = queryStaffIdsWithPerformanceToday(allStaffIds);

            // 6. 批量查询员工好评数（business_type=5, score>=4.5, business_id=员工ID）
            Map<Integer, Integer> positiveCommentsCountMap = queryPositiveCommentsCountMap(allStaffIds, storeId);

            // 7. 按标题分组构建结果
            List<StaffTitleGroupVo> result = new ArrayList<>();
            for (StoreStaffTitle title : titleList) {
                StaffTitleGroupVo groupVo = new StaffTitleGroupVo();
                groupVo.setTitleId(title.getId());
                groupVo.setTitleName(title.getTitleName());
                groupVo.setStaffCount(title.getStaffCount());

                // 解析该标题下的员工ID
                List<Integer> titleStaffIds = parseStaffConfigIds(title.getStaffIds());
                List<StoreStaffConfig> titleStaffList = new ArrayList<>();

                for (Integer staffId : titleStaffIds) {
                    StoreStaffConfig staff = staffMap.get(staffId);
                    if (staff != null) {
                        // 填充今日是否有演出
                        Boolean hasPerformanceToday = staffIdsWithPerformanceToday.contains(staffId);
                        staff.setHasPerformanceToday(hasPerformanceToday);

                        // 填充好评数
                        Integer positiveCommentsCount = positiveCommentsCountMap.getOrDefault(staffId, 0);
                        staff.setPositiveCommentsCount(positiveCommentsCount);

                        titleStaffList.add(staff);
                    }
                }
                titleStaffList.sort((x, y) -> {
                            // 获取两个对象的topTime
                            Date xTime = x.getTopTime();
                            Date yTime = y.getTopTime();

                            // 处理null值的情况
                            if (xTime == null && yTime == null) {
                                return 0; // 两个都为null，视为相等
                            }
                            if (xTime == null) {
                                return 1; // x为null，排到后面（y在前）
                            }
                            if (yTime == null) {
                                return -1; // y为null，排到后面（x在前）
                            }

                            // 都不为null时，正常比较（按时间降序）
                            return yTime.compareTo(xTime);});
                groupVo.setStaffList(titleStaffList);
                result.add(groupVo);
            }

            log.info("查询员工列表（按标题分组）成功，storeId={}，标题数量：{}", storeId, result.size());
            return result;
        } catch (Exception e) {
            log.error("查询员工列表（按标题分组）异常，storeId={}，异常信息：{}", storeId, e.getMessage(), e);
            throw new RuntimeException("查询员工列表（按标题分组）失败：" + e.getMessage(), e);
        }
    }

    /**
     * 批量查询员工好评数
     * <p>
     * 从store_staff_review表中查询好评数（overall_rating>4.5, staff_user_id=员工ID）
     * </p>
     *
     * @param staffIds 员工ID列表
     * @param storeId  店铺ID（此参数保留以兼容现有调用，但store_staff_review表中可能不需要此字段）
     * @return 员工ID到好评数的映射
     */
    private Map<Integer, Integer> queryPositiveCommentsCountMap(List<Integer> staffIds, Integer storeId) {
        Map<Integer, Integer> countMap = new HashMap<>();

        if (staffIds == null || staffIds.isEmpty()) {
            return countMap;
        }

        try {
            // 查询好评（overall_rating>4.5, staff_user_id in staffIds）；与评价列表 SQL 一致仅统计审核通过
            LambdaQueryWrapper<StoreStaffReview> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(StoreStaffReview::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE)
                    .eq(StoreStaffReview::getAuditStatus, 1)
                    .ge(StoreStaffReview::getOverallRating, new java.math.BigDecimal("4.5"))
                    .in(StoreStaffReview::getStaffUserId, staffIds);

            List<StoreStaffReview> positiveReviews = storeStaffReviewMapper.selectList(queryWrapper);

            if (positiveReviews != null && !positiveReviews.isEmpty()) {
                // 按staff_user_id分组统计
                Map<Integer, Long> countMapLong = positiveReviews.stream()
                        .collect(Collectors.groupingBy(StoreStaffReview::getStaffUserId, Collectors.counting()));

                // 转换为Integer
                for (Map.Entry<Integer, Long> entry : countMapLong.entrySet()) {
                    countMap.put(entry.getKey(), entry.getValue().intValue());
                }
            }
        } catch (Exception e) {
            log.error("批量查询员工好评数异常，异常信息：{}", e.getMessage(), e);
        }

        return countMap;
    }

    /**
     * 根据标题ID查询员工列表（用户端）
     * <p>
     * 根据店铺ID和标题ID查询store_staff_title表中的记录，并通过staff_ids关联出store_staff_config
     * 返回该标题下的员工列表
     * 保留原有逻辑：今日是否有演出、点赞数、好评数等
     * </p>
     *
     * @param storeId 店铺ID，必须大于0
     * @param titleId 标题ID，必须大于0
     * @return 员工列表
     */
    @Override
    public List<StoreStaffConfig> queryStaffListByTitleId(Integer storeId, Integer titleId) {
        log.info("根据标题ID查询员工列表，参数：storeId={}, titleId={}", storeId, titleId);

        // 参数校验
        if (storeId == null || storeId <= 0) {
            log.warn("根据标题ID查询员工列表失败，店铺ID无效：storeId={}", storeId);
            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
        }
        if (titleId == null || titleId <= 0) {
            log.warn("根据标题ID查询员工列表失败，标题ID无效：titleId={}", titleId);
            throw new IllegalArgumentException("标题ID不能为空且必须大于0");
        }

        try {
            // 1. 查询store_staff_title表中的记录
            LambdaQueryWrapper<StoreStaffTitle> titleWrapper = new LambdaQueryWrapper<>();
            titleWrapper.eq(StoreStaffTitle::getId, titleId)
                    .eq(StoreStaffTitle::getStoreId, storeId)
                    .eq(StoreStaffTitle::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE);

            StoreStaffTitle title = storeStaffTitleMapper.selectOne(titleWrapper);

            if (title == null) {
                log.warn("根据标题ID查询员工列表失败，标题记录不存在：storeId={}, titleId={}", storeId, titleId);
                return new ArrayList<>();
            }

            // 2. 解析员工IDs
            if (StringUtils.isEmpty(title.getStaffIds())) {
                log.info("根据标题ID查询员工列表成功，但标题下无员工：storeId={}, titleId={}", storeId, titleId);
                return new ArrayList<>();
            }

            List<Integer> staffIds = parseStaffConfigIds(title.getStaffIds());

            if (staffIds.isEmpty()) {
                log.info("根据标题ID查询员工列表成功，但解析员工ID为空：storeId={}, titleId={}", storeId, titleId);
                return new ArrayList<>();
            }

            // 3. 批量查询员工信息
            List<StoreStaffConfig> staffList = storeStaffConfigMapper.selectBatchIds(staffIds);

            if (staffList == null || staffList.isEmpty()) {
                log.info("根据标题ID查询员工列表成功，但未找到员工记录：storeId={}, titleId={}", storeId, titleId);
                return new ArrayList<>();
            }

            // 4. 过滤已删除的员工，并根据title中的storeId过滤，只返回status为1（审核通过）的员工
            List<StoreStaffConfig> validStaffList = staffList.stream()
                    .filter(staff -> staff != null 
                            && CommonConstant.DELETE_FLAG_UNDELETE.equals(staff.getDeleteFlag())
                            && storeId.equals(staff.getStoreId())
                            && 0 ==(staff.getOnlineStatus())
                            && "1".equals(staff.getStatus()))
                    .collect(Collectors.toList());

            if (validStaffList.isEmpty()) {
                log.info("根据标题ID查询员工列表成功，但有效员工为空：storeId={}, titleId={}", storeId, titleId);
                return new ArrayList<>();
            }

            // 5. 批量查询今日有演出的员工ID集合（性能优化）
            List<Integer> validStaffIds = validStaffList.stream()
                    .map(StoreStaffConfig::getId)
                    .filter(id -> id != null && id > 0)
                    .collect(Collectors.toList());

            Set<Integer> staffIdsWithPerformanceToday = queryStaffIdsWithPerformanceToday(validStaffIds);

            // 6. 批量查询员工好评数
            Map<Integer, Integer> positiveCommentsCountMap = queryPositiveCommentsCountMap(validStaffIds, storeId);

            // 7. 填充字段
            for (StoreStaffConfig staff : validStaffList) {
                if (staff.getId() != null) {
                    // 填充今日是否有演出
                    Boolean hasPerformanceToday = staffIdsWithPerformanceToday.contains(staff.getId());
                    staff.setHasPerformanceToday(hasPerformanceToday);

                    // 填充好评数
                    Integer positiveCommentsCount = positiveCommentsCountMap.getOrDefault(staff.getId(), 0);
                    staff.setPositiveCommentsCount(positiveCommentsCount);
                } else {
                    staff.setHasPerformanceToday(false);
                    staff.setPositiveCommentsCount(0);
                }
            }

            log.info("根据标题ID查询员工列表成功，storeId={}, titleId={}，员工数量：{}",
                    storeId, titleId, validStaffList.size());
            return validStaffList;
        } catch (Exception e) {
            log.error("根据标题ID查询员工列表异常，storeId={}, titleId={}，异常信息：{}",
                    storeId, titleId, e.getMessage(), e);
            throw new RuntimeException("根据标题ID查询员工列表失败：" + e.getMessage(), e);
        }
    }

    /**
     * 检查用户是否喜欢该员工
     * <p>
     * 根据userId查询life_like_record表，判断是否存在点赞记录
     * type = "8" 表示点赞员工
     * </p>
     *
     * @param staffId 员工ID
     * @param userId 用户ID，可为null（未登录时返回false）
     * @return true-已喜欢，false-未喜欢
     */
    private Boolean checkIsLiked(Integer staffId, String userId) {
        // 如果用户未登录，返回false
        if (StringUtils.isEmpty(userId)) {
            return false;
        }

        try {
            StoreLikerScope likerScope = lifeLikeIdentityHelper.resolveFromDianzanId(userId);
            LambdaQueryWrapper<LifeLikeRecord> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(LifeLikeRecord::getType, "8") // 8-点赞员工
                    .eq(LifeLikeRecord::getHuifuId, String.valueOf(staffId))
                    .eq(LifeLikeRecord::getDeleteFlag, 0);
            lifeLikeIdentityHelper.applyLikerFilter(queryWrapper, likerScope);
            long count = lifeLikeRecordMapper.selectCount(queryWrapper);
            return count > 0;
        } catch (Exception e) {
            log.error("查询员工是否喜欢异常，staffId={}，userId={}，异常信息：{}", 
                    staffId, userId, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 处理视频封面URL生成
     * 为background_url中的视频文件生成封面URL（通过改变后缀）并保存到video_head_url字段
     *
     * @param storeStaffConfig 员工配置信息
     */
    private void processVideoCovers(StoreStaffConfig storeStaffConfig) {
        try {
            log.info("开始处理视频封面URL生成，staffId={}", storeStaffConfig.getId());

            String backgroundUrl = storeStaffConfig.getBackgroundUrl();
            if (StringUtils.isEmpty(backgroundUrl)) {
                return;
            }

            String[] urls = backgroundUrl.split(",");
            List<String> videoCoverUrls = new ArrayList<>();

            for (String url : urls) {
                if (StringUtils.isNotEmpty(url.trim())) {
                    String trimmedUrl = url.trim();
                    if (isVideoUrl(trimmedUrl)) {
                        // 为视频生成封面URL
                        String coverUrl = generateVideoCover(trimmedUrl);
                        if (StringUtils.isNotEmpty(coverUrl)) {
                            videoCoverUrls.add(coverUrl);
                            log.info("视频封面URL生成成功，视频URL={}，封面URL={}", trimmedUrl, coverUrl);
                        } else {
                            log.warn("视频封面URL生成失败，视频URL={}", trimmedUrl);
                        }
                    }
                }
            }

            // 更新video_head_url字段
            if (!videoCoverUrls.isEmpty()) {
                String videoHeadUrlStr = String.join(",", videoCoverUrls);
                StoreStaffConfig updateCover = new StoreStaffConfig();
                updateCover.setId(storeStaffConfig.getId());
                updateCover.setVideoHeadUrl(videoHeadUrlStr);
                storeStaffConfigMapper.updateById(updateCover);
                log.info("更新视频封面URL成功，staffId={}，videoHeadUrl={}", storeStaffConfig.getId(), videoHeadUrlStr);
            }

        } catch (Exception e) {
            log.error("处理视频封面URL生成异常，staffId={}，异常信息：{}", storeStaffConfig.getId(), e.getMessage(), e);
        }
    }

    /**
     * 为单个视频生成封面URL
     * 直接通过改变视频URL的后缀来生成封面URL
     *
     * @param videoUrl 视频URL
     * @return 封面图片URL
     */
    private String generateVideoCover(String videoUrl) {
        if (StringUtils.isEmpty(videoUrl)) {
            return null;
        }

        try {
            // 找到最后一个点的位置
            int lastDotIndex = videoUrl.lastIndexOf('.');
            if (lastDotIndex == -1) {
                // 如果没有扩展名，直接添加.jpg
                return videoUrl + ".jpg";
            }

            // 替换扩展名为.jpg
            return videoUrl.substring(0, lastDotIndex) + ".jpg";
        } catch (Exception e) {
            log.error("生成视频封面URL异常，videoUrl={}，异常信息：{}", videoUrl, e.getMessage(), e);
            return null;
        }
    }
}
