package cn.axzo.msg.center.message.service.todo.manage.broadcast;

import cn.axzo.im.center.api.feign.MessageApi;
import cn.axzo.im.center.api.vo.req.CustomMessageInfo;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.im.center.common.enums.BizTypeEnum;
import cn.axzo.msg.center.domain.entity.Todo;
import cn.axzo.msg.center.inside.notices.config.ImMessageProps;
import cn.hutool.core.thread.NamedThreadFactory;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import static java.util.stream.Collectors.toList;

/**
 * 简单处理, 内存队列
 *
 * @author yanglin
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class TodoPullBroadcaster implements DisposableBean {

    private final ImMessageProps imProps;
    private final MessageApi messageApi;
    private final ExecutorService executor = new ThreadPoolExecutor(
            10, 15,
            5, TimeUnit.MINUTES,
            new ArrayBlockingQueue<>(5000),
            new NamedThreadFactory(TodoPullBroadcaster.class.getSimpleName(), false));

    /**
     * 可以在事务中调用, 无论事务是否提交, 让终端拉多一次消息也没有影响
     */
    void fireTodoChanged(List<Todo> todos) {
        if (CollectionUtils.isEmpty(todos))
            return;
        List<String> personIds = todos.stream()
                .map(Todo::getExecutorPersonId)
                .distinct()
                .map(String::valueOf)
                .collect(toList());
        Todo sample = todos.get(0);
        List<AppTypeEnum> pollTerminals = imProps.getPollTerminals();
        try {
            Runnable sendTask = () -> {
                log.info("start - firing todo changed. personIds={}", JSON.toJSONString(personIds));
                CustomMessageInfo imRequest = new CustomMessageInfo();
                imRequest.setAppTypeList(pollTerminals);
                imRequest.setToPersonIds(personIds);
                imRequest.setOuId(sample.getOuId());
                imRequest.setBizType(BizTypeEnum.PENDING);
                messageApi.sendCustomMessage(imRequest);
                log.info("end - firing todo changed. personId={}, request={}",
                        JSON.toJSONString(personIds), imRequest);
            };
            // 异步调用, 发送IM消息不应该影响待办的创建
            executor.execute(sendTask);
        } catch (Exception e) {
            log.error("{} is busy, check whether im-center is healthy", getClass().getSimpleName(), e);
        }
    }

    @Override
    public void destroy() throws Exception {
        executor.shutdown();
        //noinspection ResultOfMethodCallIgnored
        executor.awaitTermination(5, TimeUnit.SECONDS);
    }

}