package cn.novalon.gym.manage.member.service.impl;

import cn.novalon.gym.manage.member.entity.MemberCardRecord;
import cn.novalon.gym.manage.member.repository.MemberCardRecordRepository;
import cn.novalon.gym.manage.member.service.IMemberCardRecordService;
import cn.novalon.gym.manage.common.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;

/**
 * 会员卡记录服务实现
 * 
 * @author 付嘉
 * @date 2026-05-27
 */
@Slf4j
@Service
public class MemberCardRecordServiceImpl implements IMemberCardRecordService {
    private final MemberCardRecordRepository memberCardRecordRepository;
    private final RedisUtil redisUtil;

    private static final String MEMBER_CARD_RECORD_CACHE_PREFIX = "member:card:record:";
    private static final long CACHE_EXPIRE_SECONDS = 300;

    public MemberCardRecordServiceImpl(MemberCardRecordRepository memberCardRecordRepository, RedisUtil redisUtil) {
        this.memberCardRecordRepository = memberCardRecordRepository;
        this.redisUtil = redisUtil;
    }

    @Override
    public Mono<MemberCardRecord> findById(Long recordId) {
        String cacheKey = MEMBER_CARD_RECORD_CACHE_PREFIX + recordId;
        Object cached = redisUtil.get(cacheKey);
        if (cached != null && cached instanceof MemberCardRecord) {
            log.debug("从缓存获取会员卡记录, recordId: {}", recordId);
            return Mono.just((MemberCardRecord) cached);
        }

        return memberCardRecordRepository.findById(recordId)
                .doOnSuccess(record -> {
                    if (record != null) {
                        redisUtil.setWithExpire(cacheKey, record, CACHE_EXPIRE_SECONDS);
                    }
                });
    }

    @Override
    public Flux<MemberCardRecord> findByMemberId(Long memberId, Pageable pageable) {
        return memberCardRecordRepository.findByMemberId(memberId, pageable);
    }

    @Override
    public Flux<MemberCardRecord> findActiveCardsByMemberId(Long memberId) {
        return memberCardRecordRepository.findActiveCardsByMemberId(memberId);
    }

    @Override
    public Mono<MemberCardRecord> insertActiveRecord(MemberCardRecord record) {
        return memberCardRecordRepository.insertActiveRecord(
                record.getMemberId(),
                record.getMemberCardId(),
                record.getExpireTime(),
                record.getRemainingTimes(),
                record.getRemainingAmount(),
                record.getSourceOrderId()
        );
    }

    @Override
    public Mono<Integer> deductUsage(Long recordId, Integer deductTimes, Double deductAmount) {
        return memberCardRecordRepository.deductUsage(recordId, deductTimes, deductAmount)
                .doOnSuccess(updated -> {
                    if (updated > 0) {
                        clearRecordCache(recordId);
                    }
                });
    }

    @Override
    public Mono<Integer> renewCard(Long recordId, Integer addTimes, Double addAmount, LocalDateTime newExpireTime) {
        return memberCardRecordRepository.renewCard(recordId, addTimes, addAmount, newExpireTime)
                .doOnSuccess(updated -> {
                    if (updated > 0) {
                        clearRecordCache(recordId);
                    }
                });
    }

    @Override
    public Mono<Integer> updateStatus(Long recordId, String status) {
        return memberCardRecordRepository.updateStatus(recordId, status)
                .doOnSuccess(updated -> {
                    if (updated > 0) {
                        clearRecordCache(recordId);
                    }
                });
    }

    @Override
    public Mono<MemberCardRecord> validateCountCard(Long recordId, Integer requiredTimes) {
        return memberCardRecordRepository.validateCountCard(recordId, requiredTimes);
    }

    @Override
    public Mono<MemberCardRecord> validateStoredCard(Long recordId, Double requiredAmount) {
        return memberCardRecordRepository.validateStoredCard(recordId, requiredAmount);
    }

    @Override
    public Flux<MemberCardRecord> findExpiredCards() {
        return memberCardRecordRepository.findExpiredCards();
    }

    private void clearRecordCache(Long recordId) {
        String cacheKey = MEMBER_CARD_RECORD_CACHE_PREFIX + recordId;
        redisUtil.delete(cacheKey);
        log.debug("清除会员卡记录缓存, recordId: {}", recordId);
    }
}
