package com.ruoyi.interfaces.controller.web;

import com.aizuda.snailjob.client.job.core.enums.AllocationAlgorithmEnum;
import com.aizuda.snailjob.client.job.core.enums.TriggerTypeEnum;
import com.aizuda.snailjob.client.job.core.handler.add.BroadcastAddHandler;
import com.aizuda.snailjob.client.job.core.handler.add.ClusterAddHandler;
import com.aizuda.snailjob.client.job.core.handler.query.RequestQueryHandler;
import com.aizuda.snailjob.client.job.core.handler.update.BroadcastUpdateHandler;
import com.aizuda.snailjob.client.job.core.handler.update.ClusterUpdateHandler;
import com.aizuda.snailjob.client.job.core.openapi.SnailJobOpenApi;
import com.aizuda.snailjob.common.core.enums.JobBlockStrategyEnum;
import com.aizuda.snailjob.common.core.enums.StatusEnum;
import com.aizuda.snailjob.model.request.base.JobRequest;
import com.aizuda.snailjob.model.response.JobApiResponse;
import com.aizuda.snailjob.model.response.JobBatchApiResponse;
import com.aizuda.snailjob.model.response.WorkflowDetailApiResponse;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.interfaces.api.SnailJobApi;
import com.ruoyi.interfaces.domain.Job;
import com.ruoyi.interfaces.domain.vo.JobRequestVo;
import com.ruoyi.interfaces.service.SnailJobService;
import com.ruoyi.interfaces.service.impl.SnailJobServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Set;

@RestController
@RequestMapping("/snail/job")
public class SnailJobController extends BaseController {

    @Autowired
    private SnailJobService snailJobService;


    @GetMapping("/jobList")
    public TableDataInfo jobList(Job jobRequestVo) {
        startPage();
        List<Job> list = snailJobService.selectJobList(jobRequestVo);
        return getDataTable(list);
    }

    /**
     * 根据任务id获取job任务详情
     *
     * @return
     */
    @GetMapping("/getJobDetail")
    public AjaxResult getJobDetail(Long jobId) {
        return success(SnailJobOpenApi.getJobDetail(jobId).execute());
    }

    /**
     * @return
     */
    @GetMapping("/getJobBatchDetail")
    public AjaxResult getJobBatchDetail(Long jobId) {
        return success(SnailJobOpenApi.getJobBatchDetail(jobId).execute());
    }

    /**
     * @return
     */
    @GetMapping("/getWorkflowBatchDetail")
    public AjaxResult getWorkflowBatchDetail(Long jobId) {
        return success(SnailJobOpenApi.getWorkflowBatchDetail(jobId).execute());
    }


    /**
     * 更新定时任务状态
     *
     * @param jobId  定时任务ID
     * @param status
     */
    @GetMapping("/updateJobStatus")
    public AjaxResult updateJobStatus(Long jobId, Long status) {
        return success(SnailJobOpenApi
                .updateJobStatus(jobId)
                .setStatus(StatusEnum.YES.getStatus().equals(status.intValue()) ? StatusEnum.YES : StatusEnum.NO)
                .execute());
    }

    /**
     * 更新工作流任务状态
     *
     * @param workFlowId 工作流ID
     * @param status
     */
    @GetMapping("/updateWorkFlowStatus")
    public AjaxResult updateWorkFlowStatus(Long workFlowId, Long status) {
        return success(SnailJobOpenApi
                .updateWorkFlowStatus(workFlowId)
                .setStatus(StatusEnum.YES.getStatus().equals(status.intValue()) ? StatusEnum.YES : StatusEnum.NO)
                .execute());
    }

    /**
     * 手动调度任务
     *
     * @param jobId 任务Id
     */
    @GetMapping("/triggerJob")
    public AjaxResult triggerJob(Long jobId, Integer taskType) {
        switch (taskType) {
            case 1:
                return success(SnailJobOpenApi.triggerClusterJob(jobId).execute());
            case 2:
                return success(SnailJobOpenApi.triggerBroadcastJob(jobId).execute());
            case 3:
                return success(SnailJobOpenApi.triggerShardingJob(jobId).execute());
            case 4:
                return success(SnailJobOpenApi.triggerMapJob(jobId).execute());
            case 5:
                return success(SnailJobOpenApi.triggerMapReduceJob(jobId).execute());
            case 6:
                return success(SnailJobOpenApi.triggerWorkFlow(jobId).execute());
        }
        return success(false);
    }

    @DeleteMapping("job")
    public AjaxResult deleteJob(@RequestParam Set<Long> jobIds) {
        return success(SnailJobOpenApi.deleteJob(jobIds).execute());
    }

