package cn.novalon.gym.manage.checkIn.repository;

import cn.novalon.gym.manage.checkIn.entity.SignInRecord;
import org.springframework.data.r2dbc.repository.Query;
import org.springframework.data.r2dbc.repository.R2dbcRepository;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;

/**
 * 签到记录 Repository
 *
 * @author 付嘉
 * @date 2026-06-08
 */
@Repository
public interface SignInRecordRepository extends R2dbcRepository<SignInRecord, Long> {

    /**
     * 查询会员某天的签到记录
     */
    @Query("SELECT * FROM sign_in_record WHERE member_id = :memberId AND sign_in_time >= :startTime AND sign_in_time < :endTime AND is_delete = false")
    Mono<SignInRecord> findByMemberIdAndDate(Long memberId, LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 查询会员的签到记录列表
     */
    @Query("SELECT * FROM sign_in_record WHERE member_id = :memberId AND is_delete = false ORDER BY sign_in_time DESC")
    Flux<SignInRecord> findByMemberId(Long memberId);

    /**
     * 统计会员某天的签到次数
     */
    @Query("SELECT COUNT(*) FROM sign_in_record WHERE member_id = :memberId AND sign_in_time >= :startTime AND sign_in_time < :endTime AND is_delete = false")
    Mono<Long> countByMemberIdAndDate(Long memberId, LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 插入签到记录
     */
    @Query("INSERT INTO sign_in_record (member_id, member_card_id, sign_in_time, sign_in_type, sign_in_status, verification_details, fail_reason, source, created_at, updated_at, is_delete) " +
            "VALUES (:memberId, :memberCardId, :signInTime, :signInType, :signInStatus, :verificationDetails, :failReason, :source, NOW(), NOW(), false)")
    Mono<Void> insertRecord(Long memberId, Long memberCardId, LocalDateTime signInTime, 
                            String signInType, String signInStatus, String verificationDetails, 
                            String failReason, String source);

    /**
     * 根据会员ID和时间范围查询签到记录
     */
    @Query("SELECT * FROM sign_in_record WHERE member_id = :memberId AND sign_in_time >= :startTime AND sign_in_time <= :endTime AND is_delete = false ORDER BY sign_in_time DESC")
    Flux<SignInRecord> findByMemberIdAndTimeRange(Long memberId, LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 根据时间范围查询签到记录
     */
    @Query("SELECT * FROM sign_in_record WHERE sign_in_time >= :startTime AND sign_in_time <= :endTime AND is_delete = false ORDER BY sign_in_time DESC")
    Flux<SignInRecord> findByTimeRange(LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 统计会员在时间范围内的签到次数
     */
    @Query("SELECT COUNT(*) FROM sign_in_record WHERE member_id = :memberId AND sign_in_time >= :startTime AND sign_in_time <= :endTime AND is_delete = false")
    Mono<Long> countByMemberIdAndTimeRange(Long memberId, LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 统计时间范围内的签到次数
     */
    @Query("SELECT COUNT(*) FROM sign_in_record WHERE sign_in_time >= :startTime AND sign_in_time <= :endTime AND is_delete = false")
    Mono<Long> countByTimeRange(LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 统计会员在时间范围内的成功签到次数
     */
    @Query("SELECT COUNT(*) FROM sign_in_record WHERE member_id = :memberId AND sign_in_time >= :startTime AND sign_in_time <= :endTime AND sign_in_status = 'SUCCESS' AND is_delete = false")
    Mono<Long> countSuccessByMemberIdAndTimeRange(Long memberId, LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 统计时间范围内的成功签到次数
     */
    @Query("SELECT COUNT(*) FROM sign_in_record WHERE sign_in_time >= :startTime AND sign_in_time <= :endTime AND sign_in_status = 'SUCCESS' AND is_delete = false")
    Mono<Long> countSuccessByTimeRange(LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 统计时间范围内签到的独立会员数
     */
    @Query("SELECT COUNT(DISTINCT member_id) FROM sign_in_record WHERE sign_in_time >= :startTime AND sign_in_time <= :endTime AND is_delete = false")
    Mono<Long> countDistinctMembersByTimeRange(LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 获取会员在时间范围内的首次签到时间
     */
    @Query("SELECT MIN(sign_in_time) FROM sign_in_record WHERE member_id = :memberId AND sign_in_time >= :startTime AND sign_in_time <= :endTime AND is_delete = false")
    Mono<LocalDateTime> getFirstSignInTime(Long memberId, LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 获取会员在时间范围内的最后签到时间
     */
    @Query("SELECT MAX(sign_in_time) FROM sign_in_record WHERE member_id = :memberId AND sign_in_time >= :startTime AND sign_in_time <= :endTime AND is_delete = false")
    Mono<LocalDateTime> getLastSignInTime(Long memberId, LocalDateTime startTime, LocalDateTime endTime);
}