package yangtz.cs.liu.campus.service.impl.office;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.util.UserInfoUtil;
import com.ruoyi.system.service.ISysUserService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.persistence.entity.TaskEntityImpl;
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.util.CollectionUtils;
import yangtz.cs.liu.activiti.service.IProcessService;
import yangtz.cs.liu.campus.domain.office.SchoolOfficePurchase;
import yangtz.cs.liu.campus.domain.vehicle.SchoolVehicleApplication;
import yangtz.cs.liu.campus.mapper.office.SchoolOfficePurchaseMapper;
import yangtz.cs.liu.campus.service.office.ISchoolOfficePurchaseService;
import yangtz.cs.liu.campus.vo.office.OfficeTodoListVO;
import yangtz.cs.liu.campus.vo.vehicle.VehicleApplicationVO;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.baomidou.mybatisplus.core.toolkit.ObjectUtils.isNotNull;
import static com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank;
import static com.core.constant.ProcessCommon.*;
import static com.core.constant.ProcessDefinition.OFFICEPURCHASE;
import static com.core.constant.ProcessVariables.CHARGEUSERID;
import static com.core.constant.ProcessVariables.CHARGEUSERIDS;

/**
 * 办公申购Service业务层处理
 *
 * @author xu
 * @date 2022-09-27
 */
@Service
public class SchoolOfficePurchaseServiceImpl extends ServiceImpl<SchoolOfficePurchaseMapper, SchoolOfficePurchase> implements ISchoolOfficePurchaseService {
    @Autowired
    private SchoolOfficePurchaseMapper schoolOfficePurchaseMapper;

    @Resource
    private IdentityService identityService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private IProcessService processService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private UserInfoUtil userInfoUtil;

    /**
     * 查询办公申购列表
     *
     * @param schoolOfficePurchase 办公申购
     * @return 办公申购
     */
    @Override
    public List<OfficeTodoListVO> queryList(String submitState,SchoolOfficePurchase schoolOfficePurchase) {
        List<OfficeTodoListVO> voList = schoolOfficePurchaseMapper.queryList(submitState,schoolOfficePurchase);
        // 当前环节
        for (OfficeTodoListVO leave : voList) {
            if (StringUtils.isNotBlank(leave.getInstanceId())) {
                List<Task> taskList = taskService.createTaskQuery()
                        .processInstanceId(leave.getInstanceId())
//                        .singleResult();
                        .list();    // 例如请假会签，会同时拥有多个任务
                if (!CollectionUtils.isEmpty(taskList)) {
                    TaskEntityImpl task = (TaskEntityImpl) taskList.get(0);
                    leave.setTaskId(task.getId());
                    if (task.getSuspensionState() == 2) {
                        leave.setTaskName("已挂起");
                        leave.setSuspendState("2");
                    } else {
                        leave.setTaskName(task.getName());
                        leave.setSuspendState("1");
                    }
                } else {
                    // 已办结或者已撤销
                    leave.setTaskName("已结束");
                }
            } else {
                leave.setTaskName("未启动");
            }
        }
        return voList;
    }

    @Override
    public OfficeTodoListVO getInfo(Long id) {
        return schoolOfficePurchaseMapper.getInfo(id);
    }

