package shop.alien.store.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.stereotype.Service;
import shop.alien.entity.store.BarPerformance;
import shop.alien.entity.store.StoreDictionary;
import shop.alien.entity.store.StoreStaffConfig;
import shop.alien.entity.store.vo.PerformanceDetailVo;
import shop.alien.entity.store.vo.PerformanceGroupByDateVo;
import shop.alien.entity.store.vo.PerformanceGroupListVo;
import shop.alien.entity.store.vo.PerformanceGuestVo;
import shop.alien.entity.store.vo.PerformanceListVo;
import shop.alien.mapper.BarPerformanceMapper;
import shop.alien.mapper.StoreDictionaryMapper;
import shop.alien.mapper.StoreStaffConfigMapper;
import shop.alien.store.service.PerformanceListService;
import shop.alien.store.util.CommonConstant;

import java.text.SimpleDateFormat;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 演出列表服务实现类
 * 实现用户端演出列表查询功能
 *
 * @author system
 * @since 2025-01-XX
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PerformanceListServiceImpl implements PerformanceListService {

    private final BarPerformanceMapper barPerformanceMapper;
    private final StoreStaffConfigMapper storeStaffConfigMapper;
    private final StoreDictionaryMapper storeDictionaryMapper;

    /**
     * 日期格式化：yyyy.MM.dd
     */
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy.MM.dd");

    /**
     * 当日演出日期格式化：yyyy.M.d
     */
    private static final SimpleDateFormat TODAY_DATE_FORMAT = new SimpleDateFormat("yyyy.M.d");

    /**
     * 日期格式化：MM-dd（用于日期标题）
     */
    private static final SimpleDateFormat DATE_TITLE_FORMAT = new SimpleDateFormat("MM-dd");

    /**
     * 日期格式化：yyyy-MM-dd（用于日期字符串）
     */
    private static final SimpleDateFormat DATE_STRING_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

    /**
     * 时间格式化：HH:mm
     */
    private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm");

    /**
     * LocalTime格式化：HH:mm
     */
    private static final DateTimeFormatter LOCAL_TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm");

    /**
     * 星期几中文数组
     * Calendar中：1=周日，2=周一，...，7=周六
     */
    private static final String[] WEEK_DAYS = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};

    @Override
    public IPage<PerformanceListVo> queryPerformanceList(Integer page, Integer size, Integer storeId) {
        log.info("查询演出列表，参数：page={}, size={}, storeId={}", page, size, storeId);

        // 参数校验
        validateQueryParams(page, size, storeId);

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

        // 构建查询条件：仅店铺 + 已上线
        LambdaQueryWrapper<BarPerformance> queryWrapper = buildOnlineListQueryWrapper(storeId);

        // 执行查询
        IPage<BarPerformance> result = barPerformanceMapper.selectPage(performancePage, queryWrapper);

        // 转换为VO列表
        List<PerformanceListVo> voList = convertToVoList(result.getRecords());

        // 构建返回结果
        IPage<PerformanceListVo> voPage = new Page<>(page, size, result.getTotal());
        voPage.setRecords(voList);

        log.info("查询演出列表成功，店铺ID={}，共{}条记录，当前页{}条", 
                storeId, result.getTotal(), voList.size());
        return voPage;
    }

    /**
     * 校验查询参数
     *
     * @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 (size > CommonConstant.MAX_PAGE_SIZE) {
            throw new IllegalArgumentException("分页条数不能超过" + CommonConstant.MAX_PAGE_SIZE);
        }
        if (storeId == null || storeId <= 0) {
            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
        }
    }

    /**
     * 构建用户端列表查询条件（/performance/list/query）
     * 仅查询指定店铺下已上线、未删除的演出，不做审核/过期等额外筛选
     *
     * @param storeId 店铺ID
     * @return 查询条件包装器
     */
    private LambdaQueryWrapper<BarPerformance> buildOnlineListQueryWrapper(Integer storeId) {
        LambdaQueryWrapper<BarPerformance> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BarPerformance::getStoreId, storeId)
                .eq(BarPerformance::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE)
                .eq(BarPerformance::getOnlineStatus, CommonConstant.PERFORMANCE_ONLINE_STATUS_ONLINE)
                .orderByDesc(BarPerformance::getCreatedTime);
        return queryWrapper;
    }

    /**
     * 构建查询条件（按日期分组等场景：含审核通过、未过期等筛选）
     *
     * @param storeId 店铺ID
     * @return 查询条件包装器
     */
    private LambdaQueryWrapper<BarPerformance> buildQueryWrapper(Integer storeId) {
        LambdaQueryWrapper<BarPerformance> queryWrapper = new LambdaQueryWrapper<>();

        // 必须条件：店铺ID、未删除、审核通过、已上线
        queryWrapper.eq(BarPerformance::getStoreId, storeId)
                .eq(BarPerformance::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE)
                .eq(BarPerformance::getReviewStatus, CommonConstant.PERFORMANCE_REVIEW_STATUS_APPROVED)
                .eq(BarPerformance::getOnlineStatus, CommonConstant.PERFORMANCE_ONLINE_STATUS_ONLINE).eq(BarPerformance::getStatus, 1);

        // 过滤已过期的演出
        Date now = new Date();
        // 获取今天的开始时间（00:00:00）
        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();

        // 使用and条件，确保至少满足以下条件之一（即未过期）：
        // 1. 单次演出：结束时间 >= 当前时间
        // 2. 定时演出（每天定时或每周定时）：结束日期 > 今天 或 (结束日期 = 今天 AND 结束时间 >= 当前时分秒)
        queryWrapper.and(wrapper -> {
            // 单次演出：结束时间 >= 现在
            wrapper.or(w -> w.eq(BarPerformance::getPerformanceFrequency, "0")
                    .ge(BarPerformance::getSingleEndDatetime, now));
            // 定时演出：结束日期 > 今天 或 (结束日期 = 今天 AND 结束时间 >= 当前时分秒)
            wrapper.or(w -> w.in(BarPerformance::getPerformanceFrequency, "1", "2")
                    .and(subWrapper -> {
                        // 结束日期 > 今天
                        subWrapper.gt(BarPerformance::getDailyEndDate, todayStart)
                                // 或 (结束日期 = 今天 AND 结束时间 >= 当前时分秒)
                                .or(subSubWrapper -> subSubWrapper.apply("DATE(daily_end_date) = CURDATE() AND daily_end_time >= TIME(NOW())"));
                    }));
        });

        // 排序规则：按创建时间降序
        queryWrapper.orderByDesc(BarPerformance::getCreatedTime);

        return queryWrapper;
    }

    /**
     * 转换为VO列表
     *
     * @param performances 演出列表
     * @return VO列表
     */
    private List<PerformanceListVo> convertToVoList(List<BarPerformance> performances) {
        if (performances == null || performances.isEmpty()) {
            return new ArrayList<>();
        }

        return performances.stream()
                .map(this::convertToVo)
                .collect(Collectors.toList());
    }

    /**
     * 转换为VO列表（用于按日期分组查询，过滤下线演出人员）
     *
     * @param performances 演出列表
     * @return VO列表
     */
    private List<PerformanceListVo> convertToVoListForGroupByDate(List<BarPerformance> performances) {
        if (performances == null || performances.isEmpty()) {
            return new ArrayList<>();
        }

        return performances.stream()
                .map(this::convertToVoForGroupByDate)
                .collect(Collectors.toList());
    }

    /**
     * 转换为VO
     *
     * @param performance 演出信息
     * @return VO对象
     */
    private PerformanceListVo convertToVo(BarPerformance performance) {
        PerformanceListVo vo = new PerformanceListVo();
        vo.setId(performance.getId());
        vo.setPerformanceName(performance.getPerformanceName());
        vo.setPerformancePoster(performance.getPerformancePoster());
        vo.setPerformanceType(performance.getPerformanceType());
        vo.setPerformanceFrequency(performance.getPerformanceFrequency());

        // 设置演出者信息（过滤下线演出人员）
        vo.setPerformersInfo(buildPerformersInfoFilterOffline(performance.getStaffConfigIds()));

        // 设置日期范围
        vo.setDateRange(buildDateRange(performance));

        // 设置演出时间安排
        vo.setScheduleInfo(buildScheduleInfo(performance));

        // 设置演出风格（直接返回表中的值，不查询字典）
        vo.setPerformanceStyle(performance.getPerformanceStyle());

        // 设置演出人员头像列表（过滤下线演出人员）
        vo.setStaffImageList(queryStaffImageListFilterOffline(performance.getStaffConfigIds()));

        // 设置当日演出时间
        vo.setTodayPerformanceTime(buildTodayPerformanceTime(performance));

        return vo;
    }

    /**
     * 转换为VO（用于按日期分组查询，过滤下线演出人员）
     *
     * @param performance 演出信息
     * @return VO对象
     */
    private PerformanceListVo convertToVoForGroupByDate(BarPerformance performance) {
        PerformanceListVo vo = new PerformanceListVo();
        vo.setId(performance.getId());
        vo.setPerformanceName(performance.getPerformanceName());
        vo.setPerformancePoster(performance.getPerformancePoster());
        vo.setPerformanceType(performance.getPerformanceType());
        vo.setPerformanceFrequency(performance.getPerformanceFrequency());

        // 设置演出者信息（过滤下线演出人员）
        vo.setPerformersInfo(buildPerformersInfoFilterOffline(performance.getStaffConfigIds()));

        // 设置日期范围
        vo.setDateRange(buildDateRange(performance));

        // 设置演出时间安排
        vo.setScheduleInfo(buildScheduleInfo(performance));

        // 设置演出风格（直接返回表中的值，不查询字典）
        vo.setPerformanceStyle(performance.getPerformanceStyle());

        // 设置演出人员头像列表（过滤下线演出人员）
        vo.setStaffImageList(queryStaffImageListFilterOffline(performance.getStaffConfigIds()));

        return vo;
    }

    /**
     * 构建演出者信息
     * <p>
     * 从员工ID列表中查询第一个有名字的员工，显示格式：
     * - 1人：显示员工名字
     * - 多人：显示"xx等X人"
     * </p>
     *
     * @param staffConfigIds 员工配置ID字符串（逗号分隔）
     * @return 演出者信息（如：刘能等7人）
     */
    private String buildPerformersInfo(String staffConfigIds) {
        if (StringUtils.isEmpty(staffConfigIds)) {
            return "";
        }

        try {
            String[] ids = staffConfigIds.split(",");
            List<Integer> staffIdList = new ArrayList<>();
            
            // 解析所有有效的员工ID
            for (String idStr : ids) {
                if (StringUtils.isNotEmpty(idStr.trim())) {
                    try {
                        Integer staffId = Integer.parseInt(idStr.trim());
                        if (staffId > 0) {
                            staffIdList.add(staffId);
                        }
                    } catch (NumberFormatException e) {
                        log.warn("解析员工配置ID失败，无效的ID：{}", idStr);
                    }
                }
            }

            if (staffIdList.isEmpty()) {
                return "";
            }

            int count = staffIdList.size();
            String firstName = null;

            // 遍历员工ID列表，找到第一个有名字的员工
            for (Integer staffId : staffIdList) {
                try {
                    StoreStaffConfig staff = storeStaffConfigMapper.selectById(staffId);
                    if (staff != null && StringUtils.isNotEmpty(staff.getName())) {
                        firstName = staff.getName();
                        break; // 找到第一个有名字的员工就退出
                    }
                } catch (Exception e) {
                    log.warn("查询员工信息失败，staffId={}，异常信息：{}", staffId, e.getMessage());
                    // 继续查询下一个员工
                }
            }

            // 根据人数和是否找到名字来构建返回信息
            if (count == 1) {
                return firstName != null ? firstName : "1人";
            } else {
                return firstName != null ? firstName + "等" + count + "人" : count + "人";
            }
        } catch (Exception e) {
            log.error("构建演出者信息异常，staffConfigIds={}，异常信息：{}", staffConfigIds, e.getMessage(), e);
            return "";
        }
    }

    /**
     * 构建演出者信息（过滤下线演出人员）
     * <p>
     * 从员工ID列表中查询第一个有名字且上线的员工，显示格式：
     * - 1人：显示员工名字
     * - 多人：显示"xx等X人"
     * 只统计上线的员工数量
     * </p>
     *
     * @param staffConfigIds 员工配置ID字符串（逗号分隔）
     * @return 演出者信息（如：刘能等7人，仅包含上线员工）
     */
    private String buildPerformersInfoFilterOffline(String staffConfigIds) {
        if (StringUtils.isEmpty(staffConfigIds)) {
            return "";
        }

        try {
            String[] ids = staffConfigIds.split(",");
            List<Integer> staffIdList = new ArrayList<>();
            
            // 解析所有有效的员工ID
            for (String idStr : ids) {
                if (StringUtils.isNotEmpty(idStr.trim())) {
                    try {
                        Integer staffId = Integer.parseInt(idStr.trim());
                        if (staffId > 0) {
                            staffIdList.add(staffId);
                        }
                    } catch (NumberFormatException e) {
                        log.warn("解析员工配置ID失败，无效的ID：{}", idStr);
                    }
                }
            }

            if (staffIdList.isEmpty()) {
                return "";
            }

            // 批量查询员工信息
            List<StoreStaffConfig> staffList = storeStaffConfigMapper.selectBatchIds(staffIdList);
            
            // 过滤出上线的员工
            List<StoreStaffConfig> onlineStaffList = new ArrayList<>();
            if (staffList != null && !staffList.isEmpty()) {
                for (StoreStaffConfig staff : staffList) {
                    if (staff != null 
                            && CommonConstant.DELETE_FLAG_UNDELETE.equals(staff.getDeleteFlag())
                            && "1".equals(staff.getStatus())
                            && CommonConstant.ONLINE_STATUS.equals(staff.getOnlineStatus())) {
                        onlineStaffList.add(staff);
                    }
                }
            }

            if (onlineStaffList.isEmpty()) {
                return "";
            }

            int count = onlineStaffList.size();
            String firstName = null;

            // 找到第一个有名字的上线员工
            for (StoreStaffConfig staff : onlineStaffList) {
                if (StringUtils.isNotEmpty(staff.getName())) {
                    firstName = staff.getName();
                    break; // 找到第一个有名字的员工就退出
                }
            }

            // 根据人数和是否找到名字来构建返回信息
            if (count == 1) {
                return firstName != null ? firstName : "1人";
            } else {
                return firstName != null ? firstName + "等" + count + "人" : count + "人";
            }
        } catch (Exception e) {
            log.error("构建演出者信息异常（过滤下线），staffConfigIds={}，异常信息：{}", staffConfigIds, e.getMessage(), e);
            return "";
        }
    }

    /**
     * 查询演出人员头像列表
     * <p>
     * 根据员工配置ID字符串（逗号分隔）查询store_staff_config表，获取所有员工的头像
     * </p>
     *
     * @param staffConfigIds 员工配置ID字符串（逗号分隔）
     * @return 员工头像URL列表
     */
    private List<String> queryStaffImageList(String staffConfigIds) {
        List<String> imageList = new ArrayList<>();
        
        if (StringUtils.isEmpty(staffConfigIds)) {
            return imageList;
        }

        try {
            String[] ids = staffConfigIds.split(",");
            List<Integer> staffIdList = new ArrayList<>();
            
            // 解析所有有效的员工ID
            for (String idStr : ids) {
                if (StringUtils.isNotEmpty(idStr.trim())) {
                    try {
                        Integer staffId = Integer.parseInt(idStr.trim());
                        if (staffId > 0) {
                            staffIdList.add(staffId);
                        }
                    } catch (NumberFormatException e) {
                        log.warn("解析员工配置ID失败，无效的ID：{}", idStr);
                    }
                }
            }

            if (staffIdList.isEmpty()) {
                return imageList;
            }

            // 批量查询员工信息
            List<StoreStaffConfig> staffList = storeStaffConfigMapper.selectBatchIds(staffIdList);
            
            if (staffList != null && !staffList.isEmpty()) {
                // 提取所有非空的头像URL
                for (StoreStaffConfig staff : staffList) {
                    if (staff != null && StringUtils.isNotEmpty(staff.getStaffImage())) {
                        imageList.add(staff.getStaffImage());
                    }
                }
            }
        } catch (Exception e) {
            log.error("查询演出人员头像列表异常，staffConfigIds={}，异常信息：{}", 
                    staffConfigIds, e.getMessage(), e);
        }

        return imageList;
    }

    /**
     * 查询演出人员头像列表（过滤下线演出人员）
     * <p>
     * 根据员工配置ID字符串（逗号分隔）查询store_staff_config表，只获取上线员工的头像
     * </p>
     *
     * @param staffConfigIds 员工配置ID字符串（逗号分隔）
     * @return 员工头像URL列表（仅包含上线员工）
     */
    private List<String> queryStaffImageListFilterOffline(String staffConfigIds) {
        List<String> imageList = new ArrayList<>();
        
        if (StringUtils.isEmpty(staffConfigIds)) {
            return imageList;
        }

        try {
            String[] ids = staffConfigIds.split(",");
            List<Integer> staffIdList = new ArrayList<>();
            
            // 解析所有有效的员工ID
            for (String idStr : ids) {
                if (StringUtils.isNotEmpty(idStr.trim())) {
                    try {
                        Integer staffId = Integer.parseInt(idStr.trim());
                        if (staffId > 0) {
                            staffIdList.add(staffId);
                        }
                    } catch (NumberFormatException e) {
                        log.warn("解析员工配置ID失败，无效的ID：{}", idStr);
                    }
                }
            }

            if (staffIdList.isEmpty()) {
                return imageList;
            }

            // 批量查询员工信息
            List<StoreStaffConfig> staffList = storeStaffConfigMapper.selectBatchIds(staffIdList);
            
            if (staffList != null && !staffList.isEmpty()) {
                // 只提取上线且非空的头像URL
                for (StoreStaffConfig staff : staffList) {
                    if (staff != null 
                            && CommonConstant.DELETE_FLAG_UNDELETE.equals(staff.getDeleteFlag())
                            && "1".equals(staff.getStatus())
                            && CommonConstant.ONLINE_STATUS.equals(staff.getOnlineStatus())
                            && StringUtils.isNotEmpty(staff.getStaffImage())) {
                        imageList.add(staff.getStaffImage());
                    }
                }
            }
        } catch (Exception e) {
            log.error("查询演出人员头像列表异常（过滤下线），staffConfigIds={}，异常信息：{}", 
                    staffConfigIds, e.getMessage(), e);
        }

        return imageList;
    }

    /**
     * 构建当日演出时间
     * <p>
     * 仅单次演出（performance_frequency=0）且今天与演出时间有重叠时返回，格式：2026.6.3/ 09:00 – 2026.6.6/05:00
     * 每天定时/每周定时演出已有 scheduleInfo 展示规律时间，不返回此字段
     * </p>
     *
     * @param performance 演出信息
     * @return 当日演出时间，非当日单次演出返回null
     */
    private String buildTodayPerformanceTime(BarPerformance performance) {
        if (performance == null
                || !CommonConstant.PERFORMANCE_FREQUENCY_SINGLE.equals(performance.getPerformanceFrequency())) {
            return null;
        }

        TodayTimeRange todayTimeRange = getTodayTimeRange();
//        if (!isSinglePerformanceToday(performance, todayTimeRange)) {
//            return null;
//        }

        Date startTime = performance.getSingleStartDatetime();
        Date endTime = performance.getSingleEndDatetime();
        if (startTime == null || endTime == null) {
            return null;
        }

        try {
            String startStr = TODAY_DATE_FORMAT.format(startTime) + "/" + TIME_FORMAT.format(startTime);
            String endStr = TODAY_DATE_FORMAT.format(endTime) + "/" + TIME_FORMAT.format(endTime);
            return startStr + " – " + endStr;
        } catch (Exception e) {
            log.error("构建当日演出时间异常，performanceId={}，异常信息：{}", performance.getId(), e.getMessage(), e);
            return null;
        }
    }

    /**
     * 判断单次演出是否在今天
     */
    private boolean isSinglePerformanceToday(BarPerformance performance, TodayTimeRange todayTimeRange) {
        Date singleStart = performance.getSingleStartDatetime();
        Date singleEnd = performance.getSingleEndDatetime();
        if (singleStart == null || singleEnd == null) {
            return false;
        }
        return !singleStart.after(todayTimeRange.getEnd()) && !singleEnd.before(todayTimeRange.getStart());
    }

    /**
     * 获取今天的时间范围
     */
    private TodayTimeRange getTodayTimeRange() {
        java.util.Calendar cal = java.util.Calendar.getInstance();

        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.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);
    }

    /**
     * 今天的时间范围
     */
    private static class TodayTimeRange {
        private final Date start;
        private final Date end;

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

        Date getStart() {
            return start;
        }

        Date getEnd() {
            return end;
        }
    }

    /**
     * 构建日期范围
     *
     * @param performance 演出信息
     * @return 日期范围（格式：2025.11.11-2027.01.31）
     */
    private String buildDateRange(BarPerformance performance) {
        String frequency = performance.getPerformanceFrequency();
        if (StringUtils.isEmpty(frequency)) {
            return "";
        }

        try {
            switch (frequency) {
                case CommonConstant.PERFORMANCE_FREQUENCY_SINGLE:
                    // 单次演出：使用singleStartDatetime和singleEndDatetime
                    Date singleStart = performance.getSingleStartDatetime();
                    Date singleEnd = performance.getSingleEndDatetime();
                    if (singleStart != null && singleEnd != null) {
                        return DATE_FORMAT.format(singleStart) + "-" + DATE_FORMAT.format(singleEnd);
                    }
                    break;
                case CommonConstant.PERFORMANCE_FREQUENCY_DAILY:
                case CommonConstant.PERFORMANCE_FREQUENCY_WEEKLY:
                    // 每天定时或每周定时：使用dailyStartDate和dailyEndDate
                    Date dailyStart = performance.getDailyStartDate();
                    Date dailyEnd = performance.getDailyEndDate();
                    if (dailyStart != null && dailyEnd != null) {
                        return DATE_FORMAT.format(dailyStart) + "-" + DATE_FORMAT.format(dailyEnd);
                    }
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            log.error("构建日期范围异常，performanceId={}，异常信息：{}", performance.getId(), e.getMessage(), e);
        }

        return "";
    }

    /**
     * 构建演出时间安排
     *
     * @param performance 演出信息
     * @return 演出时间安排（格式：每周一、二、三、四19:30-次日00:00）
     */
    private String buildScheduleInfo(BarPerformance performance) {
        String frequency = performance.getPerformanceFrequency();
        if (StringUtils.isEmpty(frequency)) {
            return "";
        }

        try {
            switch (frequency) {
                case CommonConstant.PERFORMANCE_FREQUENCY_SINGLE:
                    // 单次演出：显示具体日期和时间
                    Date singleStart = performance.getSingleStartDatetime();
                    Date singleEnd = performance.getSingleEndDatetime();
                    if (singleStart != null && singleEnd != null) {
                        return buildSingleScheduleInfo(singleStart, singleEnd);
                    }
                    break;
                case CommonConstant.PERFORMANCE_FREQUENCY_DAILY:
                    // 每天定时：使用dailyStartTime和dailyEndTime
                    LocalTime dailyStartTime = performance.getDailyStartTime();
                    LocalTime dailyEndTime = performance.getDailyEndTime();
                    if (dailyStartTime != null && dailyEndTime != null) {
                        return "每天" + buildLocalTimeRange(dailyStartTime, dailyEndTime);
                    }
                    break;
                case CommonConstant.PERFORMANCE_FREQUENCY_WEEKLY:
                    // 每周定时：显示星期几和时间，使用dailyStartTime和dailyEndTime
                    String performanceWeek = performance.getPerformanceWeek();
                    LocalTime weeklyStartTime = performance.getDailyStartTime();
                    LocalTime weeklyEndTime = performance.getDailyEndTime();
                    if (StringUtils.isNotEmpty(performanceWeek) && weeklyStartTime != null && weeklyEndTime != null) {
                        return buildWeeklyScheduleInfo(performanceWeek, weeklyStartTime, weeklyEndTime);
                    }
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            log.error("构建演出时间安排异常，performanceId={}，异常信息：{}", performance.getId(), e.getMessage(), e);
        }

        return "";
    }

    /**
     * 构建单次演出时间安排
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 时间安排字符串
     */
    private String buildSingleScheduleInfo(Date startTime, Date endTime) {
        java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.setTime(startTime);
        int dayOfWeek = cal.get(java.util.Calendar.DAY_OF_WEEK);
        String weekDay = WEEK_DAYS[dayOfWeek - 1];

        return weekDay + " " + buildTimeRange(startTime, endTime);
    }

    /**
     * 构建每周定时演出时间安排（使用LocalTime）
     *
     * @param performanceWeek 星期几字符串（0-周一，1-周二，...，6-周日，逗号分隔）
     * @param startTime        开始时间（LocalTime）
     * @param endTime          结束时间（LocalTime）
     * @return 时间安排字符串
     */
    private String buildWeeklyScheduleInfo(String performanceWeek, LocalTime startTime, LocalTime endTime) {
        String[] weekDays = performanceWeek.split(",");
        List<String> weekDayList = new ArrayList<>();

        String[] weeklyLabels = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};
        for (String weekDay : weekDays) {
            if (StringUtils.isNotEmpty(weekDay.trim())) {
                try {
                    int dayIndex = Integer.parseInt(weekDay.trim());
                    if (dayIndex >= 0 && dayIndex < weeklyLabels.length) {
                        weekDayList.add(weeklyLabels[dayIndex]);
                    }
                } catch (NumberFormatException e) {
                    log.warn("解析星期几失败，无效的值：{}", weekDay);
                }
            }
        }

        if (weekDayList.isEmpty()) {
            return "";
        }

        String weekDayStr = buildWeeklyDayText(weekDayList);
        String timeRange = buildLocalTimeRange(startTime, endTime);

        return "每周" + weekDayStr + timeRange;
    }

    private String buildWeeklyDayText(List<String> weekDayList) {
        if (weekDayList == null || weekDayList.isEmpty()) {
            return "";
        }
        List<String> normalized = new ArrayList<>();
        for (String day : weekDayList) {
            if (day != null && day.startsWith("周")) {
                day = day.substring(1);
            }
            normalized.add(day);
        }
        return String.join("、", normalized);
    }

    /**
     * 构建时间范围（使用Date）
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 时间范围字符串（格式：19:30-次日00:00）
     */
    private String buildTimeRange(Date startTime, Date endTime) {
        String startTimeStr = TIME_FORMAT.format(startTime);

        // 判断是否跨天
        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);

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

        return startTimeStr + "-" + endTimeStr;
    }

    /**
     * 构建时间范围（使用LocalTime）
     * <p>
     * 用于每天定时和每周定时演出，判断是否跨天（结束时间小于或等于开始时间表示跨天）
     * </p>
     *
     * @param startTime 开始时间（LocalTime）
     * @param endTime   结束时间（LocalTime）
     * @return 时间范围字符串（格式：19:30-次日00:00）
     */
    private String buildLocalTimeRange(LocalTime startTime, LocalTime endTime) {
        String startTimeStr = startTime.format(LOCAL_TIME_FORMAT);

        // 判断是否跨天：结束时间小于或等于开始时间表示跨天
        boolean isNextDay = !endTime.isAfter(startTime);

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

        return startTimeStr + "-" + endTimeStr;
    }

    /**
     * 查询按日期分组的演出列表（用户端）
     * <p>
     * 根据店铺ID查询演出列表，按日期分组返回
     * 只返回审核通过、已上线、未删除的演出
     * 返回未来30天内有演出的日期及其对应的演出列表
     * </p>
     *
     * @param storeId 店铺ID，必须大于0
     * @return 按日期分组的演出列表
     */
    @Override
    public PerformanceGroupListVo queryPerformanceListGroupByDate(Integer storeId) {
        log.info("查询按日期分组的演出列表，参数：storeId={}", storeId);

        // 参数校验
        if (storeId == null || storeId <= 0) {
            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
        }

        try {
            // 查询所有演出
            List<BarPerformance> performances = queryAllPerformances(storeId);

            if (performances == null || performances.isEmpty()) {
                PerformanceGroupListVo result = new PerformanceGroupListVo();
                result.setGroupList(new ArrayList<>());
                result.setTotal(0L);
                return result;
            }

            // 转换为VO列表（过滤下线演出人员）
            List<PerformanceListVo> voList = convertToVoListForGroupByDate(performances);

            // 生成演出日期映射（日期 -> 演出列表）
            Map<String, List<PerformanceListVo>> datePerformanceMap = generateDatePerformanceMap(performances, voList);

            // 构建按日期分组的列表
            List<PerformanceGroupByDateVo> groupList = buildGroupList(datePerformanceMap);

            // 构建返回结果
            PerformanceGroupListVo result = new PerformanceGroupListVo();
            result.setGroupList(groupList);
            result.setTotal((long) voList.size());

            log.info("查询按日期分组的演出列表成功，店铺ID={}，共{}个日期组，{}条演出记录",
                    storeId, groupList.size(), voList.size());
            return result;
        } catch (Exception e) {
            log.error("查询按日期分组的演出列表异常，storeId={}，异常信息：{}", storeId, e.getMessage(), e);
            throw new RuntimeException("查询按日期分组的演出列表失败：" + e.getMessage(), e);
        }
    }

    /**
     * 查询所有演出
     *
     * @param storeId 店铺ID
     * @return 演出列表
     */
    private List<BarPerformance> queryAllPerformances(Integer storeId) {
        LambdaQueryWrapper<BarPerformance> queryWrapper = buildQueryWrapper(storeId);
        // 不限制数量，查询所有符合条件的演出
        return barPerformanceMapper.selectList(queryWrapper);
    }

    /**
     * 生成演出日期映射
     * <p>
     * 根据演出类型生成未来30天内的演出日期，并建立日期与演出的映射关系
     * </p>
     *
     * @param performances 演出列表
     * @param voList       VO列表
     * @return 日期与演出列表的映射
     */
    private Map<String, List<PerformanceListVo>> generateDatePerformanceMap(
            List<BarPerformance> performances, List<PerformanceListVo> voList) {
        Map<String, List<PerformanceListVo>> datePerformanceMap = new LinkedHashMap<>();

        // 获取今天和未来30天的日期范围
        Date today = new Date();
        java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.setTime(today);
        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, 365);
        Date futureEnd = cal.getTime();

        // 遍历演出，生成日期映射
        for (int i = 0; i < performances.size(); i++) {
            BarPerformance performance = performances.get(i);
            PerformanceListVo vo = voList.get(i);
            String frequency = performance.getPerformanceFrequency();

            if (StringUtils.isEmpty(frequency)) {
                continue;
            }

            Set<String> performanceDates = new HashSet<>();

            switch (frequency) {
                case CommonConstant.PERFORMANCE_FREQUENCY_SINGLE:
                    // 单次演出：使用singleStartDatetime
                    Date singleStart = performance.getSingleStartDatetime();
                    if (singleStart != null && !singleStart.before(todayStart) && !singleStart.after(futureEnd)) {
                        String dateStr = DATE_STRING_FORMAT.format(singleStart);
                        performanceDates.add(dateStr);
                    }
                    break;
                case CommonConstant.PERFORMANCE_FREQUENCY_DAILY:
                    // 每天定时：从dailyStartDate到dailyEndDate，每天生成一条记录
                    Date dailyStart = performance.getDailyStartDate();
                    Date dailyEnd = performance.getDailyEndDate();
                    if (dailyStart != null && dailyEnd != null) {
                        Date queryStart = dailyStart.before(todayStart) ? todayStart : dailyStart;
                        Date queryEnd = dailyEnd.after(futureEnd) ? futureEnd : dailyEnd;
                        if (!queryStart.after(queryEnd)) {
                            java.util.Calendar dateCal = java.util.Calendar.getInstance();
                            dateCal.setTime(queryStart);
                            while (!dateCal.getTime().after(queryEnd)) {
                                String dateStr = DATE_STRING_FORMAT.format(dateCal.getTime());
                                performanceDates.add(dateStr);
                                dateCal.add(java.util.Calendar.DAY_OF_MONTH, 1);
                            }
                        }
                    }
                    break;
                case CommonConstant.PERFORMANCE_FREQUENCY_WEEKLY:
                    // 每周定时：从dailyStartDate到dailyEndDate，只生成符合performanceWeek的日期
                    Date weeklyStart = performance.getDailyStartDate();
                    Date weeklyEnd = performance.getDailyEndDate();
                    String performanceWeek = performance.getPerformanceWeek();
                    if (weeklyStart != null && weeklyEnd != null && StringUtils.isNotEmpty(performanceWeek)) {
                        Date queryStart = weeklyStart.before(todayStart) ? todayStart : weeklyStart;
                        Date queryEnd = weeklyEnd.after(futureEnd) ? futureEnd : weeklyEnd;
                        if (!queryStart.after(queryEnd)) {
                            // 解析星期几列表
                            Set<String> weekDaySet = new HashSet<>();
                            String[] weekDays = performanceWeek.split(",");
                            for (String weekDay : weekDays) {
                                if (StringUtils.isNotEmpty(weekDay.trim())) {
                                    weekDaySet.add(weekDay.trim());
                                }
                            }

                            java.util.Calendar dateCal = java.util.Calendar.getInstance();
                            dateCal.setTime(queryStart);
                            while (!dateCal.getTime().after(queryEnd)) {
                                // 获取当前日期是星期几（0-周一，1-周二，...，6-周日）
                                int dayOfWeek = dateCal.get(java.util.Calendar.DAY_OF_WEEK);
                                int todayWeekDay = (dayOfWeek == 1) ? 6 : (dayOfWeek - 2);
                                String todayWeekDayStr = String.valueOf(todayWeekDay);

                                if (weekDaySet.contains(todayWeekDayStr)) {
                                    String dateStr = DATE_STRING_FORMAT.format(dateCal.getTime());
                                    performanceDates.add(dateStr);
                                }
                                dateCal.add(java.util.Calendar.DAY_OF_MONTH, 1);
                            }
                        }
                    }
                    break;
                default:
                    break;
            }

            // 将演出添加到对应日期的列表中
            for (String dateStr : performanceDates) {
                datePerformanceMap.computeIfAbsent(dateStr, k -> new ArrayList<>()).add(vo);
            }
        }

        return datePerformanceMap;
    }

    /**
     * 构建按日期分组的列表
     *
     * @param datePerformanceMap 日期与演出列表的映射
     * @return 按日期分组的列表
     */
    private List<PerformanceGroupByDateVo> buildGroupList(Map<String, List<PerformanceListVo>> datePerformanceMap) {
        List<PerformanceGroupByDateVo> groupList = new ArrayList<>();

        // 获取今天的日期字符串
        String todayStr = DATE_STRING_FORMAT.format(new Date());

        // 按日期排序
        List<String> sortedDates = datePerformanceMap.keySet().stream()
                .sorted()
                .collect(Collectors.toList());

        // 构建分组列表
        for (String dateStr : sortedDates) {
            PerformanceGroupByDateVo group = new PerformanceGroupByDateVo();
            group.setDate(dateStr);

            // 判断是否为今天
            boolean isToday = todayStr.equals(dateStr);
            group.setIsToday(isToday);

            // 构建日期标题
            try {
                Date date = DATE_STRING_FORMAT.parse(dateStr);
                String dateTitle = DATE_TITLE_FORMAT.format(date);

                if (isToday) {
                    group.setDateTitle(dateTitle + " 今天");
                } else {
                    // 获取星期几
                    java.util.Calendar cal = java.util.Calendar.getInstance();
                    cal.setTime(date);
                    int dayOfWeek = cal.get(java.util.Calendar.DAY_OF_WEEK);
                    String weekDay = WEEK_DAYS[dayOfWeek - 1];
                    group.setDateTitle(dateTitle + " " + weekDay);
                }
            } catch (Exception e) {
                log.warn("解析日期失败，dateStr={}，异常信息：{}", dateStr, e.getMessage());
                group.setDateTitle(dateStr);
            }

            group.setPerformanceList(datePerformanceMap.get(dateStr));
            groupList.add(group);
        }

        return groupList;
    }

    /**
     * 查询演出详情（用户端）
     * <p>
     * 根据演出ID查询演出详细信息
     * 包含演出基本信息、演出时间、演出风格、演出详情描述和演出嘉宾列表
     * </p>
     *
     * @param id 演出ID，必须大于0
     * @return 演出详情，如果演出不存在则返回null
     */
    @Override
    public PerformanceDetailVo queryPerformanceDetail(Integer id) {
        log.info("查询演出详情，参数：id={}", id);

        // 参数校验
        if (id == null || id <= 0) {
            log.warn("查询演出详情失败，演出ID无效：id={}", id);
            throw new IllegalArgumentException("演出ID不能为空且必须大于0");
        }

        try {
            // 查询演出基本信息
            BarPerformance performance = barPerformanceMapper.selectById(id);
            String todayPerformanceTime = buildTodayPerformanceTime(performance);
            if (performance == null) {
                log.warn("查询演出详情失败，演出不存在：id={}", id);
                return null;
            }

            // 校验演出状态：只返回审核通过、已上线、未删除的演出
            if (!CommonConstant.DELETE_FLAG_UNDELETE.equals(performance.getDeleteFlag()) ||
                    !CommonConstant.PERFORMANCE_REVIEW_STATUS_APPROVED.equals(performance.getReviewStatus()) ||
                    !CommonConstant.PERFORMANCE_ONLINE_STATUS_ONLINE.equals(performance.getOnlineStatus())) {
                log.warn("查询演出详情失败，演出状态不符合要求：id={}，deleteFlag={}，reviewStatus={}，onlineStatus={}",
                        id, performance.getDeleteFlag(), performance.getReviewStatus(), performance.getOnlineStatus());
                return null;
            }

            // 构建演出详情VO
            PerformanceDetailVo vo = new PerformanceDetailVo();
            vo.setId(performance.getId());
            vo.setPerformanceName(performance.getPerformanceName());
            vo.setPerformancePoster(performance.getPerformancePoster());
            vo.setPerformanceType(performance.getPerformanceType());
            vo.setPerformanceContent(performance.getPerformanceContent());
            vo.setTodayPerformanceTime(todayPerformanceTime);
            // 构建演出时间
            vo.setPerformanceTime(buildPerformanceTime(performance));

            // 构建演出风格
            vo.setPerformanceStyle(performance.getPerformanceStyle());

            // 查询演出嘉宾列表
            List<PerformanceGuestVo> guestList = queryGuestList(performance.getStaffConfigIds());
            vo.setGuestList(guestList);

            // 设置演出人员数量
            vo.setGuestCount(guestList != null ? guestList.size() : 0);

            // 设置演出图片
            vo.setPerformanceDetail(performance.getPerformanceDetail());

            log.info("查询演出详情成功，id={}，嘉宾数量：{}", id,
                    vo.getGuestCount());
            return vo;
        } catch (Exception e) {
            log.error("查询演出详情异常，id={}，异常信息：{}", id, e.getMessage(), e);
            throw new RuntimeException("查询演出详情失败：" + e.getMessage(), e);
        }
    }

    /**
     * 构建演出时间字符串
     * <p>
     * 格式：2025.11.11-2027.01.31每周一、四19:30-次日00:00
     * </p>
     *
     * @param performance 演出信息
     * @return 演出时间字符串
     */
    private String buildPerformanceTime(BarPerformance performance) {
        String frequency = performance.getPerformanceFrequency();
        if (StringUtils.isEmpty(frequency)) {
            return "";
        }

        try {
            StringBuilder timeStr = new StringBuilder();

            // 构建日期范围
            String dateRange = buildDateRange(performance);
            if (StringUtils.isNotEmpty(dateRange)) {
                timeStr.append(dateRange);
            }

            // 构建时间安排
            String scheduleInfo = buildScheduleInfo(performance);
            if (StringUtils.isNotEmpty(scheduleInfo)) {
                if (timeStr.length() > 0) {
                    timeStr.append(" ");
                }
                timeStr.append(scheduleInfo);
            }

            return timeStr.toString();
        } catch (Exception e) {
            log.error("构建演出时间字符串异常，performanceId={}，异常信息：{}", performance.getId(), e.getMessage(), e);
            return "";
        }
    }

    /**
     * 构建演出风格字符串
     * <p>
     * 根据performance_style字段（dict_id逗号分隔）查询字典表，转换为名称
     * 格式：流行、民谣
     * </p>
     *
     * @param performanceStyle 演出风格dict_id字符串（逗号分隔）
     * @return 演出风格名称字符串（逗号分隔）
     */
    private String buildPerformanceStyle(String performanceStyle) {
        if (StringUtils.isEmpty(performanceStyle)) {
            return "";
        }

        try {
            String[] styleIds = performanceStyle.split(",");
            List<String> styleNames = new ArrayList<>();

            for (String styleId : styleIds) {
                if (StringUtils.isNotEmpty(styleId.trim())) {
                    try {
                        // 查询字典表，typeName为proficient_tag
                        LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
                        queryWrapper.eq(StoreDictionary::getTypeName, "proficient_tag")
                                .eq(StoreDictionary::getDictId, styleId.trim())
                                .eq(StoreDictionary::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE)
                                .last("limit 1");
                        StoreDictionary dictionary = storeDictionaryMapper.selectOne(queryWrapper);
                        if (dictionary != null && StringUtils.isNotEmpty(dictionary.getDictDetail())) {
                            styleNames.add(dictionary.getDictDetail());
                        }
                    } catch (Exception e) {
                        log.warn("查询演出风格字典失败，styleId={}，异常信息：{}", styleId, e.getMessage());
                    }
                }
            }

            return String.join("、", styleNames);
        } catch (Exception e) {
            log.error("构建演出风格字符串异常，performanceStyle={}，异常信息：{}", performanceStyle, e.getMessage(), e);
            return "";
        }
    }

    /**
     * 查询演出嘉宾列表
     *
     * @param staffConfigIds 员工配置ID字符串（逗号分隔）
     * @return 演出嘉宾列表
     */
    private List<PerformanceGuestVo> queryGuestList(String staffConfigIds) {
        List<PerformanceGuestVo> guestList = new ArrayList<>();

        if (StringUtils.isEmpty(staffConfigIds)) {
            return guestList;
        }

        try {
            String[] ids = staffConfigIds.split(",");
            List<Integer> staffIdList = new ArrayList<>();

            // 解析所有有效的员工ID
            for (String idStr : ids) {
                if (StringUtils.isNotEmpty(idStr.trim())) {
                    try {
                        Integer staffId = Integer.parseInt(idStr.trim());
                        if (staffId > 0) {
                            staffIdList.add(staffId);
                        }
                    } catch (NumberFormatException e) {
                        log.warn("解析员工配置ID失败，无效的ID：{}", idStr);
                    }
                }
            }

            if (staffIdList.isEmpty()) {
                return guestList;
            }

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

            // 转换为VO列表
            for (StoreStaffConfig staff : staffList) {
                if (staff == null || !CommonConstant.DELETE_FLAG_UNDELETE.equals(staff.getDeleteFlag())
                        ||!"1".equals(staff.getStatus()) ||!CommonConstant.ONLINE_STATUS.equals(staff.getOnlineStatus())
                        ) {
                    continue;
                }

                PerformanceGuestVo guest = new PerformanceGuestVo();
                guest.setStaffId(staff.getId());
                guest.setName(staff.getName());
                guest.setTag(staff.getTag());
                guest.setStaffImage(staff.getStaffImage());
                guest.setStaffPosition(staff.getStaffPosition());
                guest.setProficientProjects(staff.getProficientProjects());
                guest.setLikeCount(staff.getLikeCount() != null ? staff.getLikeCount() : 0);
                guestList.add(guest);
            }

            return guestList;
        } catch (Exception e) {
            log.error("查询演出嘉宾列表异常，staffConfigIds={}，异常信息：{}", staffConfigIds, e.getMessage(), e);
            return guestList;
        }
    }
}

