package com.highdatas.mdm.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.highdatas.mdm.entity.Flows;
import com.highdatas.mdm.entity.Maintain;
import com.highdatas.mdm.entity.TUser;
import com.highdatas.mdm.mapper.FlowsMapper;
import com.highdatas.mdm.pojo.*;
import com.highdatas.mdm.service.ActivitiService;
import com.highdatas.mdm.service.IFlowsService;
import com.highdatas.mdm.service.IMaintainService;
import com.highdatas.mdm.service.ITUserService;
import com.highdatas.mdm.service.act.*;
import com.highdatas.mdm.util.Constant;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.FileNotFoundException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author kimi
 * @description
 * @date 2019-12-13 10:57
 */

@Slf4j
@RestController
@RequestMapping("/act")
public class ActivitiController {

    @Autowired
    IdentityService identityService;

    @Autowired
    IFlowsService flowsService;
    @Autowired
    FlowsMapper flowsMapper;

    @Autowired
    HistoryService historyService;

    @Autowired
    RepositoryService repositoryService;

    @Autowired
    RuntimeService runtimeService;

    @Autowired
    TaskService taskService;

    @Autowired
    ActivitiService activitiService;

    @Autowired
    IMaintainService maintainService;
    @Autowired
    ITUserService userService;


    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public Result<List<Map<String, Object>>> list(HttpServletRequest request) throws FileNotFoundException {
        String filterSegment = request.getParameter("filterSegment");
        if (StringUtils.isEmpty(filterSegment)) {
            filterSegment = Constant.WHERE_DEFAULT;
        }
        List<Map<String, Object>> list = flowsMapper.selectVersion(filterSegment);
        for (Map<String, Object> one : list) {
            String newModelId = (String) one.get(Constant.ID);
            String url = "processes/" +  newModelId +  "/" +  newModelId  +  ".png";
            one.put("imgurl",url);
        }
        return Result.success(list);
    }

    @RequestMapping(value = "/processlist", method = RequestMethod.GET)
    public Result<Result<JSONArray>> processlist(HttpServletRequest request)  {
        Result<JSONArray> processList   = repositoryService.getProcessList();
        return Result.success(processList);
    }

    @RequestMapping(value = "/modellist", method = RequestMethod.GET)
    public Result<Result<JSONArray>> modellist(HttpServletRequest request)  {
        Result<JSONArray> processList   = repositoryService.getProcessList();
        return Result.success(processList);
    }


    @RequestMapping(value = "/start/{key}", method = RequestMethod.GET)
    public Result<Object> start(@PathVariable String key,@RequestParam String businessId, HttpServletRequest request)  {
        if (StringUtils.isEmpty(key)) {
                return Result.error(new CodeMsg(1000, "key is not found"));
            }
            String desp = request.getParameter("desp");
            String businessType = request.getParameter("businessType");
            ActivitiBusinessType type;
            if (StringUtils.isEmpty(businessType)) {
                type = ActivitiBusinessType.maintain;
            } else {
                type = ActivitiBusinessType.valueOf(businessType);
            }
            HttpSession session = request.getSession();
            Flows flows = activitiService.start(key, session, businessId, type);
            if (flows == null) {
                return Result.error(CodeMsg.INSERT_ERROR);
            }  else {

            if (type.equals(ActivitiBusinessType.maintain)) {
                Maintain maintain = maintainService.selectById(businessId);
                maintain.setFlowId(flows.getId());
                maintain.setDesp(desp);
                maintain.updateById();
                return Result.success(flows.getId());
            }else if (type.equals(ActivitiBusinessType.exists)) {
                HashMap<String, String> body=new HashMap();
                NextTaskUserInfo nestTaskAssignee = taskService.getNestTaskAssignee(flows.getWorkflowId());

                body.put("activitiId", flows.getId());
                if (nestTaskAssignee == null) {
                    body.put("roleId", null);
                    body.put("userId", null);
                } else {
                    body.put("roleId", nestTaskAssignee.getRoleId());
                    body.put("userId", nestTaskAssignee.getUserId());
                }
                return Result.success(body);
            }
        }
        return Result.error(CodeMsg.ERROR_PARAMS_NOT_MATHED);
    }

