package com.activiti6.service.activiti.impl;


import com.activiti6.common.utils.TableSupport;
import com.activiti6.domain.*;

import com.activiti6.mapper.DbTableHisMapper;
import com.activiti6.mapper.MyFormDataActivitiMapper;
import com.activiti6.service.activiti.IDbTableHisService;
import com.activiti6.service.activiti.ProcessInstanceService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.identity.User;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ProcessInstanceServiceImpl implements ProcessInstanceService {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private MyFormDataActivitiMapper myFormDataActivitiMapper;

    @Autowired
    private IdentityService identityService;

    @Override
    public TableDataInfo list() {
        TableDataInfo tableDataInfo = getTableDataInfo();
        return tableDataInfo;
    }

    private TableDataInfo getTableDataInfo() {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
        TableDataInfo tableDataInfo = new TableDataInfo();
        tableDataInfo.setCode(200);
        int size = runtimeService.createProcessInstanceQuery().list().size();
        tableDataInfo.setTotal(size);
        pageNum = (pageNum - 1) * pageSize;
        List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().listPage(pageNum, pageSize);
        List<MyProcessInstance> collect = list.stream().map(x -> {
            MyProcessInstance myProcessInstance = new MyProcessInstance();
            List<Task> listTask = taskService.createTaskQuery().processInstanceId(x.getId()).list();
            String taskName = "";
            for (Task task : listTask) {
                taskName += task.getName() + "/";

            }
            if (!StringUtils.isEmpty(taskName)) {
                taskName = taskName.substring(0, taskName.length() - 1);
                myProcessInstance.setNextTask(taskName);
            }
            BeanUtils.copyProperties(x, myProcessInstance);
            return myProcessInstance;
        }).collect(Collectors.toList());
        tableDataInfo.setRows(collect);
        return tableDataInfo;
    }

    private List<TreeVo> getTreeVos() {
        List<User> users = identityService.createUserQuery().list();
        //用户树信息
        return users.stream().map(x -> {
            TreeVo childrenTreeVo = new TreeVo();
            childrenTreeVo.setValue(x.getId());
            childrenTreeVo.setLabel(x.getFirstName());
            return childrenTreeVo;
        }).collect(Collectors.toList());
    }


    @Override
    public void suspendProcess(String processInstanceId, Integer status) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().
                processInstanceId(processInstanceId).singleResult();
        if (null == processInstance) {
            throw new RuntimeException("不存在正在执行的流程实例:[ " + processInstanceId + " ]");
        }
        //挂起流程
        if (1 == status) {
            runtimeService.suspendProcessInstanceById(processInstanceId);
        }
        //激活流程
        else {
            runtimeService.activateProcessInstanceById(processInstanceId);
        }

    }


    @Override
    public void deleteProcess(String processInstanceId) {
        runtimeService.deleteProcessInstance(processInstanceId, "cascade");
        MyFormDataActivitiExample example = new MyFormDataActivitiExample();
        MyFormDataActivitiExample.Criteria criteria = example.createCriteria();
        criteria.andInstanceIdEqualTo(processInstanceId);
        myFormDataActivitiMapper.deleteByExample(example);
    }

    @Autowired
    private DbTableHisMapper dbTableHisMapper;

    @Override
    public void deleteProcess(List<String> list) {
        for (String processInstanceId : list) {
            runtimeService.deleteProcessInstance(processInstanceId, "cascade");
            MyFormDataActivitiExample example = new MyFormDataActivitiExample();
            MyFormDataActivitiExample.Criteria criteria = example.createCriteria();
            criteria.andInstanceIdEqualTo(processInstanceId);
            myFormDataActivitiMapper.deleteByExample(example);
        }

    }


    @Override
    public void transToOffice(String taskId, String userId) {
        taskService.setAssignee(taskId, userId);
        taskService.setOwner(taskId, userId);
    }

    @Override
    public void entrust(String taskId, String userId) {
        taskService.delegateTask(taskId, userId);
    }

    @Override
    public List<TreeVo> listTask(String processInstanceId) {
        List<Task> listTask = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        List<TreeVo> collect = listTask.stream().map(x -> {
            TreeVo treeVo = new TreeVo();
            treeVo.setLabel(x.getName());
            treeVo.setValue(x.getId());
            return treeVo;
        }).collect(Collectors.toList());
        return collect;
    }

    @Override
    public List<TreeVo> listUser() {
        List<User> users = identityService.createUserQuery().list();
        //用户树信息
        return users.stream().map(x -> {
            TreeVo childrenTreeVo = new TreeVo();
            childrenTreeVo.setValue(x.getId());
            childrenTreeVo.setLabel(x.getFirstName());
            return childrenTreeVo;
        }).collect(Collectors.toList());
    }

    @Autowired
    private IDbTableHisService iDbTableHisService;

    @Override
    @Transactional
    public String commit(ProcessInstanceCommitFrom processInstanceCommitFrom) {
        String processId = processInstanceCommitFrom.getProcessId();
        Long fromId = processInstanceCommitFrom.getFormId();
        String fromKey = processInstanceCommitFrom.getFormKey();
        Map<String, Object> dataMap = processInstanceCommitFrom.getDataMap();
        String appUserId = processInstanceCommitFrom.getUserId();
        // 启动流程时设置业务 key
        dataMap.put("appUserId", appUserId);
        dataMap.put("formId", fromId);
        dataMap.put("formKey", fromKey);
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceById(processId, dataMap);
        String processInstanceId = processInstance.getId();
        Task task = taskService.createTaskQuery().taskAssignee(appUserId).processInstanceId(processInstanceId).singleResult();
        String taskId = task.getId();
        //设置签收
        taskService.claim(taskId, appUserId);
        //完成task
        taskService.complete(taskId, dataMap);
        //插入历史
        iDbTableHisService.insertDbTableHis(processInstanceId,fromId, fromKey);
        return processInstanceId;
    }

    @Override
    @Transactional
    public String recommit(ProcessInstanceCommitFrom processInstanceCommitFrom) {
        String taskId = processInstanceCommitFrom.getTaskId();
        Map<String, Object> dataMap = processInstanceCommitFrom.getDataMap();
        String appUserId = processInstanceCommitFrom.getUserId().toString();
        //设置签收
        taskService.claim(taskId, appUserId);
        //完成task
        taskService.complete(taskId, dataMap);
        return taskId;
    }

    @Override
    public Map<String, String> check(ProcessInstanceCheckFrom processInstanceCommitFrom) {
        Map<String, String> map = new HashMap<>();
        List<String> instanceIdS = processInstanceCommitFrom.getInstanceIdS();
        String appUserId = processInstanceCommitFrom.getSysUser().getUserId().toString();
        List<Task> list = taskService.createTaskQuery().taskAssignee(appUserId).processInstanceIdIn(instanceIdS).list();
        for (Task task : list) {
            String id = task.getId();
            String processInstanceId = task.getProcessInstanceId();
            map.put(processInstanceId, task.getId());
        }
        return map;
    }


}
