package cn.novalon.gym.manage.groupcourse.dao;

import cn.novalon.gym.manage.groupcourse.entity.GroupCourseBookingEntity;
import org.springframework.data.domain.Sort;
import org.springframework.data.r2dbc.repository.R2dbcRepository;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * 团课预约记录DAO接口
 * 
 * @author 张翔
 * @date 2026-06-01
 */
@Repository
public interface GroupCourseBookingDao extends R2dbcRepository<GroupCourseBookingEntity, Long> {

    /**
     * 根据ID查询未删除的预约记录
     */
    Mono<GroupCourseBookingEntity> findByIdIsAndDeletedAtIsNull(Long id);

    /**
     * 根据会员ID查询所有预约记录
     */
    Flux<GroupCourseBookingEntity> findByMemberIdAndDeletedAtIsNull(Long memberId);

    /**
     * 根据会员ID查询所有预约记录（带排序）
     */
    Flux<GroupCourseBookingEntity> findByMemberIdAndDeletedAtIsNull(Long memberId, Sort sort);

    /**
     * 根据团课ID查询所有预约记录
     */
    Flux<GroupCourseBookingEntity> findByCourseIdAndDeletedAtIsNull(Long courseId);

    /**
     * 根据团课ID和会员ID查询预约记录
     */
    Mono<GroupCourseBookingEntity> findByCourseIdAndMemberIdAndDeletedAtIsNull(Long courseId, Long memberId);

    /**
     * 根据团课ID和状态查询预约记录
     */
    Flux<GroupCourseBookingEntity> findByCourseIdAndStatusAndDeletedAtIsNull(Long courseId, String status);

    /**
     * 查询会员在指定课程的有效预约（状态为已预约且未取消）
     */
    Mono<GroupCourseBookingEntity> findByCourseIdAndMemberIdAndStatusAndDeletedAtIsNull(Long courseId, Long memberId, String status);

    /**
     * 根据会员卡记录ID查询预约记录
     */
    Flux<GroupCourseBookingEntity> findByMemberCardRecordIdAndDeletedAtIsNull(Long memberCardRecordId);

    /**
     * 统计团课已预约人数
     */
    Mono<Long> countByCourseIdAndStatusAndDeletedAtIsNull(Long courseId, String status);

    /**
     * 查询会员是否有时间冲突的预约（状态为已预约且未取消）
     * 时间冲突条件：新课程的开始时间 < 已预约课程的结束时间 且 新课程的结束时间 > 已预约课程的开始时间
     */
    @org.springframework.data.r2dbc.repository.Query("SELECT * FROM group_course_booking b " +
            "JOIN group_course c ON b.course_id = c.id " +
            "WHERE b.member_id = :memberId " +
            "AND b.status = '0' " +
            "AND b.deleted_at IS NULL " +
            "AND c.deleted_at IS NULL " +
            "AND :newStartTime < c.end_time " +
            "AND :newEndTime > c.start_time")
    Flux<GroupCourseBookingEntity> findConflictingBookings(Long memberId, java.time.LocalDateTime newStartTime, java.time.LocalDateTime newEndTime);

    /**
     * 更新预约状态
     */
    @org.springframework.data.r2dbc.repository.Modifying
    @org.springframework.data.r2dbc.repository.Query("UPDATE group_course_booking SET status = :status, cancel_time = :cancelTime, updated_at = :updatedAt WHERE id = :id AND deleted_at IS NULL")
    Mono<Integer> updateStatus(Long id, String status, java.time.LocalDateTime cancelTime, java.time.LocalDateTime updatedAt);

    /**
     * 软删除预约记录
     */
    @org.springframework.data.r2dbc.repository.Modifying
    @org.springframework.data.r2dbc.repository.Query("UPDATE group_course_booking SET deleted_at = :deletedAt WHERE id = :id")
    Mono<Integer> softDelete(Long id, java.time.LocalDateTime deletedAt);

    /**
     * 查询已开始课程但未到场会员的预约记录
     * 条件：课程开始时间早于当前时间，预约状态为已预约(0)
     */
    @org.springframework.data.r2dbc.repository.Query("SELECT b.* FROM group_course_booking b " +
            "JOIN group_course c ON b.course_id = c.id " +
            "WHERE b.status = '0' " +
            "AND b.deleted_at IS NULL " +
            "AND c.deleted_at IS NULL " +
            "AND c.status = '0' " +
            "AND c.start_time < CURRENT_TIMESTAMP")
    Flux<GroupCourseBookingEntity> findAbsentMembers();

    /**
     * 批量更新预约状态为缺席
     */
    @org.springframework.data.r2dbc.repository.Modifying
    @org.springframework.data.r2dbc.repository.Query("UPDATE group_course_booking SET status = '3', updated_at = :updatedAt WHERE id = :id AND deleted_at IS NULL")
    Mono<Integer> updateToAbsent(Long id, java.time.LocalDateTime updatedAt);
}