package com.jeesharp.business.modules.member.application;

import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.member.api.MemberPointsBizOrderProvider;
import com.jeesharp.business.modules.member.api.dto.MemberPointsBizOrderDTO;
import com.jeesharp.business.modules.member.application.support.MemberPointsBizOrderProviderRegistry;
import com.jeesharp.business.modules.member.dto.MemberPointsGrantDTO;
import com.jeesharp.business.modules.member.dto.MemberPointsRevokeDTO;
import com.jeesharp.business.modules.member.enums.MemberPointsBizTypeEnum;
import com.jeesharp.business.modules.member.enums.MemberPointsOrderBizSceneEnum;
import com.jeesharp.business.modules.member.enums.MemberPointsSceneEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 订单支付/退款与积分发放编排：按 {@code ORDER_CONSUME} 规则试算并幂等发放或冲正。
 *
 * @author jeesharp
 * @since 2026-06-24
 */
@Slf4j
@Service
@AllArgsConstructor
@Transactional(readOnly = true)
public class MemberPointsOrderApplicationService {

    private final MemberPointsApplicationService memberPointsApplicationService;
    private final MemberPointsBizOrderProviderRegistry providerRegistry;

    @Transactional(readOnly = false)
    public void onOrderPaid(String bizScene, String bizOrderId) {
        if (!MemberPointsOrderBizSceneEnum.isEnabledInPhase1(bizScene) || StrUtil.isBlank(bizOrderId)) {
            return;
        }
        MemberPointsBizOrderProvider provider = providerRegistry.getProvider(bizScene);
        if (provider == null) {
            log.warn("未注册 MemberPointsBizOrderProvider, bizScene={}", bizScene);
            return;
        }
        MemberPointsBizOrderDTO orderDto = provider.loadBizOrder(bizOrderId.trim());
        if (!provider.isEligibleForPoints(orderDto)) {
            return;
        }
        grantOrderConsumePoints(orderDto);
    }

    @Transactional(readOnly = false)
    public void onOrderPaid(MemberPointsBizOrderDTO orderDto) {
        if (orderDto == null || !MemberPointsOrderBizSceneEnum.isEnabledInPhase1(orderDto.getBizScene())) {
            return;
        }
        MemberPointsBizOrderProvider provider = providerRegistry.getProvider(orderDto.getBizScene());
        if (provider != null && !provider.isEligibleForPoints(orderDto)) {
            return;
        }
        grantOrderConsumePoints(orderDto);
    }

    @Transactional(readOnly = false)
    public void onOrderRefunded(String bizScene, String bizOrderId) {
        if (!MemberPointsOrderBizSceneEnum.isEnabledInPhase1(bizScene) || StrUtil.isBlank(bizOrderId)) {
            return;
        }
        MemberPointsBizOrderProvider provider = providerRegistry.getProvider(bizScene);
        if (provider == null) {
            log.warn("未注册 MemberPointsBizOrderProvider, bizScene={}", bizScene);
            return;
        }
        MemberPointsBizOrderDTO orderDto = provider.loadBizOrder(bizOrderId.trim());
        if (orderDto == null || StrUtil.isBlank(orderDto.getBuyerMemberId())) {
            return;
        }
        memberPointsApplicationService.revoke(MemberPointsRevokeDTO.builder()
                .memberId(orderDto.getBuyerMemberId())
                .sceneCode(MemberPointsSceneEnum.ORDER_CONSUME.getCode())
                .bizId(orderDto.getBizOrderId())
                .revokeBizType(MemberPointsBizTypeEnum.ORDER_CANCEL.getCode())
                .bizDesc("订单退款扣回积分")
                .operateSource("SYSTEM")
                .build());
    }

    private void grantOrderConsumePoints(MemberPointsBizOrderDTO orderDto) {
        if (orderDto == null || StrUtil.isBlank(orderDto.getBuyerMemberId())
                || StrUtil.isBlank(orderDto.getBizOrderId())) {
            return;
        }
        Map<String, Object> context = new HashMap<>();
        if (orderDto.getCashPayAmount() != null) {
            context.put("payAmount", orderDto.getCashPayAmount());
        }
        String bizDesc = StrUtil.isNotBlank(orderDto.getBizOrderNo())
                ? "订单消费赠送积分：" + orderDto.getBizOrderNo()
                : "订单消费赠送积分";
        memberPointsApplicationService.grant(MemberPointsGrantDTO.builder()
                .memberId(orderDto.getBuyerMemberId())
                .sceneCode(MemberPointsSceneEnum.ORDER_CONSUME.getCode())
                .bizId(orderDto.getBizOrderId())
                .bizNo(orderDto.getBizOrderNo())
                .bizDesc(bizDesc)
                .operateSource("SYSTEM")
                .context(context)
                .build());
    }
}
