package com.yunzhupaas.flowable.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.ImmutableMap;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import com.yunzhupaas.base.ActionResult;
import com.yunzhupaas.base.controller.SuperController;
import com.yunzhupaas.base.vo.PageListVO;
import com.yunzhupaas.base.vo.PaginationVO;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.exception.WorkFlowException;
import com.yunzhupaas.flowable.entity.OperatorEntity;
import com.yunzhupaas.flowable.entity.TaskEntity;
import com.yunzhupaas.flowable.entity.TriggerTaskEntity;
import com.yunzhupaas.flowable.enums.TaskStatusEnum;
import com.yunzhupaas.flowable.model.task.*;
import com.yunzhupaas.flowable.model.template.BeforeInfoVo;
import com.yunzhupaas.flowable.model.trigger.TriggerInfoModel;
import com.yunzhupaas.flowable.service.TaskService;
import com.yunzhupaas.flowable.service.TriggerTaskService;
import com.yunzhupaas.flowable.util.OperatorUtil;
import com.yunzhupaas.flowable.util.ServiceUtil;
import com.yunzhupaas.flowable.util.TaskUtil;
import com.yunzhupaas.flowable.util.TimeUtil;
import com.yunzhupaas.permission.entity.UserEntity;
import com.yunzhupaas.permission.model.user.UserIdListVo;
import com.yunzhupaas.util.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

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

/**
 * 流程任务
 *
 * @author YUNZHUPAASYUNZHUPAAS开发组
 * @version 5.0.x
 * @since 2024/4/17 15:13
 */
@Tag(name = "流程任务", description = "TaskController")
@RestController
@RequestMapping("/api/workflow/task")
@RequiredArgsConstructor
public class TaskController extends SuperController<TaskService, TaskEntity> {
    private final TaskService taskService;
    @Autowired
    private ServiceUtil serviceUtil;
    @Autowired
    private TaskUtil taskUtil;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private OperatorUtil operatorUtil;
    @Autowired
    private TriggerTaskService triggerTaskService;

    /**
     * 详情
     *
     * @param id 任务id
     * @param fo 参数类
     */
    @Operation(summary = "详情")
    @GetMapping("/{id}")
    public ActionResult getInfo(@PathVariable("id") String id, FlowModel fo) throws WorkFlowException {
        if (ObjectUtil.equals(fo.getType(), 2)) {
            TriggerInfoModel triggerInfo = triggerTaskService.getInfo(id);
            return ActionResult.success(triggerInfo);
        }
        return ActionResult.success(taskService.getInfo(id, fo));
    }

    /**
     * 暂存或提交
     *
     * @param fo 参数类
     */
    @Operation(summary = "暂存或提交")
    @PostMapping
    public ActionResult saveOrSubmit(@RequestBody FlowModel fo) throws Exception {
        taskService.batchSaveOrSubmit(fo);
        if (ObjectUtil.equals(TaskStatusEnum.RUNNING.getCode(), fo.getStatus())) {
            operatorUtil.event(fo, 1);
        }
        TaskEntity taskEntity = fo.getTaskEntity();
        if (taskEntity.getRejectDataId() == null) {
            operatorUtil.autoAudit(fo);
            operatorUtil.handleEvent();
        }
        List<OperatorEntity> list = fo.getList();
        if (CollectionUtil.isNotEmpty(list)) {
            TimeUtil.timeModel(list, fo, redisUtil);
        }
        String msg = TaskStatusEnum.TO_BE_SUBMIT.getCode().equals(fo.getStatus()) ? MsgCode.SU002.get()
                : MsgCode.SU006.get();
        TaskEntity task = taskService.getById(taskEntity.getId());
        taskEntity = task == null ? taskEntity : task;
        AuditModel model = taskUtil.getAuditModel(taskEntity.getId(), fo, null);
        return ActionResult.success(msg, model);
    }

    /**
     * 暂存或提交，已暂存的再次暂存或提交
     *
     * @param id 任务主键
     * @param fo 参数
     */
    @Operation(summary = "暂存或提交(我发起的)")
    @PutMapping("/{id}")
    public ActionResult saveOrSubmit(@PathVariable("id") String id, @RequestBody FlowModel fo) throws Exception {
        Map<String, Object> data = fo.getFormData();
        String flowTaskID = Objects.nonNull(data.get(FlowFormConstant.FLOWTASKID))
                ? data.get(FlowFormConstant.FLOWTASKID).toString()
                : id;
        fo.setId(flowTaskID);
        TaskEntity taskEntity = taskService.getById(flowTaskID);
        if (taskEntity != null) {
            taskUtil.isSuspend(taskEntity);
            taskUtil.isCancel(taskEntity);
        }
        taskService.batchSaveOrSubmit(fo);
        if (ObjectUtil.equals(TaskStatusEnum.RUNNING.getCode(), fo.getStatus())) {
            operatorUtil.event(fo, 1);
        }
        taskEntity = fo.getTaskEntity();
        if (taskEntity.getRejectDataId() == null) {
            operatorUtil.autoAudit(fo);
            operatorUtil.handleEvent();
        }
        List<OperatorEntity> list = fo.getList();
        if (CollectionUtil.isNotEmpty(list)) {
            TimeUtil.timeModel(list, fo, redisUtil);
        }
        TaskEntity task = taskService.getById(taskEntity.getId());
        taskEntity = task == null ? taskEntity : task;
        String msg = TaskStatusEnum.TO_BE_SUBMIT.getCode().equals(fo.getStatus()) ? MsgCode.SU002.get()
                : MsgCode.SU006.get();
        AuditModel model = taskUtil.getAuditModel(taskEntity.getId(), fo, null);
        return ActionResult.success(msg, model);
    }

