package cn.axzo.workflow.server.controller.web.bpmn;

import cn.axzo.workflow.client.feign.bpmn.ProcessTaskApi;
import cn.axzo.workflow.common.enums.AttachmentTypeEnum;
import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCompleteDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAttachmentDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCommentDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskPageSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskRemindDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskTransferDTO;
import cn.axzo.workflow.common.model.response.BpmPageResult;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceGroupVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskDonePageItemVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskTodoPageItemVO;
import cn.axzo.workflow.core.service.BpmnProcessTaskService;
import cn.axzo.workflow.server.common.annotation.ErrorReporter;
import cn.axzo.workflow.server.common.annotation.RepeatSubmit;
import cn.azxo.framework.common.model.CommonResponse;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.flowable.form.api.FormInfo;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Nullable;
import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;

import static cn.azxo.framework.common.model.CommonResponse.success;

/**
 * 流程任务相关控制器
 */
@Slf4j
@RequestMapping({"/web/v1/api/process/task", "/api/process/task"})
@RestController
@ErrorReporter
@Validated
public class BpmnProcessTaskController implements ProcessTaskApi {

    @Resource
    private BpmnProcessTaskService bpmnProcessTaskService;


    /**
     * 待审核列表
     */
    @Operation(summary = "待审核列表")
    @GetMapping("/page/todo")
    @Override
    public CommonResponse<BpmPageResult<BpmnTaskTodoPageItemVO>> getTodoTaskPage(@Validated @RequestBody BpmnTaskPageSearchDTO dto) {
        log.info("待审核列表 getTodoTaskPage===>>>参数：{}", dto);
        return success(bpmnProcessTaskService.getTodoTaskPage(dto));
    }

    /**
     * 已完成的审批列表
     */
    @Operation(summary = "已完成的审批列表")
    @GetMapping("/page/done")
    @Override
    public CommonResponse<BpmPageResult<BpmnTaskDonePageItemVO>> getDoneTaskPage(@Validated @RequestBody BpmnTaskPageSearchDTO dto) {
        log.info("已完成的审批列表 getDoneTaskPage===>>>参数：{}", dto);
        return success(bpmnProcessTaskService.getDoneTaskPage(dto));
    }


    /**
     * 同意
     */
    @Operation(summary = "通过任务")
    @PostMapping("/approve")
    @Override
    @RepeatSubmit
    public CommonResponse<Boolean> approveTask(@Validated @RequestBody BpmnTaskAuditDTO dto) {
        log.info("同意 approveTask===>>>参数：{}", dto);
        List<AttachmentDTO> tempAttachments = ListUtils.defaultIfNull(dto.getAttachmentList(), new ArrayList<>());
        if (StringUtils.hasText(dto.getSignatureUrl())) {
            AttachmentDTO signature = new AttachmentDTO();
            signature.setType(AttachmentTypeEnum.signature);
            signature.setName(dto.getApprover().getAssignerName() + "的签名");
            signature.setUrl(dto.getSignatureUrl());
            tempAttachments.add(signature);
            dto.setAttachmentList(tempAttachments);
        }
        bpmnProcessTaskService.approveTask(dto);
        return success(true);
    }

    /**
     * 驳回
     */
    @Operation(summary = "驳回任务")
    @PostMapping("/reject")
    @Override
    @RepeatSubmit
    public CommonResponse<Boolean> rejectTask(@Validated @RequestBody BpmnTaskAuditDTO dto) {
        log.info("驳回 rejectTask===>>>参数：{}", dto);
        bpmnProcessTaskService.rejectTask(dto);
        return success(true);
    }

    /**
     * 转交
     */
    @Operation(summary = "转交任务")
    @PostMapping("/transfer")
    @Override
    @RepeatSubmit
    public CommonResponse<Boolean> transferTask(@Validated @RequestBody BpmnTaskTransferDTO dto) {
        bpmnProcessTaskService.transferTask(dto);
        return success(true);
    }

    /**
     * 评论
     */
    @Operation(summary = "评论流程实例")
    @PostMapping("/comment")
    @Override
    @RepeatSubmit
    public CommonResponse<Boolean> commentTask(@Validated @RequestBody BpmnTaskCommentDTO commentDTO) {
        bpmnProcessTaskService.commentTask(commentDTO);
        return success(true);
    }


    /**
     * 加签
     */
    @Operation(summary = "加签任务")
    @Override
    @PostMapping("/countersign")
    @RepeatSubmit
    public CommonResponse<Boolean> countersignTask(@Validated @RequestBody BpmnTaskCountersignDTO countersignDTO) {
        bpmnProcessTaskService.countersignTask(countersignDTO);
        return success(true);
    }

    /**
     * 催办
     *
     * @param dto
     * @return
     */
    @Operation(summary = "催办任务")
    @PostMapping("/remind")
    @Override
    @RepeatSubmit
    public CommonResponse<Boolean> remindTask(@Validated @RequestBody BpmnTaskRemindDTO dto) {
        bpmnProcessTaskService.remindTask(dto);
        return success(true);
    }

