package edu.whut.infrastructure.adapter.port;
import edu.whut.domain.trade.adapter.port.ITradePort;
import edu.whut.domain.trade.model.entity.NotifyTaskEntity;
import edu.whut.domain.trade.model.valobj.NotifyTypeEnumVO;
import edu.whut.infrastructure.event.EventPublisher;
import edu.whut.infrastructure.gateway.GroupBuyNotifyService;
import edu.whut.infrastructure.redis.IRedisService;
import edu.whut.types.enums.NotifyTaskHTTPEnumVO;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class TradePort implements ITradePort {

    private final GroupBuyNotifyService groupBuyNotifyService;

    private final IRedisService redisService;

    private final EventPublisher publisher;

    /**
     * 执行拼团通知任务：根据通知类型notify_type（HTTP／MQ）回调目标系统，并使用分布式锁防止重复执行。
     * 有两种消息notify_mq：1：拼团成功消息 2.退单消息
     */
    @Override
    public String groupBuyNotify(NotifyTaskEntity notifyTask) throws Exception {
        // 从 Redis 获取一个可重入分布式锁，防止同一任务被多台实例并发执行
        RLock lock = redisService.getLock(notifyTask.lockKey());
        try {
            // 尝试在 3 秒内获取锁，leaseTime=0 是看门狗机制，自动续期，锁需要手动释放
            if (lock.tryLock(3, 0, TimeUnit.SECONDS)) {
                try {
                    // 如果通知类型是 HTTP 回调
                    if (NotifyTypeEnumVO.HTTP.getCode().equals(notifyTask.getNotifyType())) {
                        // notifyUrl 为空或占位，则视为无需调用，直接返回 SUCCESS
                        if (StringUtils.isBlank(notifyTask.getNotifyUrl())
                                || "暂无".equals(notifyTask.getNotifyUrl())) {
                            return NotifyTaskHTTPEnumVO.SUCCESS.getCode();
                        }
                        // 真正发起 HTTP 回调(回调小商场中的groupBuyNotify接口)，返回调用结果码
                        return groupBuyNotifyService
                                .groupBuyNotify(notifyTask.getNotifyUrl(),
                                        notifyTask.getParameterJson());
                    }

                    // 如果通知类型是消息队列（MQ）回调
                    if (NotifyTypeEnumVO.MQ.getCode().equals(notifyTask.getNotifyType())) {
                        // 发布消息到 MQ（Rabbit/Kafka 等）
                        publisher.publish(notifyTask.getNotifyMQ(),
                                notifyTask.getParameterJson());
                        return NotifyTaskHTTPEnumVO.SUCCESS.getCode();
                    }

                    // 如果既不是 HTTP 也不是 MQ，则不处理，返回 NULL
                    return NotifyTaskHTTPEnumVO.NULL.getCode();
                } finally {
                    // 手动释放锁，确保当前线程持有锁且未被其他线程解锁过
                    if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                        lock.unlock();
                    }
                }
            }
            // 获取锁失败（已被其他实例占用），返回 NULL，稍后可重试或直接忽略
            return NotifyTaskHTTPEnumVO.NULL.getCode();
        } catch (Exception e) {
            // 若锁等待被中断或执行出错，重置中断标志并返回 NULL
            Thread.currentThread().interrupt();
            return NotifyTaskHTTPEnumVO.NULL.getCode();
        }
    }

}
