package com.activiti6.service.activiti.impl;


import com.activiti6.common.exception.CustomException;
import com.activiti6.common.utils.DateUtils;
import com.activiti6.common.utils.StringUtils;
import com.activiti6.common.utils.TableSupport;
import com.activiti6.domain.*;
import com.activiti6.mapper.MyFormDataActivitiMapper;
import com.activiti6.mapper.activiti.NewMyFormDataMapper;
import com.activiti6.service.activiti.LeaveNewService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.activiti.engine.*;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.DelegationState;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class LeaveNewServiceImpl implements LeaveNewService {
    protected final Logger logger = LoggerFactory.getLogger(LeaveNewServiceImpl.class);

    @Autowired
    private NewMyFormDataMapper newMyFormDataMapper;
    @Autowired
    private MyFormDataActivitiMapper myFormDataActivitiMapper;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private FormService formService;

    @Override
    @Transactional
    public Object getFormData(String processKey,Long userId) {
        ProcessDefinitionQuery pdq = repositoryService.createProcessDefinitionQuery();

//        ProcessDefinition processDefinition = pdq.processDefinitionKey(processKey).processDefinitionVersion(version).singleResult();
        ProcessDefinition processDefinition = pdq.processDefinitionId(processKey).singleResult();
        String id = processDefinition.getId();
        String startFormKey = formService.getStartFormKey(id);
        MyFormData myFormData = null;
        if (!StringUtils.isNull(startFormKey)) {
            myFormData = getMyFormDataBean(processKey, startFormKey);
            return myFormData;
        } else {
            //流程发起人
            identityService.setAuthenticatedUserId(userId.toString());
            // 启动流程时设置业务 key
            Map<String, Object> map = new HashMap<>();
            String appUserId = userId.toString();
            map.put("appUserId", appUserId);
            ProcessInstance processInstance = runtimeService
                    .startProcessInstanceById(processKey, map);
            String processInstanceId = processInstance.getId();
            Task task = taskService.createTaskQuery().taskAssignee(appUserId).processInstanceId(processInstanceId).singleResult();
            String formKey = task.getFormKey();
            //获取选人表单数据
            myFormData = getMyFormDataBean(processKey, formKey);
            //填充表单渲染数据
            MyFormDataActiviti myFormDataActiviti = new MyFormDataActiviti();
            myFormDataActiviti.setInstanceId(processInstanceId);
            myFormDataActiviti.setTaskId(task.getId());
            BeanUtils.copyProperties(myFormData, myFormDataActiviti);
            return myFormDataActiviti;
        }

    }

    private MyFormData getMyFormDataBean(String processKey, String startFormKey) {

        MyFormDataExample example = new MyFormDataExample();
        MyFormDataExample.Criteria criteria = example.createCriteria();
        criteria.andFKeyEqualTo(startFormKey);
        String[] split = processKey.split(":");
        processKey = split[0];
        Integer version = Integer.valueOf(split[1]);
        criteria.andModelKeyEqualTo(processKey);
        criteria.andModelVersionEqualTo(version);
        List<MyFormData> myFormDataList = newMyFormDataMapper.selectByExample(example);
        if (myFormDataList.size() == 0) {
            throw new CustomException("没找到对应的外置表单!");
        }
        myFormDataList = myFormDataList.stream().sorted(Comparator.comparing(MyFormData::getfVersion, Comparator.reverseOrder())).collect(Collectors.toList());
        MyFormData myFormData = myFormDataList.get(0);
        return myFormData;
    }

    @Override
    @Transactional
    public int add(MyFormDataActiviti myFormDataActiviti,Long userId) {
        //获取登录信息
        myFormDataActiviti.setCreateUser(userId.toString());
        myFormDataActiviti.setCreateTime(new Date());
        int i = myFormDataActivitiMapper.insertSelective(myFormDataActiviti);
        //如果没有任务id就是普通新增
        String taskId = myFormDataActiviti.getTaskId();
        if (!StringUtils.isNull(taskId)) {
            String jsonData = myFormDataActiviti.getJsonData();
            JSONObject jsonObject = JSON.parseObject(jsonData);
            JSONObject formData = jsonObject.getJSONObject("formData");
            Map<String, Object> map = JSONObject.toJavaObject(formData, Map.class);
            map.put("myFormDataActiviti", myFormDataActiviti);
            //设置签收
            taskService.claim(taskId, userId.toString());
            //完成task
            taskService.complete(taskId, map);
        }
        return i;
    }

    @Override
    public List<MyFormDataActiviti> select(Long userId) {
        MyFormDataActivitiExample example = new MyFormDataActivitiExample();
        MyFormDataActivitiExample.Criteria criteria = example.createCriteria();
        String appUser = userId.toString();
        criteria.andCreateByEqualTo(appUser);
        criteria.andApplyUserEqualTo(appUser);
        example.setOrderByClause("create_time desc");
        List<MyFormDataActiviti> myFormDataActivitis = myFormDataActivitiMapper.selectByExample(example);
        return myFormDataActivitis;
    }

    @Override
    public MyFormDataActiviti get(Long id) {
        MyFormDataActiviti myFormDataActiviti = myFormDataActivitiMapper.selectByPrimaryKey(id);
        return myFormDataActiviti;
    }

    @Override
    public int update(MyFormDataActiviti myFormData,Long userId) {
        myFormData.setUpdateBy(userId.toString());
        myFormData.setUpdateTime(new Date());
        return myFormDataActivitiMapper.updateByPrimaryKeySelective(myFormData);
    }

    @Override
    public int remove(List<Long> ids) {
        MyFormDataActivitiExample example = new MyFormDataActivitiExample();
        MyFormDataActivitiExample.Criteria criteria = example.createCriteria();
        criteria.andFIdIn(ids);
        int i = myFormDataActivitiMapper.deleteByExample(example);
        return i;
    }


    @Autowired
    private IdentityService identityService;

    @Autowired
    private RuntimeService runtimeService;

    /**
     * 启功流程
     *
     * @param id
     */
    @Override
    public void submitApply(Long id,Long userId) {
        MyFormDataActiviti myFormDataActiviti = myFormDataActivitiMapper.selectByPrimaryKey(id);
        // 用来设置启动流程的人员ID，引擎会自动把用户ID保存到activiti:initiator中
        String applyUser = myFormDataActiviti.getApplyUser();
        identityService.setAuthenticatedUserId(applyUser);
        String modelKey = myFormDataActiviti.getModelKey();
        Long aLong = myFormDataActiviti.getfId();
        //启动流程
        ProcessInstance processInstance = runtimeService // 启动流程时设置业务 key
                .startProcessInstanceByKey(modelKey, aLong.toString());
        String processInstanceId = processInstance.getId();
        myFormDataActiviti.setInstanceId(processInstanceId);
        //更新标记
        myFormDataActiviti.setUpdateBy(userId.toString());
        myFormDataActiviti.setUpdateTime(new Date());
        myFormDataActivitiMapper.updateByPrimaryKey(myFormDataActiviti);
    }

    @Autowired
    private TaskService taskService;

    @Override

    public String taskUserMsg(String userId) {
        List<Task> list = new ArrayList<>();
        List<Task> list1 = taskService.createTaskQuery().taskAssignee(userId).list();
        list.addAll(list1);
        List<Task> list2 = taskService.createTaskQuery().taskCandidateUser(userId).list();
        list.addAll(list2);
        //去重
        list = list.stream().distinct().collect(Collectors.toList());
        String msg = null;
        //分组
        if (list.size() > 0) {
            msg = "你有" + list.size() + "条工单未审核!";
        }
        return msg;
    }

    @Override
    public TableDataInfo findTodoTasks(MyTaskVo myTaskVoForm,String userId) throws InterruptedException {
        //Thread.sleep(100 * 3);
        TableDataInfo tableDataInfo = new TableDataInfo();
        //用户id

        List<Task> list = new ArrayList<>();
        //分页处理
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
        pageNum = (pageNum - 1) * pageSize;
        String processDefinitionName1 = myTaskVoForm.getProcessDefinitionName();
        if (!org.springframework.util.StringUtils.isEmpty(processDefinitionName1)) {
            String pdName = "%" + processDefinitionName1 + "%";
            List<Task> list1 = taskService.createTaskQuery().taskAssignee(userId).processDefinitionNameLike(pdName).list();
            list.addAll(list1);
            List<Task> list2 = taskService.createTaskQuery().taskCandidateUser(userId).processDefinitionNameLike(pdName).list();
            list.addAll(list2);
        } else {
            List<Task> list1 = taskService.createTaskQuery().taskAssignee(userId).list();
            list.addAll(list1);
            List<Task> list2 = taskService.createTaskQuery().taskCandidateUser(userId).list();
            list.addAll(list2);
        }
        int size = list.size();
        //去重
        if (list.size() > 1) {
            Set<Task> set = new HashSet();
            List<Task> listnew = new ArrayList<>();
            set.addAll(list);
            listnew.addAll(set);
            list = listnew;
        }
        List<MyTaskVo> myTaskVoList = new ArrayList<>();
        for (Task task : list) {

            //流程被暂停跳过
            boolean suspended = task.isSuspended();
            String formKey = task.getFormKey();
            if (suspended) {
                continue;
            }
            if (StringUtils.isNull(formKey)) {
                continue;
            }
            MyTaskVo myTaskVo = new MyTaskVo();
            String id = task.getId();
            String name = task.getName();
            String processInstanceId = task.getProcessInstanceId();
            String processDefinitionId = task.getProcessDefinitionId();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            String[] split = processDefinitionId.split(":");
            String processDefinitionName = processDefinition.getName();
            String businessKey = split[0];
            Integer version = Integer.valueOf(split[1]);
            myTaskVo.setTaskId(id);
            myTaskVo.setProcessDefinitionName(processDefinitionName);
            Object workNum = taskService.getVariable(id, "workNum");
            if (StringUtils.isNotNull(workNum)) {
                myTaskVo.setWorkNum(workNum.toString());
            }
            Object title = taskService.getVariable(id, "title");
            if (StringUtils.isNotNull(title)) {
                myTaskVo.setTitle(title.toString());
            }
            Object creatUserName = taskService.getVariable(id, "creatUserName");
            if (StringUtils.isNotNull(creatUserName)) {
                myTaskVo.setCreatUserName(creatUserName.toString());
            }
            Object creatDeptName = taskService.getVariable(id, "creatDeptName");
            if (StringUtils.isNotNull(creatDeptName)) {
                myTaskVo.setCreatDeptName(creatDeptName.toString());
            }
            Object creatTime = taskService.getVariable(id, "creatTime");
            if (StringUtils.isNotNull(creatTime)) {
                Date creatTimeRe = DateUtils.parseDate(creatTime);
                myTaskVo.setCreatFormTime(creatTimeRe);
            }
            myTaskVo.setTaskName(name);
            myTaskVo.setFormKey(formKey);
            myTaskVo.setInstanceId(processInstanceId);
            myTaskVo.setModelKey(businessKey);
            myTaskVo.setModelVersion(version);
            myTaskVoList.add(myTaskVo);
        }
        //以属性一降序
        List<MyTaskVo> collect = myTaskVoList.stream().sorted(
                Comparator.comparing(MyTaskVo::getCreatFormTime, Comparator.reverseOrder())
        ).collect(Collectors.toList());
        //数据
        tableDataInfo.setRows(collect);
        //条数
        tableDataInfo.setTotal(size);
        tableDataInfo.setCode(200);
        tableDataInfo.setMsg("success");
        return tableDataInfo;
    }

    @Override
    public MyFormData taskFormData(MyTaskVo myTaskVo) {
        MyFormDataExample example = new MyFormDataExample();
        MyFormDataExample.Criteria criteria = example.createCriteria();
        String modelKey = myTaskVo.getModelKey();
        String formKey = myTaskVo.getFormKey();
        Integer modelVersion = myTaskVo.getModelVersion();
        criteria.andFKeyEqualTo(formKey);
        criteria.andModelKeyEqualTo(modelKey);
//        criteria.andModelVersionEqualTo(modelVersion);
        List<MyFormData> myFormDataList = newMyFormDataMapper.selectByExample(example);
        if (myFormDataList.size() == 0) {
            throw new CustomException("没找到对应的外置表单!");
        }
        myFormDataList = myFormDataList.stream().sorted(Comparator.comparing(MyFormData::getfVersion, Comparator.reverseOrder())).collect(Collectors.toList());
        MyFormData myFormData = myFormDataList.get(0);
        return myFormData;
    }

    @Override
    @Transactional
    public void taskCommit(TaskCommitForm taskCommitForm,SysUser user) {
        //新增提交历史数据道数据库
        Long userId = user.getUserId();
        String userIdStr = userId.toString();
        //acitviti提交
        MyFormDataActiviti myFormDataActiviti = commit(taskCommitForm, userIdStr);
        //本地表单提交
        insertMyFormDataActiviti(user, userIdStr, myFormDataActiviti);
    }

    private void insertMyFormDataActiviti(SysUser user, String userIdStr, MyFormDataActiviti myFormDataActiviti) {
        String deptName = user.getDept().getDeptName();
        //提交人
        myFormDataActiviti.setCreateUser(user.getUserName());
        //提交部门
        myFormDataActiviti.setCreateDept(deptName);
        myFormDataActiviti.setCreateBy(userIdStr);
        myFormDataActiviti.setCreateTime(new Date());
        myFormDataActivitiMapper.insertSelective(myFormDataActiviti);
    }

    private MyFormDataActiviti commit(TaskCommitForm taskCommitForm, String userIdStr) {
        MyFormDataActiviti myFormDataActiviti = taskCommitForm.getMyFormDataActiviti();
        String taskId = taskCommitForm.getTaskId();
        String jsonData = myFormDataActiviti.getJsonData();
        JSONObject jsonObject = JSON.parseObject(jsonData);
        JSONObject formData = jsonObject.getJSONObject("formData");
        if (formData.size() == 0) {
            throw new CustomException("请提交审核数据!");
        }
        Map map = JSONObject.toJavaObject(formData, Map.class);
        //完成task
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        String processDefinitionId = task.getProcessDefinitionId();
        String[] split = processDefinitionId.split(":");
        String businessKey = split[0];
        Integer version = Integer.valueOf(split[1]);
        myFormDataActiviti.setModelVersion(version);
        DelegationState delegationState = task.getDelegationState();
        if (!StringUtils.isNull(delegationState)) {
            if (delegationState.toString().equals("RESOLVED")) {
                taskService.complete(taskId, map);
            } else if (delegationState.toString().equals("PENDING")) {
                //如果是委托任务需要做处理
                taskService.resolveTask(taskId, map);
                taskService.complete(taskId, map);
            } else {
                System.out.println("此任务不是委托任务");
            }
        } else {
            //非委托任务需要签收
            taskService.claim(taskId, userIdStr);
            taskService.complete(taskId, map);
        }
        return myFormDataActiviti;
    }

    @Override
    public List<FormsVo> showForms(String instanceId) {
        MyFormDataActivitiExample example = new MyFormDataActivitiExample();
        MyFormDataActivitiExample.Criteria criteria = example.createCriteria();
        criteria.andInstanceIdEqualTo(instanceId);
        List<MyFormDataActiviti> list = myFormDataActivitiMapper.selectByExample(example);
        List<FormsVo> collect = list.stream().map(x -> {
            FormsVo formsVo = new FormsVo();
            String s = x.getfName();
            Date createTime = x.getCreateTime();
            //设置任务名称
            formsVo.setTaskName(s);
            String jsonData = x.getJsonData();
//            JSONObject jsonObject = JSON.parseObject(jsonData);
//            Map map = jsonObject.toJavaObject(Map.class);
            formsVo.setCreateUser(x.getCreateUser());
            formsVo.setCreateDept(x.getCreateDept());
            //数据回显
            formsVo.setFormObj(jsonData);
            formsVo.setCreateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, createTime));
            return formsVo;
        }).collect(Collectors.toList());
        return collect;
    }

    @Override
    public List<MyFormDataActiviti> taskDoneList(MyFormDataActiviti myFormDataActiviti,String userIdStr) {
        myFormDataActiviti.setCreateBy(userIdStr);
        List<MyFormDataActiviti> list = myFormDataActivitiMapper.taskDoneList(myFormDataActiviti);
        return list;
    }

    @Override
    public List<MyTaskVo> taskList(String proId) {
        List<Task> list = taskService.createTaskQuery().processDefinitionId(proId).list();
        List<MyTaskVo> myTaskVoList = new ArrayList<>();
        for (Task task : list) {
            MyTaskVo myTaskVo = new MyTaskVo();
            String id = task.getId();
            String formKey = task.getFormKey();
            String name = task.getName();
            String processInstanceId = task.getProcessInstanceId();
            String processDefinitionId = task.getProcessDefinitionId();
            String[] split = processDefinitionId.split(":");
            String businessKey = split[0];
            Integer version = Integer.valueOf(split[1]);
            myTaskVo.setTaskId(id);
            myTaskVo.setTaskName(name);
            myTaskVo.setFormKey(formKey);
            myTaskVo.setInstanceId(processInstanceId);
            myTaskVo.setModelKey(businessKey);
            myTaskVo.setModelVersion(version);
            myTaskVoList.add(myTaskVo);
        }
        return myTaskVoList;
    }
}
