package cn.reghao.tnb.content.app.vod.service.rcmd.task;

import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
import cn.reghao.tnb.content.app.util.redis.ds.RedisList;
import cn.reghao.tnb.content.app.util.redis.ds.RedisSet;
import cn.reghao.tnb.content.app.vod.service.ContentPermission;
import cn.reghao.tnb.content.app.vod.service.VideoPostQuery;
import cn.reghao.tnb.content.app.vod.service.rcmd.UserInterestBased;
import cn.reghao.tnb.user.api.iface.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author reghao
 * @date 2024-12-22 21:19:57
 */
@Slf4j
@Component
public class RcmdConsumer {
    @DubboReference(check = false)
    private UserService userService;

    private final int threads = 10;
    private final ExecutorService threadPool = ThreadPoolWrapper.threadPool("data-consumer", threads);
    private final Object monitor;
    private final RcmdProducer rcmdProducer;
    private final VideoPostQuery videoPostQuery;
    private final UserInterestBased userInterestBased;
    private final RedisSet redisSet;
    private final RedisList redisList;
    private final ContentPermission contentPermission;

    public RcmdConsumer(VideoPostQuery videoPostQuery, UserInterestBased userInterestBased, RedisSet redisSet,
                        RedisList redisList, ContentPermission contentPermission, RcmdProducer rcmdProducer) {
        this.videoPostQuery = videoPostQuery;
        this.userInterestBased = userInterestBased;
        this.redisSet = redisSet;
        this.redisList = redisList;
        this.contentPermission = contentPermission;
        this.monitor = rcmdProducer.getMonitor();
        this.rcmdProducer = rcmdProducer;
    }

    @PostConstruct
    public void run() {
        threadPool.submit(new ConsumerThread());
        log.info("rcmd producer-consumer 模型启动...");
    }

    class ConsumerThread implements Runnable {
        @Override
        public void run() {
            ThreadPoolExecutor tpe = (ThreadPoolExecutor) threadPool;
            while (!Thread.interrupted()) {
                try {
                    if (tpe.getActiveCount() < threads) {
                        dispatch();
                    } else {
                        //log.info("当前有 {} 个活跃线程, 休眠 10s 等待线程池空闲...", tpe.getActiveCount());
                        Thread.sleep(10_000);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void dispatch() throws Exception {
        synchronized (monitor) {
            Object object = rcmdProducer.get();
            if (object != null) {
                if (object instanceof RcmdData) {
                    RcmdData rcmdData = (RcmdData) object;
                    int mode = userService.getRecommendMode(rcmdData.getUserId());
                    RcmdTask rcmdTask = new RcmdTask(rcmdData, videoPostQuery, userInterestBased,
                            redisSet, redisList, contentPermission, mode);
                    Future<?> future = threadPool.submit(rcmdTask);
                } else {
                    log.error("Object 类型未知");
                }
            } else {
                log.info("调用 monitor.wait() 等待 DataProducer 中有数据可用");
                monitor.wait();
            }
        }
    }
}
