package com.lanyuanxiaoyao.service.web.controller;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.lanyuanxiaoyao.service.common.entity.FlinkJob;
import com.lanyuanxiaoyao.service.common.entity.TableMeta;
import com.lanyuanxiaoyao.service.configuration.ExecutorProvider;
import com.lanyuanxiaoyao.service.configuration.entity.PageResponse;
import com.lanyuanxiaoyao.service.configuration.entity.info.VersionUpdated;
import com.lanyuanxiaoyao.service.forest.service.InfoService;
import com.lanyuanxiaoyao.service.web.controller.base.AmisMapResponse;
import com.lanyuanxiaoyao.service.web.controller.base.AmisResponse;
import com.lanyuanxiaoyao.service.web.controller.base.BaseController;
import com.lanyuanxiaoyao.service.web.entity.VersionUpdateVO;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.ImmutableList;
import org.eclipse.collections.api.map.MutableMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * 跨天相关
 *
 * @author lanyuanxiaoyao
 * @date 2023-06-06
 */
@RestController
@RequestMapping("version_update")
public class VersionController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(VersionController.class);

    private final InfoService infoService;

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    public VersionController(InfoService infoService) {
        this.infoService = infoService;
    }

    @GetMapping("list")
    public AmisMapResponse list(
            @RequestParam(value = "page", defaultValue = "1") Integer page,
            @RequestParam(value = "count", defaultValue = "10") Integer count,
            @RequestParam(value = "order", required = false) String order,
            @RequestParam(value = "direction", required = false) String direction,
            @RequestParam(value = "search_version", required = false) String searchVersion,
            @RequestParam(value = "search_flink_job_id", required = false) String searchFlinkJobId,
            @RequestParam(value = "search_alias", required = false) String searchAlias,
            @RequestParam(value = "filter_schedules", required = false) List<Boolean> filterSchedules
    ) {
        MutableMap<String, Object> queryMap = buildQueryMap(page, count, order, direction, searchFlinkJobId, searchAlias);
        if (StrUtil.isNotBlank(searchVersion)) {
            queryMap.put("version", searchVersion);
        }
        if (ObjectUtil.isNotEmpty(filterSchedules)) {
            queryMap.put("filter_schedules", filterSchedules);
        }
        PageResponse<VersionUpdated> pageResponse = infoService.versionTables(queryMap);
        ImmutableList<VersionUpdated> source = Lists.immutable.ofAll(pageResponse.getData());
        Long total = pageResponse.getTotal();
        ImmutableList<VersionUpdateVO> vos = source
                .asParallel(ExecutorProvider.EXECUTORS, 1)
                .collect(item -> {
                    CompletableFuture<FlinkJob> flinkJobFuture = CompletableFuture.supplyAsync(() -> infoService.flinkJobDetail(item.getFlinkJobId()), ExecutorProvider.EXECUTORS);
                    CompletableFuture<TableMeta> tableMetaFuture = CompletableFuture.supplyAsync(() -> infoService.tableMetaDetail(item.getFlinkJobId(), item.getAlias()), ExecutorProvider.EXECUTORS);
                    try {
                        CompletableFuture.allOf(flinkJobFuture, tableMetaFuture).get();
                        return new VersionUpdateVO(
                                item.getFlinkJobId(),
                                item.getAlias(),
                                item.getVersion(),
                                item.getUpdated(),
                                flinkJobFuture.get(),
                                tableMetaFuture.get()
                        );
                    } catch (InterruptedException | ExecutionException e) {
                        logger.error("Something bad", e);
                        return null;
                    }
                })
                .reject(ObjectUtil::isNull)
                .toList()
                .toImmutable();
        return AmisResponse.responseCrudData(vos, total)
                .setData("scheduled", pageResponse.getMetadata().get("scheduled"))
                .setData("unScheduled", pageResponse.getMetadata().get("unScheduled"));
    }
}
