package com.yanzhu.wechat.controller;

import com.yanzhu.common.annotation.Log;
import com.yanzhu.common.constant.Constants;
import com.yanzhu.common.core.controller.BaseController;
import com.yanzhu.common.core.domain.AjaxResult;
import com.yanzhu.common.core.domain.entity.SysRole;
import com.yanzhu.common.core.domain.entity.SysUser;
import com.yanzhu.common.core.page.TableDataInfo;
import com.yanzhu.common.core.redis.RedisCache;
import com.yanzhu.common.enums.BusinessType;
import com.yanzhu.common.enums.OperatorType;
import com.yanzhu.flowable.domain.FlowTaskDto;
import com.yanzhu.flowable.domain.FlowTaskVo;
import com.yanzhu.flowable.service.IFlowBusinessKeyService;
import com.yanzhu.flowable.service.IFlowDefinitionService;
import com.yanzhu.flowable.service.IFlowInstanceService;
import com.yanzhu.flowable.service.IFlowTaskService;
import com.yanzhu.system.domain.flowable.FlowQueryVo;
import com.yanzhu.system.domain.flowable.FlowTaskEntity;
import com.yanzhu.wechat.domain.StartProcessInstanceVo;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections4.CollectionUtils;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.UserTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @version : V1.0
 * @ClassName: WxFlowableController
 * @Description: 工作流任务
 * @Auther: JiangYuQi
 * @Date: 2024/02/25 18:03
 */
@RestController
@RequestMapping("/wxApi/flowTask")
public class WxFlowableController extends BaseController {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IFlowTaskService flowTaskService;

    @Autowired
    private IFlowInstanceService flowInstanceService;

    @Autowired
    private IFlowDefinitionService flowDefinitionService;

    @Autowired
    private IFlowBusinessKeyService flowBusinessKeyService;

    /**
     * 启动流程实例
     * @param startProcessInstanceVo
     * @return
     */
    @Log(title = "发起流程", businessType = BusinessType.INSERT, operatorType = OperatorType.MOBILE)
    @PostMapping("/startProcessInstance")
    public AjaxResult startProcessInstance(@RequestBody @Valid StartProcessInstanceVo startProcessInstanceVo) {
        return flowDefinitionService.startProcessInstanceById(startProcessInstanceVo.getProcDefId(), startProcessInstanceVo.getProProjectApply());
    }

    /**
     * 我的流程实例列表
     * @param flowQueryVo
     * @return
     */
    @GetMapping(value = "/myDefinitionList")
    public AjaxResult myDefinitionList(FlowQueryVo flowQueryVo) {
        return AjaxResult.success(flowDefinitionService.list(flowQueryVo));
    }

    /**
     * 查询流程节点
     * @param deployId
     * @return
     */
    @ApiOperation(value = "查询流程节点")
    @GetMapping("/readNotes/{deployId}")
    public AjaxResult readNotes(@ApiParam(value = "流程定义id") @PathVariable(value = "deployId") String deployId) {
        String key = "YANZHU.FLOW.readNotes:" + deployId;
        Object object = redisCache.getCacheObject(key);
        if (object != null) {
            return success(object);
        }
        List<FlowElement> list = flowDefinitionService.readNodes(deployId);
        redisCache.setCacheObject(key, list, Constants.DATA_EXPIRATION, TimeUnit.MINUTES);
        return success(list);
    }

    /**
     * 查询流程节点
     * @param deployId
     * @return
     */
    @ApiOperation(value = "查询流程节点")
    @GetMapping("/readDeployNotes/{deployId}")
    public AjaxResult readDeployNotes(@ApiParam(value = "流程定义id") @PathVariable(value = "deployId") String deployId) {
        String key = "YANZHU.FLOW.readDeployNotes:" + deployId;
        Object object = redisCache.getCacheObject(key);
        if (object != null) {
            return success(object);
        }
        List<UserTask> list = flowDefinitionService.findFlowNodes(deployId);
        redisCache.setCacheObject(key, list, Constants.DATA_EXPIRATION, TimeUnit.MINUTES);
        return success(list);
    }