    @RequestMapping(value = "/status/{flowid}", method = RequestMethod.GET)
    public ArrayList<HistoricActivityInstance> status(@PathVariable String flowid, HttpServletRequest request)  {
        if (StringUtils.isEmpty(flowid)) {
            return null;
        }
        historyService.setSession(request.getSession());
        Flows flows = flowsService.selectById(flowid);
        if (flows == null) {
            return null;
        }
        String workflowid = flows.getWorkflowId();
        ArrayList<HistoricActivityInstance> historyAction = historyService.getHistoryAction(workflowid);
        return historyAction;
    }

    @RequestMapping(value = "{tableName}/history/{pageNo}", method = RequestMethod.GET)
    public Result history(@PathVariable String tableName, @PathVariable Integer pageNo, HttpServletRequest request)  {
        historyService.setSession(request.getSession());
        String pageSizeStr = request.getParameter("pageSize");

        List<HistoricProcessInstance> processInstanceList = historyService.getHistoryTask();
        List<HistoricProcessInstance> subList = new ArrayList<>();
        for (HistoricProcessInstance historicProcessInstance : processInstanceList) {
            Flows flows = flowsService.selectOne(new EntityWrapper<Flows>().eq("workflow_id", historicProcessInstance.getId()));
            if (flows == null) {
                continue;
            }
            ActivitiBusinessType businessType = flows.getBusinessType();
            if (ActivitiBusinessType.maintain.equals(businessType)) {
                String businessId = flows.getBusinessId();
                Maintain maintain = maintainService.selectById(businessId);
                if (maintain == null) {
                    continue;
                }
                String maintainTableName = maintain.getTableName();
                if (maintainTableName.equalsIgnoreCase(tableName)) {
                    subList.add(historicProcessInstance);
                }
            }
        }

        Page page = new Page(subList.size());
        page.setPageNo(pageNo);
        if (!StringUtils.isEmpty(pageSizeStr)) {
            page.setPageSize(Integer.valueOf(pageSizeStr));
        }
        subList = subList.stream().skip(page.getBeginRecordNo_1()).limit(page.getPageSize()).collect(Collectors.toList());
        ArrayList<Map<String, Object>> result = new ArrayList<>();
        for (HistoricProcessInstance historicProcessInstance : subList) {
            HashMap<String, Object> one = new HashMap<>();
            String workflowId = historicProcessInstance.getId();
            String startUserId = historicProcessInstance.getStartUserId();
            TUser user = userService.selectById(startUserId);
            Flows flows = flowsService.selectOne(new EntityWrapper<Flows>().eq("workflow_id", workflowId));
            Maintain maintain = maintainService.selectById(flows.getBusinessId());
            one.put("userName", user.getUserName());
            one.put("id", flows.getId());
            one.put("status", flows.getStatus());
            one.put("createTime", flows.getCreateTime());
            result.add(one);
        }
        JSONObject object = new JSONObject();
        object.fluentPut("total", page.getRecordCount());
        object.fluentPut("size", page.getPageSize());
        object.fluentPut("pages", page.getPageCount());
        object.fluentPut("current", page.getPageNo());
        object.fluentPut("record", result);

        return Result.success(object);
    }


    @RequestMapping(value = "/diagram/{flowid}", method = RequestMethod.GET)
    public void getDiagram(@PathVariable String flowid, HttpServletResponse response)  {
        if (StringUtils.isEmpty(flowid)) {
            return;
        }
        Flows flows = flowsService.selectById(flowid);
        if (flows == null) {
            return;
        }
        String workflowid = flows.getWorkflowId();
        runtimeService.getDiagram(workflowid, response);
    }
    @RequestMapping(value = "/run", method = RequestMethod.GET)
    public List<Map<String, String>> runTask(HttpServletRequest request){
        historyService.setSession(request.getSession());
        List<Map<String, String>> myRunTask = historyService.getMyRunTask();
        return myRunTask;
    }