    /**
     * 创建机器人节点, 暂停流程任务
     *
     * @param dto
     * @return
     */
    @Operation(summary = "创建机器人节点, 暂停流程任务")
    @PostMapping("/robot/create")
    @Override
    @RepeatSubmit
    public CommonResponse<String> createRobotTask(@Validated @RequestBody BpmnRobotTaskCreateDTO dto) {
        return success(bpmnProcessTaskService.createRobotTask(dto));
    }

    /**
     * 完成机器人节点, 继续流程任务
     *
     * @param dto
     * @return
     */
    @Operation(summary = "完成机器人节点, 继续流程任务")
    @PostMapping("/robot/complete")
    @Override
    @RepeatSubmit
    public CommonResponse<Boolean> completeRobotTask(@Validated @RequestBody BpmnRobotTaskCompleteDTO dto) {
        bpmnProcessTaskService.completeRobotTask(dto);
        return success(true);
    }

    /**
     * 获取指定流程实例的审批过程信息
     * <p>
     * 同一层级结构
     */
    @Operation(summary = "获取指定流程实例的审批过程信息(flat)")
    @GetMapping("/list/flat")
    @Override
    public CommonResponse<List<BpmnHistoricTaskInstanceVO>> getTaskListFlatByProcessInstanceId(
            @NotBlank(message = "流程实例 ID 不能为空") @RequestParam String processInstanceId,
            @Nullable @RequestParam(required = false) String tenantId) {
        log.info("获取历史已审批的列表详情 getTaskListFlatByProcessInstanceId===>>>参数：{}", processInstanceId);
        return success(bpmnProcessTaskService.getHistoricTaskListByProcessInstanceId(processInstanceId, tenantId));
    }

    /**
     * 获取指定流程实例的审批过程信息
     * <p>
     * 分组结构
     */
    @Operation(summary = "获取指定流程实例的审批过程信息(group)")
    @GetMapping("/list/group")
    @Override
    public CommonResponse<List<BpmnHistoricTaskInstanceGroupVO>> getTaskListGroupByProcessInstanceId(
            @NotBlank(message = "流程实例 ID 不能为空") @RequestParam String processInstanceId,
            @Nullable @RequestParam(required = false) String tenantId) {
        log.info("获取历史已审批的列表详情 getTaskListGroupByProcessInstanceId===>>>参数：{}", processInstanceId);
        return success(bpmnProcessTaskService.getHistoricTaskListGroupByProcessInstanceId(processInstanceId, tenantId));
    }

    /**
     * 获取实例正在审核的人列表
     */
    @Operation(summary = "获取实例正在审核的人列表")
    @GetMapping("/active/list")
    @Override
    public CommonResponse<List<BpmnTaskInstanceVO>> getActiveTasksByProcessInstanceId(
            @NotBlank(message = "流程实例 ID 不能为空") @RequestParam String processInstanceId,
            @NotBlank(message = "租户不能为空") @RequestParam String tenantId) {
        log.info(" 获取实例正在审核的人列表 getActiveTasksByProcessInstanceId===>>>参数：{}", processInstanceId);
        return success(bpmnProcessTaskService.getActiveTasksByProcessInstanceId(processInstanceId, tenantId));
    }

    /**
     * 获取任务表单信息
     *
     * @param taskId
     * @param tenantId
     * @return
     */
    @Operation(summary = "获取任务表单信息")
    @GetMapping("/form")
    public CommonResponse<FormInfo> getTaskForm(@NotBlank(message = "任务 ID 不能为空") @RequestParam String taskId,
                                                @NotBlank(message = "租户不能为空") @RequestParam String tenantId) {
        return success(bpmnProcessTaskService.getTaskFormModel(taskId, tenantId));
    }

    /**
     * 添加附件
     *
     * @param dto 附件信息
     * @return 无返回值
     */
    @Operation(summary = "添加附件")
    @PostMapping("/attachment/add")
    public CommonResponse<Void> addAttachment(@Validated @RequestBody BpmnTaskAttachmentDTO dto) {
        bpmnProcessTaskService.attachmentTask(dto, "");
        return success();
    }

    /**
     * 根据实例 ID 和自然人 ID 查询对应待处理的任务 ID
     *
     * @param processInstanceId
     * @param personId
     * @return
     */
    @Operation(summary = "根据实例 ID 和自然人 ID 查询对应待处理的任务 ID")
    @GetMapping("/find")
    @Override
    public CommonResponse<String> findTaskIdByInstanceIdAndPersonId(@RequestParam(required = false) @NotBlank(message = "流程实例 ID 不能为空") String processInstanceId,
                                                                    @RequestParam(required = false) @NotBlank(message = "自然人 ID 不能为空") String personId) {
        return success(bpmnProcessTaskService.findTaskIdByInstanceIdAndPersonId(processInstanceId, personId));
    }
}
