package com.lanyuanxiaoyao.service.web.controller;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.lanyuanxiaoyao.service.configuration.entity.PageResponse;
import com.lanyuanxiaoyao.service.configuration.entity.hudi.HudiCleanerPlan;
import com.lanyuanxiaoyao.service.configuration.entity.hudi.HudiCompactionPlan;
import com.lanyuanxiaoyao.service.configuration.entity.hudi.HudiInstant;
import com.lanyuanxiaoyao.service.configuration.entity.hudi.HudiRollbackPlan;
import com.lanyuanxiaoyao.service.forest.service.HudiService;
import com.lanyuanxiaoyao.service.web.controller.base.AmisCrudResponse;
import com.lanyuanxiaoyao.service.web.controller.base.AmisDetailResponse;
import com.lanyuanxiaoyao.service.web.controller.base.AmisResponse;
import com.lanyuanxiaoyao.service.web.controller.base.BaseController;
import java.util.List;
import java.util.function.Function;
import org.eclipse.collections.api.factory.Maps;
import org.eclipse.collections.api.map.ImmutableMap;
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;

/**
 * Hudi 接口
 *
 * @author lanyuanxiaoyao
 * @date 2023-05-01
 */
@RestController
@RequestMapping("hudi")
public class HudiController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(HudiController.class);
    private static final ImmutableMap<String, Function<HudiInstant, String>> TIMELINE_SORT_MAP = Maps.immutable.of(
            "timestamp",
            HudiInstant::getTimestamp
    );
    private final HudiService hudiService;

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    public HudiController(HudiService hudiService) {
        this.hudiService = hudiService;
    }

    @GetMapping("/timeline/list")
    public AmisCrudResponse timeline(
            @RequestParam(value = "page", defaultValue = "1") Integer page,
            @RequestParam(value = "count", defaultValue = "10") Integer count,
            @RequestParam(value = "order", defaultValue = "timestamp") String order,
            @RequestParam(value = "direction", defaultValue = "desc") String direction,
            @RequestParam("flink_job_id") Long flinkJobId,
            @RequestParam("alias") String alias,
            @RequestParam(value = "filter_type", required = false) List<String> filterType,
            @RequestParam(value = "filter_action", required = false) List<String> filterAction,
            @RequestParam(value = "filter_state", required = false) List<String> filterState
    ) {
        MutableMap<String, Object> queryMap = buildQueryMap(page, count, order, direction, flinkJobId.toString(), alias);
        if (ObjectUtil.isNotEmpty(filterType)) {
            queryMap.put("filter_type", filterType);
        }
        if (ObjectUtil.isNotEmpty(filterAction)) {
            queryMap.put("filter_action", filterAction);
        }
        if (ObjectUtil.isNotEmpty(filterState)) {
            queryMap.put("filter_state", filterState);
        }
        PageResponse<HudiInstant> response = hudiService.timelineList(queryMap);
        return AmisResponse.responseCrudData(response.getData(), response.getTotal());
    }

    @GetMapping("/timeline/list_hdfs")
    public AmisCrudResponse timelineHdfs(
            @RequestParam(value = "page", defaultValue = "1") Integer page,
            @RequestParam(value = "count", defaultValue = "10") Integer count,
            @RequestParam(value = "order", defaultValue = "timestamp") String order,
            @RequestParam(value = "direction", defaultValue = "desc") String direction,
            @RequestParam("hdfs") String hdfs,
            @RequestParam(value = "filter_type", required = false) List<String> filterType,
            @RequestParam(value = "filter_action", required = false) List<String> filterAction,
            @RequestParam(value = "filter_state", required = false) List<String> filterState
    ) {
        MutableMap<String, Object> queryMap = Maps.mutable.empty();
        queryMap.put("page", page);
        queryMap.put("count", count);
        if (StrUtil.isNotBlank(order) && StrUtil.isNotBlank(direction)) {
            queryMap.put("order", order);
            queryMap.put("direction", direction);
        }
        if (ObjectUtil.isNotEmpty(hdfs)) {
            queryMap.put("hdfs", hdfs);
        }
        if (ObjectUtil.isNotEmpty(filterType)) {
            queryMap.put("filter_type", filterType);
        }
        if (ObjectUtil.isNotEmpty(filterAction)) {
            queryMap.put("filter_action", filterAction);
        }
        if (ObjectUtil.isNotEmpty(filterState)) {
            queryMap.put("filter_state", filterState);
        }
        PageResponse<HudiInstant> response = hudiService.timelineHdfsList(queryMap);
        return AmisResponse.responseCrudData(response.getData(), response.getTotal());
    }

    @GetMapping("read_compaction_plan")
    public AmisResponse<HudiCompactionPlan> readCompactionPlan(
            @RequestParam(value = "flink_job_id", required = false) Long flinkJobId,
            @RequestParam(value = "alias", required = false) String alias,
            @RequestParam(value = "hdfs", required = false) String hdfs,
            @RequestParam("instant") String instant
    ) throws Exception {
        if (StrUtil.isNotBlank(hdfs)) {
            return AmisResponse.responseSuccess(hudiService.readCompactionPlanHdfs(hdfs, instant));
        } else if (ObjectUtil.isNotNull(flinkJobId) && StrUtil.isNotBlank(alias)) {
            return AmisResponse.responseSuccess(hudiService.readCompactionPlan(flinkJobId, alias, instant));
        }
        throw new Exception("Flink job id and alias or hdfs cannot be blank");
    }

    @GetMapping("read_rollback_plan")
    public AmisResponse<HudiRollbackPlan> readRollbackPlan(
            @RequestParam(value = "flink_job_id", required = false) Long flinkJobId,
            @RequestParam(value = "alias", required = false) String alias,
            @RequestParam(value = "hdfs", required = false) String hdfs,
            @RequestParam("instant") String instant
    ) throws Exception {
        if (StrUtil.isNotBlank(hdfs)) {
            return AmisResponse.responseSuccess(hudiService.readRollbackPlanHdfs(hdfs, instant));
        } else if (ObjectUtil.isNotNull(flinkJobId) && StrUtil.isNotBlank(alias)) {
            return AmisResponse.responseSuccess(hudiService.readRollbackPlan(flinkJobId, alias, instant));
        }
        throw new Exception("Flink job id and alias or hdfs cannot be blank");
    }

    @GetMapping("read_cleaner_plan")
    public AmisResponse<HudiCleanerPlan> readCleanerPlan(
            @RequestParam(value = "flink_job_id", required = false) Long flinkJobId,
            @RequestParam(value = "alias", required = false) String alias,
            @RequestParam(value = "hdfs", required = false) String hdfs,
            @RequestParam("instant") String instant
    ) throws Exception {
        if (StrUtil.isNotBlank(hdfs)) {
            return AmisResponse.responseSuccess(hudiService.readCleanerPlanHdfs(hdfs, instant));
        } else if (ObjectUtil.isNotNull(flinkJobId) && StrUtil.isNotBlank(alias)) {
            return AmisResponse.responseSuccess(hudiService.readCleanerPlan(flinkJobId, alias, instant));
        }
        throw new Exception("Flink job id and alias or hdfs cannot be blank");
    }

    @GetMapping("schema")
    public AmisDetailResponse readCleanerPlan(
            @RequestParam(value = "flink_job_id", required = false) Long flinkJobId,
            @RequestParam(value = "alias", required = false) String alias,
            @RequestParam(value = "hdfs", required = false) String hdfs
    ) throws Exception {
        if (StrUtil.isNotBlank(hdfs)) {
            return AmisResponse.responseDetailData(hudiService.schema(hdfs));
        } else if (ObjectUtil.isNotNull(flinkJobId) && StrUtil.isNotBlank(alias)) {
            return AmisResponse.responseDetailData(hudiService.schema(flinkJobId, alias));
        }
        throw new Exception("Flink job id and alias or hdfs cannot be blank");
    }
}