    /**
     * 取消申请
     * @param flowTaskVo
     * @return
     */
    @ApiOperation(value = "取消申请", response = FlowTaskDto.class)
    @Log(title = "取消申请", businessType = BusinessType.UPDATE, operatorType = OperatorType.MOBILE)
    @PostMapping(value = "/stopProcess")
    public AjaxResult stopProcess(@RequestBody FlowTaskVo flowTaskVo) {
        return flowTaskService.stopProcess(flowTaskVo);
    }

    /**
     * 撤回流程
     * @param flowTaskVo
     * @return
     */
    @ApiOperation(value = "撤回流程", response = FlowTaskDto.class)
    @Log(title = "撤回流程", businessType = BusinessType.UPDATE, operatorType = OperatorType.MOBILE)
    @PostMapping(value = "/revokeProcess")
    public AjaxResult revokeProcess(@RequestBody FlowTaskVo flowTaskVo) {
        return flowTaskService.revokeProcess(flowTaskVo);
    }

    /**
     * 审批任务
     * @param flowTaskVo
     * @return
     */
    @ApiOperation(value = "审批任务")
    @Log(title = "审批流程", businessType = BusinessType.UPDATE, operatorType = OperatorType.MOBILE)
    @PostMapping(value = "/complete")
    public AjaxResult complete(@RequestBody FlowTaskVo flowTaskVo) {
        return flowTaskService.complete(flowTaskVo);
    }

    /**
     * 驳回任务
     * @param flowTaskVo
     * @return
     */
    @ApiOperation(value = "驳回任务")
    @Log(title = "驳回流程", businessType = BusinessType.UPDATE, operatorType = OperatorType.MOBILE)
    @PostMapping(value = "/reject")
    public AjaxResult taskReject(@RequestBody FlowTaskVo flowTaskVo) {
        flowTaskService.taskReject(flowTaskVo);
        return AjaxResult.success();
    }

    /**
     * 退回任务
     * @param flowTaskVo
     * @return
     */
    @ApiOperation(value = "退回任务")
    @Log(title = "退回流程", businessType = BusinessType.UPDATE, operatorType = OperatorType.MOBILE)
    @PostMapping(value = "/return")
    public AjaxResult taskReturn(@RequestBody FlowTaskVo flowTaskVo) {
        flowTaskService.taskReturn(flowTaskVo);
        return AjaxResult.success();
    }

    /**
     * 默认驳回到申请人
     * @param flowTaskVo
     * @return
     */
    @ApiOperation(value = "驳回申请人")
    @Log(title = "驳回申请人", businessType = BusinessType.UPDATE, operatorType = OperatorType.MOBILE)
    @PostMapping(value = "/defaultReturn")
    public AjaxResult taskDefaultReturn(@RequestBody FlowTaskVo flowTaskVo) {
        flowTaskService.defaultReturn(flowTaskVo);
        return AjaxResult.success();
    }

    /**
     * 删除流程实例
     * @param instanceId 流程实例ID
     * @param deleteReason 删除原因
     * @return
     */
    @ApiOperation(value = "删除流程实例")
    @Log(title = "删除流程", businessType = BusinessType.DELETE, operatorType = OperatorType.MOBILE)
    @DeleteMapping(value = "/delete/{instanceId}")
    public AjaxResult delete(@ApiParam(value = "流程实例ID", required = true) @PathVariable String instanceId,
                             @ApiParam(value = "删除原因") @RequestParam(required = false) String deleteReason) {
        flowInstanceService.delete(instanceId,deleteReason);
        return AjaxResult.success();
    }

    /**
     * 委派任务
     * @param flowTaskVo
     * @return
     */
    @ApiOperation(value = "委派任务")
    @Log(title = "委派流程", businessType = BusinessType.UPDATE, operatorType = OperatorType.MOBILE)
    @PostMapping(value = "/delegateTask")
    public AjaxResult delegate(@RequestBody FlowTaskVo flowTaskVo) {
        flowTaskService.delegateTask(flowTaskVo);
        return AjaxResult.success();
    }

    /**
     * 转办任务
     * @param flowTaskVo
     * @return
     */
    @ApiOperation(value = "转办任务")
    @Log(title = "转办流程", businessType = BusinessType.UPDATE, operatorType = OperatorType.MOBILE)
    @PostMapping(value = "/assignTask")
    public AjaxResult assign(@RequestBody FlowTaskVo flowTaskVo) {
        flowTaskService.assignTask(flowTaskVo);
        return AjaxResult.success();
    }