    /**
     * 删除工作流任务
     *
     * @param workflowIds 工作流任务ID
     */
    @DeleteMapping("workflow")
    public AjaxResult deleteWorkflow(Set<Long> workflowIds) {
        return success(SnailJobOpenApi.deleteWorkflow(workflowIds).execute());
    }

    /**
     * 新增任务
     *
     * @param jobRequest
     * @return
     */
    @PostMapping()
    public AjaxResult saveJob(@RequestBody JobRequestVo jobRequest) {
        switch (jobRequest.getTaskType()) {
            case 1:
                return success(addClusterJob(jobRequest));
            case 2:
                return success(addBroadcastJob(jobRequest));
            case 3:
                return success(addShardingJob(jobRequest));
            case 4:
                return success(addMapJob(jobRequest));
            case 5:
                return success(addMapReduceJob(jobRequest));
        }
        return success(0L);
    }


    /**
     * 更新任务
     *
     * @param jobRequest
     * @return
     */
    @PutMapping()
    public AjaxResult updateJob(@RequestBody JobRequestVo jobRequest) {
        switch (jobRequest.getTaskType()) {
            case 1:
                return success(updateClusterJob(jobRequest));
            case 2:
                return success(updateBroadcastJob(jobRequest));
            case 3:
                return success(updateShardingJob(jobRequest));
            case 4:
                return success(updateMapJob(jobRequest));
            case 5:
                return success(updateMapReduceJob(jobRequest));
        }
        return success(false);
    }

    /**
     * 新增集群模式的任务
     *
     * @param jobRequest
     * @return 任务id
     */
    public Long addClusterJob(JobRequestVo jobRequest) {
        ClusterAddHandler clusterAddHandler = SnailJobOpenApi.addClusterJob()
                //.setRouteKey(AllocationAlgorithmEnum.RANDOM)
                .setRouteKey(getAllocationAlgorithmEnum(jobRequest.getRouteKey()))
                .setJobName(jobRequest.getJobName())//
                .setExecutorInfo(jobRequest.getExecutorInfo())
                .setExecutorTimeout(jobRequest.getExecutorTimeout())
                .setDescription(jobRequest.getDescription())
                .setBlockStrategy(JobBlockStrategyEnum.valueOf(jobRequest.getBlockStrategy()))
                .setMaxRetryTimes(jobRequest.getMaxRetryTimes())
                .setTriggerType(getTriggerTypeEnum(jobRequest.getTriggerType()))
                .setTriggerInterval(jobRequest.getTriggerInterval())
                .setJobStatus(StatusEnum.of(jobRequest.getJobStatus()))  //状态不能为空
                .setRetryInterval(jobRequest.getRetryInterval());

        HashMap<String, Object> argsMap = jobRequest.getArgsStrMap();
        if (StringUtils.isNotEmpty(argsMap)) {
            argsMap.forEach(clusterAddHandler::addArgsStr);
        }
        return clusterAddHandler.execute();
    }

    /**
     * 修改集群模式的任务
     */
    public Boolean updateClusterJob(JobRequestVo jobRequest) {
        ClusterUpdateHandler clusterUpdateHandler = SnailJobOpenApi.updateClusterJob(jobRequest.getId())
                .setRouteKey(getAllocationAlgorithmEnum(jobRequest.getRouteKey()))
                .setJobName(jobRequest.getJobName())//
                .setExecutorInfo(jobRequest.getExecutorInfo())
                .setExecutorTimeout(jobRequest.getExecutorTimeout())
                .setDescription(jobRequest.getDescription())
                .setBlockStrategy(JobBlockStrategyEnum.valueOf(jobRequest.getBlockStrategy()))
                .setMaxRetryTimes(jobRequest.getMaxRetryTimes())
                .setTriggerType(getTriggerTypeEnum(jobRequest.getTriggerType()))
                .setTriggerInterval(jobRequest.getTriggerInterval())
                .setRetryInterval(jobRequest.getRetryInterval());

        HashMap<String, Object> argsMap = jobRequest.getArgsStrMap();
        if (StringUtils.isNotEmpty(argsMap)) {
            argsMap.forEach(clusterUpdateHandler::addArgsStr);
        }

        return clusterUpdateHandler.execute();

    }


