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

import cn.novalon.gym.manage.member.entity.MemberCardRecord;
import org.springframework.data.domain.Pageable;
import org.springframework.data.r2dbc.repository.Modifying;
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-05-27
 */
@Repository
public interface MemberCardRecordRepository extends R2dbcRepository<MemberCardRecord, Long> {

    /**
     * 插入新的激活卡记录
     */
    @Modifying
    @Query("INSERT INTO member_card_record (member_id, member_card_id, status, expire_time, remaining_times, remaining_amount, source_order_id, purchase_time, created_at, updated_at) " +
            "VALUES (:memberId, :memberCardId, 'ACTIVE', :expireTime, :remainingTimes, :remainingAmount, :sourceOrderId, NOW(), NOW(), NOW()) " +
            "RETURNING *")
    Mono<MemberCardRecord> insertActiveRecord(Long memberId, Long memberCardId,
                                              LocalDateTime expireTime, Integer remainingTimes,
                                              Double remainingAmount, Long sourceOrderId);

    /**
     * 扣减使用次数/金额
     */
    @Modifying
    @Query("UPDATE member_card_record SET " +
            "remaining_times = remaining_times - :deductTimes, " +
            "remaining_amount = remaining_amount - :deductAmount, " +
            "updated_at = NOW() " +
            "WHERE member_card_record_id = :recordId " +
            "AND deleted_at IS NULL " +
            "AND remaining_times >= :deductTimes " +
            "AND remaining_amount >= :deductAmount")
    Mono<Integer> deductUsage(Long recordId, Integer deductTimes, Double deductAmount);

    /**
     * 续费卡片
     */
    @Modifying
    @Query("UPDATE member_card_record SET remaining_times = remaining_times + :addTimes, " +
            "remaining_amount = remaining_amount + :addAmount, expire_time = :newExpireTime, updated_at = NOW() " +
            "WHERE member_card_record_id = :recordId AND deleted_at IS NULL")
    Mono<Integer> renewCard(Long recordId, Integer addTimes, Double addAmount, LocalDateTime newExpireTime);

    /**
     * 更新卡片状态
     */
    @Modifying
    @Query("UPDATE member_card_record SET status = :status, updated_at = NOW() " +
            "WHERE member_card_record_id = :recordId AND deleted_at IS NULL")
    Mono<Integer> updateStatus(Long recordId, String status);

    /**
     * 查询会员的有效卡片
     */
    @Query("SELECT * FROM member_card_record WHERE member_id = :memberId AND status = 'ACTIVE' AND deleted_at IS NULL ORDER BY expire_time ASC")
    Flux<MemberCardRecord> findActiveCardsByMemberId(Long memberId);

    /**
     * 查询会员的所有卡片（分页）
     */
    @Query("SELECT mcr.* FROM member_card_record mcr " +
            "INNER JOIN member_user m ON mcr.member_id = m.id " +
            "WHERE mcr.member_id = :memberId AND mcr.deleted_at IS NULL " +
            "ORDER BY mcr.purchase_time DESC LIMIT :#{#pageable.pageSize} OFFSET :#{#pageable.offset}")
    Flux<MemberCardRecord> findByMemberId(Long memberId, Pageable pageable);

    /**
     * 验证次卡是否有足够次数
     */
    @Query("SELECT * FROM member_card_record WHERE member_card_record_id = :recordId " +
            "AND status = 'ACTIVE' AND deleted_at IS NULL " +
            "AND expire_time > NOW() " +
            "AND remaining_times >= :requiredTimes")
    Mono<MemberCardRecord> validateCountCard(Long recordId, Integer requiredTimes);

    /**
     * 验证储值卡是否有足够余额
     */
    @Query("SELECT * FROM member_card_record WHERE member_card_record_id = :recordId " +
            "AND status = 'ACTIVE' AND deleted_at IS NULL " +
            "AND expire_time > NOW() " +
            "AND remaining_amount >= :requiredAmount")
    Mono<MemberCardRecord> validateStoredCard(Long recordId, Double requiredAmount);

    /**
     * 查询已过期的卡片
     */
    @Query("SELECT * FROM member_card_record WHERE status = 'ACTIVE' AND expire_time < NOW() AND deleted_at IS NULL LIMIT 500")
    Flux<MemberCardRecord> findExpiredCards();

    /**
     * 查询所有有效记录
     */
    @Query("SELECT * FROM member_card_record WHERE status = 'ACTIVE' AND deleted_at IS NULL")
    Flux<MemberCardRecord> findActiveRecords();
}