    /**
     * @param schoolOfficePurchase 业务实体
     * @param username             提交申请人 记录到底是哪个人提交了申请
     * @param key                  流程标识 用于指定到底启动的是哪个流程(请假流程 办公流程 会议流程等) 这里启动的是 办公流程
     * @param variables            变量集合 流程中指定一些变量,这里我们主要用于动态指定审批人
     *                             <p>
     *                             启动流程
     *                             1. 设置流程申请人.
     *                             2. 设置审批人.审批人因为是动态的,所以放在variables集合里面
     *                             3. 启动流程
     * @author lyric
     * @date 2022-09-30
     */
    @Override
    public int submitApply(SchoolOfficePurchase schoolOfficePurchase, String username, String key, Map<String, Object> variables) {
        // 业务key 用于对于流程的区分,比如一个办公流程,有很多人都提交了申请,businessKey主要是用来区分不同用户的.toString()因为activiti的表存的是varchar
        String businessKey = schoolOfficePurchase.getId().toString();
        identityService.setAuthenticatedUserId(username);

        //设置 候选人
        String candidateUsers = candidateUser((String) variables.get(ROLEKEY));
        variables.put(CHARGEUSERIDS, candidateUsers);
        //variables.put(CHARGEUSERIDS, "1,2");

        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key, businessKey, variables);
        String instanceId = processInstance.getId();
        //与我们的业务表开始建立关系
        schoolOfficePurchase.setInstanceId(instanceId);
        return schoolOfficePurchaseMapper.updateById(schoolOfficePurchase);
    }

    /**
     * @author lyric
     * @date 2022-10-27
     * 设置候选组
     */
    public String candidateUser(String key) {
        if (StringUtils.isEmpty(key)) {
            return "";
        }
        List<SysUser> userList = userService.selectUserListByRoleKey(key);
        List<String> userIds = userList.stream().map(o -> o.getUserId().toString()).collect(Collectors.toList());
        String candidateUsers = String.join(",", userIds);
        return candidateUsers;
    }

    /**
     * @author lyric
     * @date 2021-10-07
     * 同时需要删除工作流(暂时停用)
     */
    @Override
    public int deleteOfficePurchaseByIds(List<Long> ids) {
        for (Long id : ids) {
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processDefinitionKey(OFFICEPURCHASE).processInstanceBusinessKey(id + "").singleResult();
            if (ObjectUtils.isNotNull(processInstance)) {
                runtimeService.deleteProcessInstance(processInstance.getId(), "删除");
            }
            // 删除历史数据
            HistoricProcessInstance history = historyService.createHistoricProcessInstanceQuery()
                    .processDefinitionKey(OFFICEPURCHASE).processInstanceBusinessKey(id + "").singleResult();
            if (history != null) {
                historyService.deleteHistoricProcessInstance(history.getId());
            }
        }
        return 0;
    }

    public List<OfficeTodoListVO> getTodoList(List<Task> taskList) {
        List<OfficeTodoListVO> results = new ArrayList<>();
        for (Task task : taskList) {
            TaskEntityImpl taskImpl = (TaskEntityImpl) task;
            //拿到当前任务id
            String processInstanceId = taskImpl.getProcessInstanceId();
            //拿到流程定义对象
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            //业务id(我们当时新增的时候指定了businessKey为id)
            String businessKey = processInstance.getBusinessKey();
            //通过id查询出我们业务对象
            SchoolOfficePurchase schoolOfficePurchase = schoolOfficePurchaseMapper.selectById(new Long(businessKey));
            if(StringUtils.isNotNull(schoolOfficePurchase)){
                //转vo
                OfficeTodoListVO officeTodoListVO = new OfficeTodoListVO();
                BeanUtils.copyProperties(schoolOfficePurchase, officeTodoListVO);
                officeTodoListVO.setTaskId(taskImpl.getId());
                if (SUSPENDSTATE_PENDING.equals(taskImpl.getSuspensionState())) {
                    //挂起
                    officeTodoListVO.setTaskName(PENDING);
                } else {
                    officeTodoListVO.setTaskName(taskImpl.getName());
                }
                results.add(officeTodoListVO);
            }
        }
        return results;
    }

    /**
     * @param entity
     * @param userId
     * @return
     * @author lyric
     * @date 2021-10-07
     * 待办列表
     * <p>
     * 1.根据当前登录人查询出待办任务集合(这里查的不仅是处理人的,还有事用户组的也查出来了,可能之后需要做处理)
     * 2.遍历集合,获取每一个业务对象转vo
     * 3.分页返回
     */
    @Override
    public List<OfficeTodoListVO> findTodoTasks(String key, SchoolOfficePurchase entity, String userId) {
        //当前登录人待办任务集合
        List<Task> taskList = processService.findCandidateTasks(userId, key);
        return getTodoList(taskList);
    }

    /**
     * @param key
     * @param entity
     * @param userId
     * @return 已办列表
     * @author lyric
     * @date 2021-10-10
     */
    @Override
    public List<OfficeTodoListVO> findDoneTasks(String key, SchoolOfficePurchase entity, String userId) {
        List<OfficeTodoListVO> list = new ArrayList<>();
        //当前登录人完成的历史集合
        List<HistoricTaskInstance> hisList = processService.findDoneTasks(userId, key);

        for (HistoricTaskInstance instance : hisList) {
            //流程实例key
            String processInstanceId = instance.getProcessInstanceId();
            HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .singleResult();
            //业务id
            String businessKey = processInstance.getBusinessKey();
            //通过id查询出我们业务对象
            SchoolOfficePurchase schoolOfficePurchase = schoolOfficePurchaseMapper.selectById(new Long(businessKey));
            if(StringUtils.isNotNull(schoolOfficePurchase)) {
                //转vo
                OfficeTodoListVO officeTodoListVO = new OfficeTodoListVO();
                BeanUtils.copyProperties(schoolOfficePurchase, officeTodoListVO);
                officeTodoListVO.setTaskName(instance.getName());
                list.add(officeTodoListVO);
            }
        }
        return list;
    }

    /**
     * @author lyric
     * @date 2022/10/27 13:00
     * 我的待办
     */
    @Override
    public List<OfficeTodoListVO> findMyTodoTasks(String key, SchoolOfficePurchase entity, String userId) {
        //当前登录人待办任务集合
        List<Task> taskList = processService.findAssigneeTasks(userId, key);
        return getTodoList(taskList);
    }

    /**
     * 查询小程序办公申购列表
     *
     * @param schoolOfficePurchase 办公申购
     * @return 办公申购集合
     */
    @Override
    public List<OfficeTodoListVO> queryMyList(String submitState, SchoolOfficePurchase schoolOfficePurchase) {
        Long userId = userInfoUtil.getTeacherUserId();
        schoolOfficePurchase.setApplyId(userId);
        List<OfficeTodoListVO> voList = schoolOfficePurchaseMapper.queryList(submitState,schoolOfficePurchase);
        // 当前环节
        for (OfficeTodoListVO leave : voList) {
            if (StringUtils.isNotBlank(leave.getInstanceId())) {
                List<Task> taskList = taskService.createTaskQuery()
                        .processInstanceId(leave.getInstanceId())
//                        .singleResult();
                        .list();    // 例如请假会签，会同时拥有多个任务
                if (!CollectionUtils.isEmpty(taskList)) {
                    TaskEntityImpl task = (TaskEntityImpl) taskList.get(0);
                    leave.setTaskId(task.getId());
                    if (task.getSuspensionState() == 2) {
                        leave.setTaskName("已挂起");
                        leave.setSuspendState("2");
                    } else {
                        leave.setTaskName(task.getName());
                        leave.setSuspendState("1");
                    }
                } else {
                    // 已办结或者已撤销
                    leave.setTaskName("已结束");
                }
            } else {
                leave.setTaskName("未启动");
            }
        }
        return voList;
    }
}
