package com.lanyuanxiaoyao.service.yarn.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnClusters;
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnQueue;
import com.lanyuanxiaoyao.service.yarn.response.QueueListResponse;
import com.lanyuanxiaoyao.service.yarn.service.QueueService;
import org.eclipse.collections.api.list.ImmutableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

/**
 * Queue
 *
 * @author lanyuanxiaoyao
 * @date 2023-04-23
 */
@CacheConfig(cacheManager = "normal-cache")
@Service("QueueService")
public class QueueServiceImpl implements QueueService {
    private static final Logger logger = LoggerFactory.getLogger(QueueServiceImpl.class);

    private final YarnClusters yarnClusters;
    private final ObjectMapper mapper;

    public QueueServiceImpl(YarnClusters yarnClusters, Jackson2ObjectMapperBuilder builder) {
        this.yarnClusters = yarnClusters;

        this.mapper = builder.build();
    }

    @Cacheable(value = "queue-list", sync = true)
    @Retryable(Throwable.class)
    @Override
    public ImmutableList<YarnQueue> list(String cluster) throws JsonProcessingException {
        String queryUrl = URLUtil.completeUrl(yarnClusters.getWebUrl(cluster), "/ws/v1/cluster/scheduler");
        String body = HttpUtil.createGet(queryUrl).setMaxRedirectCount(10).execute().body();
        QueueListResponse response = mapper.readValue(body, QueueListResponse.class);
        return response.getScheduler().getSchedulerInfo().getQueues().getQueue()
                .flatCollect(flatChildren())
                .tap(q -> q.setCluster(cluster));
    }

    @Cacheable(value = "queue-detail", sync = true)
    @Retryable(Throwable.class)
    @Override
    public YarnQueue detail(String cluster, String name) throws Exception {
        return list(cluster)
                .select(q -> StrUtil.equals(q.getQueueName(), name))
                .getFirstOptional()
                .orElseThrow(() -> new Exception("cannot found " + name))
                .setCluster(cluster);
    }
}
