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

import cn.novalon.gym.manage.member.entity.MemberCardTransaction;
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 MemberCardTransactionRepository extends R2dbcRepository<MemberCardTransaction, Long> {

    /**
     * 插入交易流水记录
     */
    @Modifying
    @Query("INSERT INTO member_card_transactions (member_card_record_id, member_card_id, member_id, operation_type, change_amount, " +
            "change_balance, after_remaining_count, after_remaining_balance, related_biz_type, source_order_id, remark, created_at) " +
            "VALUES (:memberCardRecordId, :memberCardId, :memberId, :operationType, :changeAmount, :changeBalance, " +
            ":afterRemainingCount, :afterRemainingBalance, :relatedBizType, :sourceOrderId, :remark, NOW()) " +
            "RETURNING *")
    Mono<MemberCardTransaction> insertTransaction(Long memberCardRecordId, Long memberCardId, Long memberId,
                                                   String operationType, Integer changeAmount,
                                                   Double changeBalance, Integer afterRemainingCount,
                                                   Double afterRemainingBalance, String relatedBizType,
                                                   Long sourceOrderId, String remark);

    /**
     * 查询会员的使用记录（按时间范围）
     */
    @Query("SELECT * FROM member_card_transactions WHERE member_id = :memberId " +
            "AND created_at BETWEEN :startTime AND :endTime " +
            "ORDER BY created_at DESC LIMIT :#{#pageable.pageSize} OFFSET :#{#pageable.offset}")
    Flux<MemberCardTransaction> findByMemberIdAndTimeRange(Long memberId,
                                                           LocalDateTime startTime,
                                                           LocalDateTime endTime,
                                                           Pageable pageable);

    /**
     * 条件查询流水记录
     */
    @Query("SELECT * FROM member_card_transactions " +
            "AND (:memberId IS NULL OR member_id = :memberId) " +
            "AND (:memberCardId IS NULL OR member_card_id = :memberCardId) " +
            "AND (:operationType IS NULL OR operation_type = :operationType) " +
            "AND (:startTime IS NULL OR created_at >= :startTime) " +
            "AND (:endTime IS NULL OR created_at <= :endTime) " +
            "ORDER BY created_at DESC LIMIT :#{#pageable.pageSize} OFFSET :#{#pageable.offset}")
    Flux<MemberCardTransaction> findWithConditions(Long memberId, Long memberCardId,
                                                   String operationType,
                                                   LocalDateTime startTime,
                                                   LocalDateTime endTime,
                                                   Pageable pageable);

    /**
     * 统计符合条件的流水总数
     */
    @Query("SELECT COUNT(*) FROM member_card_transactions " +
            "AND (:memberId IS NULL OR member_id = :memberId) " +
            "AND (:memberCardId IS NULL OR member_card_id = :memberCardId) " +
            "AND (:operationType IS NULL OR operation_type = :operationType) " +
            "AND (:startTime IS NULL OR created_at >= :startTime) " +
            "AND (:endTime IS NULL OR created_at <= :endTime)")
    Mono<Long> countWithConditions(Long memberId, Long memberCardId,
                                   String operationType,
                                   LocalDateTime startTime,
                                   LocalDateTime endTime);

    /**
     * 按会员卡ID查询所有流水
     */
    @Query("SELECT * FROM member_card_transactions WHERE member_card_id = :memberCardId ORDER BY created_at DESC")
    Flux<MemberCardTransaction> findByMemberCardId(Long memberCardId);

    /**
     * 按会员ID查询所有流水
     */
    @Query("SELECT * FROM member_card_transactions WHERE member_id = :memberId ORDER BY created_at DESC")
    Flux<MemberCardTransaction> findByMemberId(Long memberId);

    /**
     * 按会员卡记录ID查询所有流水
     */
    @Query("SELECT * FROM member_card_transactions WHERE member_card_record_id = :recordId ORDER BY created_at DESC")
    Flux<MemberCardTransaction> findByRecordId(Long recordId);

    /**
     * 统计某卡种的总扣次数
     */
    @Query("SELECT COALESCE(SUM(change_amount), 0) FROM member_card_transactions " +
            "WHERE member_card_id = :memberCardId AND operation_type = 'DEDUCT' " +
            "AND created_at BETWEEN :startTime AND :endTime")
    Mono<Long> sumDeductCountByCardId(Long memberCardId,
                                      LocalDateTime startTime,
                                      LocalDateTime endTime);

    /**
     * 统计某时间段的续费总金额
     */
    @Query("SELECT COALESCE(SUM(change_balance), 0) FROM member_card_transactions " +
            "WHERE operation_type = 'RENEW' AND created_at BETWEEN :startTime AND :endTime")
    Mono<Double> sumRenewAmountByTimeRange(LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 统计某会员的购卡总金额
     */
    @Query("SELECT COALESCE(SUM(change_balance), 0) FROM member_card_transactions " +
            "WHERE member_id = :memberId AND operation_type = 'PURCHASE' " +
            "AND created_at BETWEEN :startTime AND :endTime")
    Mono<Double> sumPurchaseAmountByMemberId(Long memberId, LocalDateTime startTime, LocalDateTime endTime);
}
