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

import cn.novalon.gym.manage.member.entity.MemberCardRecord;
import cn.novalon.gym.manage.member.enums.CardEvent;
import cn.novalon.gym.manage.member.enums.MemberCardRecordStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

/**
 * 会员卡状态机处理器
 * 
 * @author 付嘉
 * @date 2026-05-27
 */
@Slf4j
@Component
public class MemberCardStateMachine {

    private final Map<MemberCardRecordStatus, Map<CardEvent, MemberCardRecordStatus>> stateTransitionMap;

    public MemberCardStateMachine() {
        this.stateTransitionMap = buildStateTransitionMap();
    }

    private Map<MemberCardRecordStatus, Map<CardEvent, MemberCardRecordStatus>> buildStateTransitionMap() {
        Map<MemberCardRecordStatus, Map<CardEvent, MemberCardRecordStatus>> map = new HashMap<>();

        // ACTIVE 状态可以转换的事件
        Map<CardEvent, MemberCardRecordStatus> activeTransitions = new HashMap<>();
        activeTransitions.put(CardEvent.USE, MemberCardRecordStatus.ACTIVE);
        activeTransitions.put(CardEvent.RENEW, MemberCardRecordStatus.ACTIVE);
        activeTransitions.put(CardEvent.EXPIRE, MemberCardRecordStatus.EXPIRED);
        activeTransitions.put(CardEvent.REFUND, MemberCardRecordStatus.REFUNDED);
        map.put(MemberCardRecordStatus.ACTIVE, activeTransitions);

        // USED_UP 状态可以转换的事件
        Map<CardEvent, MemberCardRecordStatus> usedUpTransitions = new HashMap<>();
        usedUpTransitions.put(CardEvent.RENEW, MemberCardRecordStatus.ACTIVE);
        usedUpTransitions.put(CardEvent.REFUND, MemberCardRecordStatus.REFUNDED);
        map.put(MemberCardRecordStatus.USED_UP, usedUpTransitions);

        // EXPIRED 状态可以转换的事件
        Map<CardEvent, MemberCardRecordStatus> expiredTransitions = new HashMap<>();
        expiredTransitions.put(CardEvent.RENEW, MemberCardRecordStatus.ACTIVE);
        map.put(MemberCardRecordStatus.EXPIRED, expiredTransitions);

        // REFUNDED 状态是终态，不允许任何转换

        return map;
    }

    public Mono<Boolean> canTransition(MemberCardRecordStatus currentState, CardEvent event) {
        return Mono.fromSupplier(() -> {
            Map<CardEvent, MemberCardRecordStatus> transitions = stateTransitionMap.get(currentState);
            if (transitions == null) {
                return false;
            }
            return transitions.containsKey(event);
        });
    }

    public Mono<MemberCardRecordStatus> transition(MemberCardRecordStatus currentState, CardEvent event) {
        return Mono.fromSupplier(() -> {
            Map<CardEvent, MemberCardRecordStatus> transitions = stateTransitionMap.get(currentState);
            if (transitions == null || !transitions.containsKey(event)) {
                log.error("Invalid state transition: currentState={}, event={}", currentState, event);
                throw new IllegalStateException(
                        String.format("不允许的状态转换: 当前状态=%s, 事件=%s", currentState, event));
            }
            MemberCardRecordStatus newState = transitions.get(event);
            log.info("State transition: {} --({})--> {}", currentState, event, newState);
            return newState;
        });
    }

    public Mono<Void> validateTransition(MemberCardRecord card, CardEvent event) {
        return canTransition(card.getStatus(), event)
                .flatMap(canTransition -> {
                    if (!canTransition) {
                        return Mono.error(new IllegalStateException(
                                String.format("会员卡记录ID=%d 不允许的状态转换: 当前状态=%s, 事件=%s",
                                        card.getMemberCardRecordId(), card.getStatus(), event)));
                    }
                    return Mono.empty();
                });
    }
}
