package com.mortals.xhx.module.task.web;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mortals.framework.common.IBaseEnum;
import com.mortals.framework.model.Context;
import com.mortals.framework.model.Result;
import com.mortals.xhx.base.system.user.model.UserQuery;
import com.mortals.xhx.base.system.user.service.UserService;
import com.mortals.xhx.common.code.FlowStateType;
import com.mortals.xhx.common.code.FlowStatusEnum;
import com.mortals.xhx.common.pdu.flow.*;
import com.mortals.xhx.feign.processinstance.ProcessCommonReq;
import com.mortals.xhx.feign.processinstance.ProcessDeleteReq;
import com.mortals.xhx.feign.processinstance.ProcessStopReq;
import com.mortals.xhx.feign.task.*;
import com.mortals.xhx.module.flowable.web.FlowableDefinitionForm;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.mortals.framework.web.BaseCRUDJsonMappingController;
import com.mortals.xhx.module.task.model.TaskProcessEntity;
import com.mortals.xhx.module.task.service.TaskProcessService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * <p>Title: 流程实例表</p>
 * <p>Description: TaskProcessController  </p>
 * <p>Copyright: Copyright &reg;  </p>
 * <p>Company: </p>
 *
 * @author zxfei
 * @version 1.0.0
 */
@RestController
@RequestMapping("task/process")
public class TaskProcessController extends BaseCRUDJsonMappingController<TaskProcessService, TaskProcessForm, TaskProcessEntity, Long> {

    @Autowired
    private UserService userService;

    public TaskProcessController() {
        super.setFormClass(TaskProcessForm.class);
        super.setModuleDesc("流程实例表");
    }