    /**
     * 新增广播模式的任务
     *
     * @param jobRequest
     * @return
     */
    public Long addBroadcastJob(JobRequestVo jobRequest) {
        BroadcastAddHandler broadcastAddHandler = SnailJobOpenApi.addBroadcastJob()
                .setJobName(jobRequest.getJobName())
                .setExecutorInfo(jobRequest.getExecutorInfo())
                .setExecutorTimeout(jobRequest.getExecutorTimeout())
                .setDescription(jobRequest.getDescription())
                .setBlockStrategy(JobBlockStrategyEnum.valueOf(jobRequest.getBlockStrategy()))
                .setMaxRetryTimes(jobRequest.getMaxRetryTimes())
                .setTriggerType(getTriggerTypeEnum(jobRequest.getTriggerType()))
                .setTriggerInterval(jobRequest.getTriggerInterval())
                .setJobStatus(StatusEnum.of(jobRequest.getJobStatus()))  //状态不能为空
                .setRetryInterval(jobRequest.getRetryInterval());
        HashMap<String, Object> argsMap = jobRequest.getArgsStrMap();
        if (StringUtils.isNotEmpty(argsMap)) {
            argsMap.forEach(broadcastAddHandler::addArgsStr);
        }
        return broadcastAddHandler.execute();
    }


    /**
     * 修改广播任务
     */
    public Boolean updateBroadcastJob(JobRequestVo jobRequest) {
        BroadcastUpdateHandler broadcastUpdateHandler = SnailJobOpenApi.updateBroadcastJob(jobRequest.getId())
                .setJobName(jobRequest.getJobName())
                .setExecutorInfo(jobRequest.getExecutorInfo())
                .setExecutorTimeout(jobRequest.getExecutorTimeout())
                .setDescription(jobRequest.getDescription())
                .setBlockStrategy(JobBlockStrategyEnum.valueOf(jobRequest.getBlockStrategy()))
                .setMaxRetryTimes(jobRequest.getMaxRetryTimes())
                .setTriggerType(getTriggerTypeEnum(jobRequest.getTriggerType()))
                .setTriggerInterval(jobRequest.getTriggerInterval())
                .setRetryInterval(jobRequest.getRetryInterval());
        HashMap<String, Object> argsMap = jobRequest.getArgsStrMap();
        if (StringUtils.isNotEmpty(argsMap)) {
            argsMap.forEach(broadcastUpdateHandler::addArgsStr);
        }
        return broadcastUpdateHandler.execute();
    }

    /**
     * 新增Sharding模式的任务
     *
     * @param jobRequest 任务名称
     * @return 任务id
     */
    public Long addShardingJob(JobRequestVo jobRequest) {
        return SnailJobOpenApi.addShardingJob()
                .setJobName(jobRequest.getJobName())
                .setExecutorInfo(jobRequest.getExecutorInfo())
                .setExecutorTimeout(jobRequest.getExecutorTimeout())
                .setDescription(jobRequest.getDescription())
                .setBlockStrategy(JobBlockStrategyEnum.valueOf(jobRequest.getBlockStrategy()))
                .setMaxRetryTimes(jobRequest.getMaxRetryTimes())
                .setTriggerType(getTriggerTypeEnum(jobRequest.getTriggerType()))
                .setTriggerInterval(jobRequest.getTriggerInterval())
                .addShardingArgs(jobRequest.getShardingArgs())
                .setParallelNum(jobRequest.getParallelNum())
                .setJobStatus(StatusEnum.of(jobRequest.getJobStatus()))  //状态不能为空
                .setRetryInterval(jobRequest.getRetryInterval())
                .execute();
    }

    /**
     * 修改Sharding模式的任务
     *
     * @param jobRequest 任务名称
     * @return 任务id
     */
    public Boolean updateShardingJob(JobRequestVo jobRequest) {
        return SnailJobOpenApi.updateShardingJob(jobRequest.getId())
                .setJobName(jobRequest.getJobName())
                .setExecutorInfo(jobRequest.getExecutorInfo())
                .setExecutorTimeout(jobRequest.getExecutorTimeout())
                .setDescription(jobRequest.getDescription())
                .setBlockStrategy(JobBlockStrategyEnum.valueOf(jobRequest.getBlockStrategy()))
                .setMaxRetryTimes(jobRequest.getMaxRetryTimes())
                .setTriggerType(getTriggerTypeEnum(jobRequest.getTriggerType()))
                .setTriggerInterval(jobRequest.getTriggerInterval())
                .addShardingArgs(jobRequest.getShardingArgs())
                .setParallelNum(jobRequest.getParallelNum())
                .setRetryInterval(jobRequest.getRetryInterval())
                .execute();
    }

