package com.patzn.lims.workflow.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.patzn.lims.core.PtConstants;
import com.patzn.lims.core.api.PtResult;
import com.patzn.lims.core.web.SuperController;
import com.patzn.lims.workflow.*;
import com.patzn.lims.workflow.service.IActReProcdefService;
import com.patzn.lims.workflow.service.IFlowProcessService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 请假工作流
 * </p>
 *
 * @author hubin
 * @since 2017-08-17
 */
@Api(tags = "工作流执行控制器")
@RestController
@RequestMapping("/v1/flow-process")
public class FlowProcessController extends SuperController {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private IFlowProcessService flowProcessService;
    @Autowired
    private IActReProcdefService actReProcdefService;


    @ApiOperation(value = "分页列表", notes = "分页查询流程部署数据列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = PtConstants.PAGE_PAGE, value = "请求数据的页码", required = true, paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = PtConstants.PAGE_ROWS, value = "每页条数", required = true, paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = PtConstants.PAGE_SIDX, value = "排序字段", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = PtConstants.PAGE_SORD, value = "排序方式", paramType = "query", dataType = "String"),
    })
    @PostMapping("/page")
    public PtResult<Page<ActReProcdef>> page(ActReProcdef actReProcdef) {
        return success(actReProcdefService.page(getPage(), actReProcdef));
    }


    @ApiOperation(value = "添加工作流任务", notes = "添加一个工作流任务")
    @PostMapping("/task")
    public PtResult<List<FlowProcess>> addFlowTask(@RequestBody List<FlowInfo> flowTaskList) {
        return success(flowProcessService.saveTask(flowTaskList, getAccount()));
    }


    @ApiOperation(value = "获取流程 fromKey", notes = "根据流程 taskID 查询 fromKey")
    @PostMapping("/fromKey")
    public PtResult<String> fromKey(String taskId) {
        return success(flowProcessService.fromKeyByTaskId(taskId));
    }


    @ApiOperation(value = "获取流程 fromKey", notes = "根据流程 taskId 查询 fromKey")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "tid", value = "任务 ID", required = true, paramType = "path", dataType = "string"),
    })
    @PostMapping("/from-key-tid-{tid}")
    public PtResult<String> fromKeyByTaskId(@PathVariable("tid") String tid) {
        return success(flowProcessService.fromKeyByTaskId(tid));
    }


    @PostMapping("/deploy")
    public PtResult<Boolean> deploy(@RequestParam("file") MultipartFile file) {
        return success(flowProcessService.deploy(currentCompanyId(), file));
    }


    @ApiOperation(value = "获取流程 fromKey", notes = "根据流程 processDefinitionId 查询 fromKey")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "eid", value = "执行流程 ID", required = true, paramType = "path", dataType = "string"),
    })
    @PostMapping("/from-key-eid-{eid}")
    public PtResult<String> fromKeyByProcessDefinitionId(@PathVariable("eid") String eid) {
        return success(flowProcessService.fromKeyByExecutionId(eid));
    }


    @ApiOperation(value = "激活指定流程", notes = "根据流程定义 key 激活指定流程")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "key", value = "流程定义 key", required = true, paramType = "path", dataType = "string"),
    })
    @PostMapping("/activate-process/{key}")
    public PtResult<Boolean> activateProcess(@PathVariable("key") String processDefinitionKey) {
        return success(flowProcessService.activateProcess(processDefinitionKey, getAccount()));
    }


    @ApiOperation(value = "挂起指定流程", notes = "根据流程定义 key 挂起指定流程")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "key", value = "流程定义 key", required = true, paramType = "path", dataType = "string"),
    })
    @PostMapping("/suspend-process/{key}")
    public PtResult<Boolean> suspendProcess(@PathVariable("key") String processDefinitionKey) {
        return success(flowProcessService.suspendProcess(processDefinitionKey, getAccount()));
    }


    @ApiOperation(value = "删除指定流程", notes = "根据流程定义 key 删除指定流程")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deploymentId", value = "部署 ID", required = true, paramType = "path", dataType = "string"),
    })
    @PostMapping("/drop-process/{deploymentId}")
    public PtResult<Boolean> deleteDeployment(@PathVariable("deploymentId") String deploymentId) {
        return success(flowProcessService.deleteDeployment(deploymentId, true));
    }


    @ApiOperation(value = "通知申请人审批结果", notes = "根据 taskId 通知申请人审批结果")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "taskId", value = "任务 ID", required = true, paramType = "path", dataType = "string"),
            @ApiImplicitParam(name = "remark", value = "备注", required = true, paramType = "query", dataType = "string"),
    })
    @PostMapping("/notify-applyer/{taskId}")
    public PtResult<FlowInfo> notifyApplyer(@PathVariable("taskId") String taskId, String remark) {
        return success(flowProcessService.notifyApplyer(taskId, remark));
    }


    @ApiOperation(value = "任务列表", notes = "根据授权用户查询任务列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "流程名称", paramType = "query", dataType = "string"),
    })
    @PostMapping("/list-task")
    public PtResult<List<Map<String, Object>>> listTask(String name) {
        return success(actReProcdefService.listTask(getAccount(), name));
    }


    @ApiOperation(value = "任务分页列表", notes = "根据授权用户查询任务分页列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = PtConstants.PAGE_PAGE, value = "请求数据的页码", required = true, paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = PtConstants.PAGE_ROWS, value = "每页条数", required = true, paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = PtConstants.PAGE_SIDX, value = "排序字段", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = PtConstants.PAGE_SORD, value = "排序方式", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "name", value = "流程名称", paramType = "query", dataType = "string"),
    })
    @PostMapping("/page-task")
    public PtResult<Page<Map<String, Object>>> pageTask(String name) {
        return success(actReProcdefService.pageTask(getPage(), getAccount(), name));
    }


    @ApiOperation(value = "我的任务总数", notes = "查询我的任务总数")
    @PostMapping("/total-task")
    public PtResult<Long> getTotalTask() {
        return success(actReProcdefService.countTask(getAccount()));
    }


    @ApiOperation(value = "任务认领", notes = "当前用户认领任务")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "任务 ID", required = true, paramType = "path", dataType = "string"),
    })
    @PostMapping("/claim-task/{id}")
    public PtResult<Boolean> claimTask(@PathVariable("id") String id) {
        return success(flowProcessService.claimTask(id, getAccount().getUserIdStr()));
    }


    @ApiOperation(value = "流程正在执行的任务认领", notes = "当前用户认领任务")
    @PostMapping("/claim-task-process")
    public PtResult<Boolean> claimTaskProcess(@RequestBody List<String> idList) {
        return success(flowProcessService.claimTaskByExecutionIds(idList, getAccount().getUserIdStr()));
    }


    @ApiOperation(value = "任务列表", notes = "根据授权用户查询任务列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "candidateGroup", value = "授权组", required = true, paramType = "path", dataType = "string"),
    })
    @GetMapping("/tasks/{candidateGroup}")
    public PtResult<List<FlowTask>> getTasks(@PathVariable("candidateGroup") String candidateGroup) {
        if (StringUtils.isNotEmpty(candidateGroup)) {
            //取得流程当前任务信息 .taskTenantId(tenantId)
            List<Task> taskList = taskService.createTaskQuery()
                    .taskTenantId(getAccount().getCompanyIdStr())
                    .taskCandidateGroup(candidateGroup).list();
            if (CollectionUtils.isNotEmpty(taskList)) {
                return success(taskList.stream().map(FlowableHelper::convertFlowTask).collect(Collectors.toList()));
            }
        }
        return success(null);
    }


    @ApiOperation(value = "获取任务参数", notes = "根据任务 ID 获取任务参数")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "taskId", value = "任务 ID", required = true, paramType = "query", dataType = "string"),
    })
    @GetMapping("/getvars")
    public PtResult<Map<String, Object>> getVariables(String taskId) {
        return success(taskService.getVariables(taskId));
    }


    @ApiOperation(value = "获取任务执行实例", notes = "根据任务 ID 获取任务执行实例")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "taskId", value = "任务 ID", required = true, paramType = "path", dataType = "string"),
    })
    @GetMapping("/process-instance/{taskId}")
    public PtResult<FlowProcess> getProcessInstance(@PathVariable("taskId") String taskId) {
        FlowProcess flowProcess = null;
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (null != task) {
            flowProcess = FlowableHelper.convertFlowProcess(runtimeService.createProcessInstanceQuery()
                    .processInstanceId(task.getProcessInstanceId()).singleResult());
        }
        return success(flowProcess);
    }


    @ApiOperation(value = "设置任务参数", notes = "设置指定任务参数操作")
    @PostMapping("/setvars")
    public PtResult<Boolean> setVariables(@RequestBody FlowVariables flowVariables) {
        taskService.setVariables(flowVariables.getTaskId(), flowVariables.getVariables());
        return success(true);
    }


    @ApiOperation(value = "执行任务完成", notes = "根据任务 ID 执行任务完成操作")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "taskId", value = "任务 ID", required = true, paramType = "path", dataType = "string"),
    })
    @PostMapping("/complete/{taskId}")
    public PtResult<FlowInfo> complete(@PathVariable("taskId") String taskId) {
        return success(flowProcessService.complete(taskId));
    }


    @ApiOperation(value = "工作流执行图", notes = "根据任务 ID 获取任务执行流程图")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "tid", value = "任务 ID", required = true, paramType = "path", dataType = "string"),
    })
    @GetMapping("/diagram/{tid}")
    public void diagram(@PathVariable("tid") String tid) {
        flowProcessService.diagramByTaskId(response, tid);
    }


    @ApiOperation(value = "工作流执行图", notes = "根据 执行 ID 获取任务执行流程图")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "eid", value = "执行 ID", required = true, paramType = "path", dataType = "string"),
    })
    @GetMapping("/diagram-process/{eid}")
    public void diagramProcess(@PathVariable("eid") String eid) {
        flowProcessService.diagramByExecutionId(response, eid);
    }


    @ApiOperation(value = "工作流 XML", notes = "根据 流程 ID 工作流 XML")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "流程 ID", required = true, paramType = "path", dataType = "string"),
    })
    @GetMapping("bpmn-xml/{id}")
    public void bpmnXml(@PathVariable("id") String id) {
        actReProcdefService.bpnm(response, true, id);
    }


    @ApiOperation(value = "工作流执行图 png", notes = "根据 流程 ID 工作流执行图")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "流程 ID", required = true, paramType = "path", dataType = "string"),
    })
    @GetMapping("bpmn-png/{id}")
    public void bpmnPng(@PathVariable("id") String id) {
        actReProcdefService.bpnm(response, false, id);
    }


    @ApiOperation(value = "执行任务完成", notes = "设置参数并执行任务完成操作")
    @PostMapping("/complete")
    public PtResult<FlowInfo> complete(@RequestBody FlowVariables flowVariables) {
        return success(flowProcessService.complete(flowVariables));
    }


    @ApiOperation(value = "添加用户组关联", notes = "添加用户机构组关联关系")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "groupId", value = "机构组", required = true, paramType = "path", dataType = "string"),
            @ApiImplicitParam(name = "userIds", value = "用户主键数组", required = true, paramType = "query", dataType = "array"),
    })
    @PostMapping("/member-ship/{groupId}")
    public PtResult<Boolean> saveFlowMemberShip(@PathVariable("groupId") String groupId, String[] userIds) {
        return success(flowProcessService.saveFlowMemberShip(groupId, userIds));
    }


    @ApiOperation(value = "移除用户组关联", notes = "移除用户机构组关联关系")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "groupId", value = "机构组", required = true, paramType = "path", dataType = "string"),
            @ApiImplicitParam(name = "userIds", value = "用户主键数组", required = true, paramType = "query", dataType = "array"),
    })
    @DeleteMapping("/member-ship/{groupId}")
    public PtResult<Boolean> removeFlowMemberShip(@PathVariable("groupId") String groupId, String[] userIds) {
        return success(flowProcessService.removeFlowMemberShip(groupId, userIds));
    }
}