    @Override
    protected void init(HttpServletRequest request, HttpServletResponse response, TaskProcessForm form, Map<String, Object> model, Context context) {
        this.addDict(model, "flowStatus", IBaseEnum.getEnumMap(FlowStatusEnum.class));

        this.addDict(model, "assigneeName", userService.find(new UserQuery(), getContext()).stream()
                .collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getRealName(), (o, n) -> n)));
    }

    /**
     * 查询流程表
     */
    @PostMapping(value = "list")
    @Override
    public String list(TaskProcessForm form) {
        Map<String, Object> model = new HashMap();
        JSONObject ret = new JSONObject();
        int code = VALUE_RESULT_SUCCESS;
        String busiDesc = "查询" + this.getModuleDesc();
        try {
            Result result = this.service.getProcessList(form.getQuery(), form.getPageInfo(), getContext());
            this.init(request, response, form, model, getContext());
            model.put("result", result.getList());
            model.put("pageInfo", result.getPageInfo());
            model.putAll(form.getModel());
            this.recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            log.error("查询流程列表异常", e);
            this.doException(request, busiDesc, model, e);
            code = VALUE_RESULT_FAILURE;
        }

        ret.put("msg", model.remove("message_info"));
        ret.put("code", code);
        ret.put("query", form.getQuery());
        ret.put("data", model);
        return ret.toJSONString();
    }

    /**
     * 获取流程执行过程
     */
    @PostMapping(value = "flowViewer")
    public String getFlowViewer(@ApiParam(value = "流程实例id") @RequestParam(value = "procInsId", required = false) String procInsId) {
        log.info("receive getFlowViewer,procInsId:" + procInsId);
        JSONObject ret = new JSONObject();
        try {
            List<FlowViewerPdu> flowViewers;
            if (ObjectUtils.isEmpty(procInsId)) {
                flowViewers = Collections.emptyList();
            } else {
                flowViewers = this.getService().getFlowViewer(procInsId);
            }

            ret.put(KEY_RESULT_DATA, flowViewers);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("读取流程图片异常", e);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return ret.toJSONString();
    }


    /**
     * 查询任务流转记录
     */
    @PostMapping(value = "flowRecord")
    public String flowRecord(@ApiParam(value = "流程实例id") @RequestParam(value = "procInsId", required = false) String procInsId,
                             @ApiParam(value = "流程定义id") @RequestParam(value = "deployId", required = false) String deployId) {

        log.info("receive flowRecord,procInsId:" + procInsId + "  deployId:" + deployId);
        Map<String, Object> model = new HashMap();
        JSONObject ret = new JSONObject();
        int code = VALUE_RESULT_SUCCESS;
        String busiDesc = "查询" + this.getModuleDesc();
        try {
            Map<String, Object> record = this.service.flowRecord(procInsId, deployId, getContext());
            ret.put(KEY_RESULT_DATA, record);
            this.recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            log.error("任务流转记录异常", e);
            this.doException(request, busiDesc, model, e);
            code = VALUE_RESULT_FAILURE;
        }
        ret.put("code", code);
        return ret.toJSONString();
    }


    /**
     * 获取流程变量
     */
    @PostMapping(value = "processVariables")
    public String processVariables(@ApiParam(value = "任务id") @RequestParam(value = "taskId", required = false) String taskId) {
        log.info("receive processVariables,taskId:" + taskId);
        JSONObject ret = new JSONObject();
        try {
            Map<String, Object> map = this.getService().getProcessVariables(taskId);
            ret.put(KEY_RESULT_DATA, map);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("获取流程变量异常", e);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return ret.toJSONString();
    }


    /**
     * 获取下一个节点
     */
    @PostMapping(value = "nextFlowNode")
    public String nextFlowNode(@ApiParam(value = "任务数据类") @RequestParam(value = "data") String data) {
        log.info("receive nextFlowNode map:" + JSONObject.toJSONString(data));
        JSONObject ret = new JSONObject();
        try {
            FlowNextPdu nextFlowNode = this.getService().getNextFlowNode(data, getContext());
            ret.put(KEY_RESULT_DATA, nextFlowNode);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("获取下一个节点异常", e);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return ret.toJSONString();
    }

    /**
     * 取消申请
     */
    @PostMapping(value = "stopProcess")
    public String stopProcess(@ApiParam(value = "任务数据类") ProcessStopReq processStopReq) {
        JSONObject ret = new JSONObject();
        try {
            this.getService().stopProcess(processStopReq, getContext());
            ret.put(KEY_RESULT_MSG, "取消申请成功！");
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("取消异常异常", e);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return ret.toJSONString();
    }

    /**
     * 删除实例
     */
    @PostMapping(value = "deleteProcess")
    public String deleteProcess(@ApiParam(value = "任务数据类") ProcessDeleteReq processDeleteReq) {
        JSONObject ret = new JSONObject();
        try {
            this.getService().delete(processDeleteReq, getContext());
            ret.put(KEY_RESULT_MSG, "删除成功！");
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("删除异常", e);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return ret.toJSONString();
    }


    /**
     * 任务审核
     */
    @PostMapping(value = "complete")
    public String complete(@ApiParam(value = "任务数据类") CompleteTaskReq completeTaskReq) {
        JSONObject ret = new JSONObject();
        try {
            String vars = request.getParameter("vars");
            if (!ObjectUtils.isEmpty(vars)) {
                ObjectMapper mapper = new ObjectMapper();
                Map<String, Object> variables = mapper.readValue(vars, Map.class);
                completeTaskReq.setVariables(variables);
            }

            this.getService().complete(completeTaskReq, getContext());
            ret.put(KEY_RESULT_MSG, "审核成功！");
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("审核异常", e);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return ret.toJSONString();
    }

    /**
     * 委派任务
     */
    @PostMapping(value = "delegate")
    public String delegate(@ApiParam(value = "任务数据类") DelegateTaskReq delegateTaskReq) {
        JSONObject ret = new JSONObject();
        try {
            this.getService().delegateTask(delegateTaskReq, getContext());
            ret.put(KEY_RESULT_MSG, "委派任务成功！");
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("委派任务异常", e);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return ret.toJSONString();
    }


    /**
     * 转办任务
     */
    @PostMapping(value = "assignTask")
    public String assignTask(@ApiParam(value = "任务数据类") TurnTaskReq turnTaskReq) {
        JSONObject ret = new JSONObject();
        try {
            this.getService().assignTask(turnTaskReq, getContext());
            ret.put(KEY_RESULT_MSG, "转办任务成功！");
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("转办任务异常", e);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return ret.toJSONString();
    }

    /**
     * 加签任务
     */
    @PostMapping(value = "addSignTask")
    public String addSignTask(@ApiParam(value = "任务数据类") AddSignTaskReq req) {
        JSONObject ret = new JSONObject();
        try {
            this.getService().addSignTask(req, getContext());
            ret.put(KEY_RESULT_MSG, "加签任务成功！");
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("加签任务异常", e);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return ret.toJSONString();
    }

    /**
     * 退回任务
     */
    @PostMapping(value = "return")
    public String taskRreturn(@ApiParam(value = "任务数据类") ReturnTaskReq returnTaskReq) {
        JSONObject ret = new JSONObject();
        try {
            this.getService().taskReturn(returnTaskReq, getContext());
            ret.put(KEY_RESULT_MSG, "退回任务成功！");
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("退回任务异常", e);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return ret.toJSONString();
    }

    /**
     * 退回任务
     */
    @PostMapping(value = "returnList")
    public String returnList(@ApiParam(value = "任务数据类") CommonTaskReq commonTaskReq) {
        JSONObject ret = new JSONObject();
        try {
            List<FlowUserTaskPdu> returnList = this.getService().getReturnList(commonTaskReq, getContext());
            ret.put(KEY_RESULT_DATA, returnList);
            ret.put(KEY_RESULT_MSG, "退回任务成功！");
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("退回任务异常", e);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return ret.toJSONString();
    }

    /**
     * 驳回任务
     */
    @PostMapping(value = "reject")
    public String rejectTask(@ApiParam(value = "任务数据类") RejectTaskReq rejectTaskReq) {
        JSONObject ret = new JSONObject();
        try {
            this.getService().reject(rejectTaskReq, getContext());

            ret.put(KEY_RESULT_MSG, "驳回成功！");
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("驳回任务异常", e);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return ret.toJSONString();
    }


    /**
     * 查询当前流程图
     */
    @PostMapping(value = "preViewImage")
    public String preViewImage(@ApiParam(value = "任务数据类") ProcessCommonReq processCommonReq) {
        JSONObject ret = new JSONObject();
        try {
            String base64 = this.getService().processReadImage(processCommonReq, getContext());
            ret.put(KEY_RESULT_MSG, "获取图片成功！");
            ret.put("pic", base64);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("获取图片异常", e);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return ret.toJSONString();
    }


    public static void main(String[] args) throws JsonProcessingException {

        HashMap<String, String> test = new HashMap<>();

        test.put("name", "value");


        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> variables = mapper.readValue(JSON.toJSONString(test), Map.class);


        System.out.println(JSON.toJSONString(variables));
    }

}