package org.dromara.common.mq.utils;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.DefaultMQPullConsumer;
import org.apache.rocketmq.client.consumer.PullResult;
import org.apache.rocketmq.client.consumer.PullStatus;
import org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.remoting.protocol.heartbeat.MessageModel;
import org.dromara.common.core.constant.GlobalConstants;
import org.dromara.common.redis.redis.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static com.baomidou.mybatisplus.extension.ddl.DdlScriptErrorHandler.PrintlnLogErrorHandler.log;

/**
 * 带超时自动销毁功能的用户级RocketMQ消费者管理器
 * 支持按用户隔离消费者，并自动清理超时未活动的实例
 */
@Component
@Slf4j
public class UserRocketMQConsumerManager {
    // 全局NameServer地址
    @Value("${rocketmq.name-server}")
    private   String namesrvAddr;

    // 超时时间(毫秒)，默认30分钟
    private long timeoutMillis = 30 * 60 * 1000;

    // 定时检查间隔(毫秒)，默认5分钟
    private long checkIntervalMillis = 5 * 60 * 1000;

    // 存储用户与消费者的映射（线程安全）
    private final Map<String, UserConsumerContext> userConsumerMap = new ConcurrentHashMap<>();

    // 定时任务执行器，用于检测超时消费者
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

    private final String consumerGroup="user_consumer_group";
    private final String topic="MEMBER_VLOG_MSG";

    @Autowired
    private  RedisCache redisCache;



    /**
     * 为指定用户创建消费者实例
     * @param userId 用户唯一标识
     * @param consumerGroup 该用户的消费组
     * @param topic 消费的主题
     * @return 是否创建成功
     */
    public boolean createConsumer(String userId, String consumerGroup, String topic) throws MQClientException {
        validateUserId(userId);

        // 若用户已存在消费者，更新活动时间并返回
        if (userConsumerMap.containsKey(userId)) {
            UserConsumerContext context = userConsumerMap.get(userId);
            context.lastActiveTime = System.currentTimeMillis();
            System.out.println("用户[" + userId + "]的消费者已存在，更新活动时间");
            return false;
        }
        System.setProperty("rocketmq.namesrv.addr", namesrvAddr);
        // 创建消费者
        DefaultMQPullConsumer consumer = new DefaultMQPullConsumer(consumerGroup);
        consumer.setMessageModel(MessageModel.CLUSTERING);
        consumer.setAllocateMessageQueueStrategy(new AllocateMessageQueueAveragely());
        consumer.start();


        // 初始化该用户的偏移量存储
        redisCache.zSetAdd(GlobalConstants.GLOBAL_OFFSET+userId,userId,0);

        // 存储用户消费者上下文
        UserConsumerContext context = new UserConsumerContext(
            consumer,
            consumerGroup,
            topic,
            System.currentTimeMillis()
        );
        userConsumerMap.put(userId, context);
        System.out.println("用户[" + userId + "]的消费者创建成功，消费组: " + consumerGroup);
        return true;
    }

    /**
     * 为指定用户拉取消息（会更新活动时间）
     * @param userId 用户唯一标识
     * @param batchSize 每次拉取数量
     * @return 拉取到的消息列表
     */
    public List<MessageExt> pullUserMessages(String userId , int batchSize){
        List<MessageExt> allMessages = new ArrayList<>();

        try{
            validateUserId(userId);
            UserConsumerContext context = getUserConsumerContext(userId);

            // 更新最后活动时间
            context.lastActiveTime = System.currentTimeMillis();

            // 获取用户的消息队列
            Set<MessageQueue> mqs = context.consumer.fetchSubscribeMessageQueues(context.topic);

            int current=0;
            // 拉取所有队列的消息
            for (MessageQueue mq : mqs) {
                PullResult result = pullSingleQueueMessage(userId, context.consumer, mq , batchSize-current);
                if (result.getPullStatus() == PullStatus.FOUND) {
                    allMessages.addAll(result.getMsgFoundList());
                    // 更新用户的偏移量
                    updateUserOffset(userId, mq, result.getNextBeginOffset());
                    redisCache.zSetAdd(GlobalConstants.GLOBAL_OFFSET+userId,mq.getQueueId()+"",result.getNextBeginOffset());
                    current+=result.getMsgFoundList().size();
                    if(current==batchSize){
                        break;
                    }
                }

            }
            return allMessages;

        }catch (Exception e){
            log.error("用户[{}]拉取消息异常{}",userId,e.getMessage());
            return Collections.emptyList();
        }



    }

    /**
     * 获取指定用户的消费者上下文
     */
    private UserConsumerContext getUserConsumerContext(String userId) throws MQClientException {
        UserConsumerContext context = userConsumerMap.get(userId);
        if (context == null) {
            createConsumer(userId, consumerGroup,topic);
        }
        return userConsumerMap.get(userId);
    }

    /**
     * 拉取单个队列的消息
     */
    private PullResult pullSingleQueueMessage(String userId, DefaultMQPullConsumer consumer,
                                              MessageQueue mq,   int batchSize)
        throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
        // 获取该用户在该队列的偏移量
        Double offset = getUserQueueOffset(userId, mq);
        if(offset==null){
            offset=0.0;
        }
        return consumer.pull(mq, userId, offset.longValue(), batchSize);
    }

    /**
     * 获取用户在指定队列的消费偏移量
     */
    private Double getUserQueueOffset(String userId, MessageQueue mq) {
       return redisCache.zSetScore(GlobalConstants.GLOBAL_OFFSET+userId,mq.getQueueId()+"") ;
    }

    /**
     * 更新用户在指定队列的消费偏移量
     */
    private void updateUserOffset(String userId, MessageQueue mq, long offset) {
    }

    /**
     * 获取当前所有用户的消费者列表
     */
    public Set<String> getRegisteredUserIds() {
        return userConsumerMap.keySet();
    }

    /**
     * 校验用户ID
     */
    private void validateUserId(String userId) {
        if (userId == null || userId.trim().isEmpty()) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
    }


    /**
     * 用户消费者上下文（存储消费者实例及活动时间）
     */
    private static class UserConsumerContext {
        DefaultMQPullConsumer consumer;
        String consumerGroup;
        String topic;
        long createTime;      // 创建时间
        long lastActiveTime;  // 最后活动时间（拉取消息时间）

        public UserConsumerContext(DefaultMQPullConsumer consumer, String consumerGroup,
                                   String topic, long createTime) {
            this.consumer = consumer;
            this.consumerGroup = consumerGroup;
            this.topic = topic;
            this.createTime = createTime;
            this.lastActiveTime = createTime;  // 初始活动时间=创建时间
        }
    }

}