    /**
     * 新增Map模式的任务
     *
     * @param jobRequest 任务名称
     * @return 任务id
     */
    public Long addMapJob(JobRequestVo jobRequest) {
        return SnailJobOpenApi.addMapJob()
                .setJobName(jobRequest.getJobName())
                .setExecutorInfo(jobRequest.getExecutorInfo())
                .setExecutorTimeout(jobRequest.getExecutorTimeout())
                .setDescription(jobRequest.getDescription())
                .setBlockStrategy(JobBlockStrategyEnum.valueOf(jobRequest.getBlockStrategy()))
                .setMaxRetryTimes(jobRequest.getMaxRetryTimes())
                .setTriggerType(getTriggerTypeEnum(jobRequest.getTriggerType()))
                .setTriggerInterval(jobRequest.getTriggerInterval())
                .setParallelNum(jobRequest.getParallelNum())
                .setRetryInterval(jobRequest.getRetryInterval())
                .setJobStatus(StatusEnum.of(jobRequest.getJobStatus()))  //状态不能为空
                .execute();
    }

    /**
     * 修改Map模式的任务
     *
     * @param jobRequest
     * @return
     */
    public Boolean updateMapJob(JobRequestVo jobRequest) {
        return SnailJobOpenApi.updateMapJob(jobRequest.getId())
                .setJobName(jobRequest.getJobName())
                .setExecutorInfo(jobRequest.getExecutorInfo())
                .setExecutorTimeout(jobRequest.getExecutorTimeout())
                .setDescription(jobRequest.getDescription())
                .setBlockStrategy(JobBlockStrategyEnum.valueOf(jobRequest.getBlockStrategy()))
                .setMaxRetryTimes(jobRequest.getMaxRetryTimes())
                .setTriggerType(getTriggerTypeEnum(jobRequest.getTriggerType()))
                .setTriggerInterval(jobRequest.getTriggerInterval())
                .setParallelNum(jobRequest.getParallelNum())
                .setRetryInterval(jobRequest.getRetryInterval())
                .execute();
    }

    /**
     * 新增MapReduce模式的任务
     *
     * @param jobRequest
     * @return 任务id
     */
    public Long addMapReduceJob(JobRequestVo jobRequest) {
        return SnailJobOpenApi.addMapReduceJob()
                .setJobName(jobRequest.getJobName())
                .setExecutorInfo(jobRequest.getExecutorInfo())
                .setExecutorTimeout(jobRequest.getExecutorTimeout())
                .setDescription(jobRequest.getDescription())
                .setBlockStrategy(JobBlockStrategyEnum.valueOf(jobRequest.getBlockStrategy()))
                .setMaxRetryTimes(jobRequest.getMaxRetryTimes())
                .setTriggerType(getTriggerTypeEnum(jobRequest.getTriggerType()))
                .setTriggerInterval(jobRequest.getTriggerInterval())
                .setParallelNum(jobRequest.getParallelNum())
                .setShardNum(jobRequest.getShardNum())
                .setRetryInterval(jobRequest.getRetryInterval())
                .execute();
    }

    /**
     * 修改MapReduce模式的任务
     *
     * @param jobRequest
     * @return 任务id
     */
    public Boolean updateMapReduceJob(JobRequestVo jobRequest) {
        return SnailJobOpenApi.updateMapReduceJob(jobRequest.getId())
                .setJobName(jobRequest.getJobName())
                .setExecutorInfo(jobRequest.getExecutorInfo())
                .setExecutorTimeout(jobRequest.getExecutorTimeout())
                .setDescription(jobRequest.getDescription())
                .setBlockStrategy(JobBlockStrategyEnum.valueOf(jobRequest.getBlockStrategy()))
                .setMaxRetryTimes(jobRequest.getMaxRetryTimes())
                .setTriggerType(getTriggerTypeEnum(jobRequest.getTriggerType()))
                .setTriggerInterval(jobRequest.getTriggerInterval())
                .setParallelNum(jobRequest.getParallelNum())
                .setShardNum(jobRequest.getShardNum())
                .setRetryInterval(jobRequest.getRetryInterval())
                .execute();

    }


    public AllocationAlgorithmEnum getAllocationAlgorithmEnum(Integer type) {
        for (AllocationAlgorithmEnum algorithm : AllocationAlgorithmEnum.values()) {
            if (type.equals(algorithm.getType())) {
                return algorithm;
            }
        }
        return null;
    }

    public TriggerTypeEnum getTriggerTypeEnum(Integer type) {
        for (TriggerTypeEnum triggerTypeEnum : TriggerTypeEnum.values()) {
            if (type.equals(triggerTypeEnum.getType())) {
                return triggerTypeEnum;
            }
        }
        return null;
    }


}