    @RequestMapping(value = "/todo", method = RequestMethod.GET)
    public Result todoTask(HttpServletRequest request){
        String pageNo = request.getParameter("pageNo");
        String pageSize = request.getParameter("pageSize");
        if (StringUtils.isEmpty(pageNo)) {
            return activitiService.todoTask(request.getSession(), request.getParameter(Constant.tableName), 1, 15);
        }
        if (StringUtils.isEmpty(pageSize)) {
            return activitiService.todoTask(request.getSession(), request.getParameter(Constant.tableName), Integer.valueOf(pageNo), 15);
        }
        return activitiService.todoTask(request.getSession(), request.getParameter(Constant.tableName), Integer.valueOf(pageNo), Integer.valueOf(pageSize));
    }

    @RequestMapping(value = "/deal/{flowid}", method = RequestMethod.GET)
    public Result doTask(@PathVariable String flowid, @RequestParam boolean pass, HttpServletRequest request)  {
        if (StringUtils.isEmpty(flowid)) {
            return Result.error(CodeMsg.ERROR_PARAMS_NOT_MATHED);
        }
        Flows flows = flowsService.selectById(flowid);
        if (flows == null) {
            return Result.error(CodeMsg.ERROR_PARAMS_NOT_MATHED);
        }
        HttpSession session = request.getSession();

        taskService.setSession(session);
        ActivitiStatus status = flows.getStatus();

        String workflowId = flows.getWorkflowId();
//        Task task = taskService.geTask(workflowId);
//        String id = task.getId();
        String taskId = null;
        if (taskService.checkClaim(workflowId)) {
            taskId = taskService.claimTask(workflowId);
        }

        String reason;
        reason = request.getParameter("reason");
        if (StringUtils.isEmpty(reason)) {
            reason = "确认处理";
        }
        if (taskId == null) {
            Task task = taskService.geTask(workflowId);
            taskId = task.getId();
        }
        boolean completed = taskService.completeTask(taskId, pass, reason);

        if (completed) {
                NextTaskUserInfo nextTaskDefinition = null;
                boolean taskFinished = historyService.isTaskFinished(workflowId);
                if (taskFinished) {
                    if (ActivitiStatus.refuse.equals(status)) {
                        flows.setStatus(ActivitiStatus.close);
                    } else {
                        flows.setStatus(ActivitiStatus.open);
                    }
                    if (flows.getBusinessType().equals(ActivitiBusinessType.maintain)){
                        String maintainId = flows.getBusinessId();
                        maintainService.dealFlow(maintainId, flows.getStatus());
                    }

                } else {
                    if (pass && flows.getStatus().equals(ActivitiStatus.refuse)) {
                        flows.setStatus(ActivitiStatus.working);
                    } else if(!pass && flows.getStatus().equals(ActivitiStatus.working)){
                        flows.setStatus(ActivitiStatus.refuse);
                    }
                    nextTaskDefinition = taskService.getNestTaskAssignee(workflowId);

                }
            HashMap<String, String> body=new HashMap();
            if (flows.getBusinessType().equals(ActivitiBusinessType.exists)){
                body.put("status", flows.getStatus().name());
                if (nextTaskDefinition == null) {
                    body.put("roleId", null);
                    body.put("userId", null);
                } else {
                    body.put("roleId", nextTaskDefinition.getRoleId());
                    body.put("userId", nextTaskDefinition.getUserId());
                }
            }

            flows.setUpdateTime(new Date());
            flowsService.updateById(flows);
            return Result.success(body);
        }else {
            return Result.success(CodeMsg.INSERT_ERROR);
        }
    }
}