    /**
     * 获取所有可回退的节点
     * @param flowTaskVo
     * @return
     */
    @ApiOperation(value = "获取所有可回退的节点")
    @PostMapping(value = "/returnList")
    public AjaxResult findReturnTaskList(@RequestBody FlowTaskVo flowTaskVo) {
        return flowTaskService.findReturnTaskList(flowTaskVo);
    }

    /**
     * 根据流程Id查询操作日志
     * @param procInsId
     * @return
     */
    @GetMapping(value = "/findCommentByProcInsId")
    public AjaxResult findCommentByProcInsId(String procInsId) {
        return success(flowBusinessKeyService.selectCommentByProcInsId(procInsId));
    }

    /**
     * 根据流程Id查询表单数据
     * @param procInsId
     * @return
     */
    @GetMapping(value = "/findFormDatasByProcInsId")
    public AjaxResult findFormDatasByProcInsId(String procInsId) {
        return success(flowBusinessKeyService.selectFormDatasByProcInsId(procInsId));
    }

    /**
     * 根据条件查询我的代办任务
     * @param flowTaskEntity
     * @return
     */
    @PostMapping(value = "/myAwaitFlowTaskList")
    public AjaxResult myAwaitFlowTaskList(@RequestBody FlowTaskEntity flowTaskEntity) {
        //超管查询所有数据
        if(!SysUser.isAdmin(super.getUserId())){
            SysUser sysUser = super.getLoginUser().getUser();
            flowTaskEntity.setAssigneeId(sysUser.getUserId());
            flowTaskEntity.setDeptAncestors(sysUser.getDept().getAncestors()+","+sysUser.getDeptId());
            flowTaskEntity.setRoleIds(sysUser.getRoles().stream().map(role -> role.getRoleId()).collect(Collectors.toList()));
        }
        return success(flowBusinessKeyService.selectMyAwaitFlowTask(flowTaskEntity));
    }

    /**
     * 根据条件查询我的代办任务数量
     * @param flowTaskEntity
     * @return
     */
    @PostMapping(value = "/myAwaitFlowTaskListCount")
    public AjaxResult myAwaitFlowTaskListCount(@RequestBody FlowTaskEntity flowTaskEntity) {
        //超管查询所有数据
        if(!SysUser.isAdmin(super.getUserId())){
            SysUser sysUser = super.getLoginUser().getUser();
            flowTaskEntity.setAssigneeId(sysUser.getUserId());
            flowTaskEntity.setDeptAncestors(sysUser.getDept().getAncestors()+","+sysUser.getDeptId());
            flowTaskEntity.setRoleIds(sysUser.getRoles().stream().map(role -> role.getRoleId()).collect(Collectors.toList()));
        }
        List<Map<String, Object>> list = flowBusinessKeyService.selectMyAwaitFlowTask(flowTaskEntity);
        Map<String,Object> data = new HashMap<>();
        if(CollectionUtils.isNotEmpty(list)){
            data.put("todo",list.size());
        }else{
            data.put("todo",0);
        }
        return success(data);
    }


    /**
     * 根据条件查询我的已办任务
     * @param flowTaskEntity
     * @return
     */
    @GetMapping(value = "/myFinishedFlowTaskList")
    public TableDataInfo myFinishedFlowTaskList(FlowTaskEntity flowTaskEntity) {
        startPage();
        SysUser sysUser = super.getLoginUser().getUser();
        flowTaskEntity.setAssigneeId(sysUser.getUserId());
        return getDataTable(flowBusinessKeyService.selectMyFinishedFlowTask(flowTaskEntity));
    }

    /**
     * 根据条件查询所有流任务
     * @param flowTaskEntity
     * @return
     */
    @GetMapping(value = "/allList")
    public TableDataInfo allList(FlowTaskEntity flowTaskEntity) {
        startPage();
        return getDataTable(flowBusinessKeyService.selectAllFlowTaskByParams(flowTaskEntity));
    }

    /**
     * 根据条件统计所有流程任务
     * @param flowTaskEntity
     * @return
     */
    @GetMapping(value = "/queryCount")
    public AjaxResult queryCount(FlowTaskEntity flowTaskEntity) {
        return success(flowBusinessKeyService.quueryCount(flowTaskEntity));
    }

}