    /**
     * 删除
     *
     * @param id 主键
     */
    @Operation(summary = "删除")
    @DeleteMapping("/{id}")
    public ActionResult<String> delete(@PathVariable("id") String id) throws Exception {
        List<TaskEntity> list = taskService.delete(id);
        taskUtil.deleteFormData(list);
        return ActionResult.success(MsgCode.SU003.get());
    }

    /**
     * 我发起的 列表
     *
     * @param pagination 分页参数
     */
    @Operation(summary = "我发起的")
    @GetMapping
    public ActionResult<PageListVO<TaskVo>> list(TaskPagination pagination) {
        List<TaskEntity> list = taskService.getList(pagination);
        List<TaskVo> voList = new ArrayList<>();
        List<UserEntity> userList = serviceUtil
                .getUserName(list.stream().map(TaskEntity::getCreatorUserId).collect(Collectors.toList()));
        for (TaskEntity entity : list) {
            TaskVo vo = JsonUtil.getJsonToBean(entity, TaskVo.class);
            UserEntity userEntity = userList.stream().filter(t -> t.getId().equals(entity.getCreatorUserId()))
                    .findFirst().orElse(null);
            vo.setCreatorUser(userEntity != null ? userEntity.getRealName() + "/" + userEntity.getAccount() : "");
            vo.setFlowUrgent(entity.getUrgent());
            if (StringUtil.isNotBlank(entity.getDelegateUserId())) {
                vo.setDelegateUser(entity.getDelegateUserId());
            }
            voList.add(vo);
        }
        PaginationVO paginationVO = JsonUtil.getJsonToBean(pagination, PaginationVO.class);
        return ActionResult.page(voList, paginationVO);
    }

    /**
     * 发起撤回
     *
     * @param id 任务主键
     */
    @Operation(summary = "发起撤回")
    @PutMapping("/Recall/{id}")
    public ActionResult<String> recall(@PathVariable("id") String id, @RequestBody FlowModel flowModel)
            throws WorkFlowException {
        taskService.recall(id, flowModel);
        operatorUtil.event(flowModel, 3);
        return ActionResult.success(MsgCode.WF008.get());
    }

    /**
     * 催办
     *
     * @param id 任务主键
     */
    @Operation(summary = "催办")
    @PostMapping("/Press/{id}")
    public ActionResult<String> press(@PathVariable("id") String id) throws WorkFlowException {
        if (taskService.press(id)) {
            return ActionResult.success(MsgCode.WF022.get());
        }
        return ActionResult.fail(MsgCode.WF023.get());
    }

    /**
     * 撤销
     *
     * @param id 任务主键
     */
    @Operation(summary = "撤销")
    @PutMapping("/Revoke/{id}")
    public ActionResult<String> revoke(@PathVariable("id") String id, @RequestBody FlowModel flowModel)
            throws Exception {
        taskService.revoke(id, flowModel);
        return ActionResult.success(MsgCode.SU006.get());
    }

    /**
     * 获取流程所关联的用户信息
     *
     * @param id         任务主键
     * @param pagination 分页参数
     */
    @Operation(summary = "获取流程所关联的用户信息")
    @GetMapping("/TaskUserList/{id}")
    public ActionResult getTaskUserList(@PathVariable("id") String id, TaskPagination pagination) {
        TaskUserListModel model = taskService.getTaskUserList(id);
        List<String> allUserIdList = model.getAllUserIdList();
        List<UserIdListVo> userList = serviceUtil.getUserList(allUserIdList, pagination, null);
        PaginationVO paginationVO = JsonUtil.getJsonToBean(pagination, PaginationVO.class);
        return ActionResult.page(userList, paginationVO);
    }

    /**
     * 子流程详情
     *
     * @param flowModel 参数
     */
    @Operation(summary = "子流程详情")
    @GetMapping("/SubFlowInfo")
    public ActionResult subFlowInfo(FlowModel flowModel) throws WorkFlowException {
        List<BeforeInfoVo> list = taskService.subFlowInfo(flowModel);
        return ActionResult.success(list);
    }

    /**
     * 查看发起表单
     *
     * @param taskId 任务主键
     */
    @Operation(summary = "查看发起表单")
    @GetMapping("/ViewStartForm/{taskId}")
    public ActionResult getStartForm(@PathVariable("taskId") String taskId) throws WorkFlowException {
        ViewFormModel model = taskService.getStartForm(taskId);
        return ActionResult.success(model);
    }

    @GetMapping("/test")
    public Map test() {
        return ImmutableMap.of("handleId",
                "03d159a3-0f88-424c-a24f-02f63855fe4f,9624fa22-ac3a-4184-af0b-b2c720df9d60,3977de33-668c-4585-b09b-239aacfb4ebe");
    }
}
