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

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.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.student.SchoolStudentLeave;
import yangtz.cs.liu.campus.domain.teacher.SchoolTeacherOvertime;
import yangtz.cs.liu.campus.mapper.teacher.SchoolTeacherOvertimeMapper;
import yangtz.cs.liu.campus.service.teacher.ISchoolTeacherOvertimeService;
import yangtz.cs.liu.campus.vo.office.OfficeTodoListVO;
import yangtz.cs.liu.campus.vo.teacher.SchoolTeacherOvertimeVO;
import yangtz.cs.liu.campus.vo.teacher.TeacherLeaveVO;
import yangtz.cs.liu.campus.vo.teacher.TeacherOvertimeVO;

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

import static com.core.constant.ProcessCommon.PENDING;
import static com.core.constant.ProcessCommon.SUSPENDSTATE_PENDING;
import static com.core.constant.ProcessVariables.*;
import static com.ruoyi.common.utils.SecurityUtils.getUserId;

@Service
public class SchoolTeacherOvertimeServiceImpl extends ServiceImpl<SchoolTeacherOvertimeMapper, SchoolTeacherOvertime> implements ISchoolTeacherOvertimeService {

    @Autowired
    private SchoolTeacherOvertimeMapper schoolTeacherOvertimeMapper;

    @Resource
    private IdentityService identityService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private IProcessService processService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private TaskService taskService;

    @Override
    public List<SchoolTeacherOvertimeVO> selectSchoolTeacherOvertimeList(String submitState, SchoolTeacherOvertimeVO schoolTeacherOvertimeVO) {
        List<SchoolTeacherOvertimeVO> schoolTeacherOvertimeVOS = schoolTeacherOvertimeMapper.selectSchoolTeacherOvertimeList(submitState, schoolTeacherOvertimeVO);
        // 当前环节
        for(SchoolTeacherOvertimeVO overtime:schoolTeacherOvertimeVOS) {
            if (StringUtils.isNotBlank(overtime.getInstanceId())) {
                List<Task> taskList = taskService.createTaskQuery()
                        .processInstanceId(overtime.getInstanceId())
//                        .singleResult();
                        .list();    // 例如请假会签，会同时拥有多个任务
                if (!CollectionUtils.isEmpty(taskList)) {
                    TaskEntityImpl task = (TaskEntityImpl) taskList.get(0);
                    overtime.setTaskId(task.getId());
                    if (task.getSuspensionState() == 2) {
                        overtime.setTaskName("已挂起");
                        overtime.setSuspendState("2");
                    } else {
                        overtime.setTaskName(task.getName());
                        overtime.setSuspendState("1");
                    }
                } else {
                    // 已办结或者已撤销
                    overtime.setTaskName("已结束");
                }
            } else {
                overtime.setTaskName("未启动");
            }
        }
        return schoolTeacherOvertimeVOS;
    }

    @Override
    public int removeSchoolTeacherOvertimeById(List<Long> ids) {
        return schoolTeacherOvertimeMapper.removeSchoolTeacherOvertimeById(ids);
    }

    @Override
    public int removeSchoolTeacherOvertimeByIds(List<Long> ids) {
        return schoolTeacherOvertimeMapper.removeSchoolTeacherOvertimeById(ids);
    }

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

        /**
         * 注: 我这里先写死为admin这个账号,之后肯定要动态改
         * 可能之后是用户组,但怎么说都是数据库查出来
         */
        //设置处理人
        variables.put(CHARGEUSERID, schoolTeacherOvertime.getHandUserId());
        //设置销假人
        variables.put(APPLYUSER, getUserId());

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

    /**
     * @author lyric
     * @date 2021-10-07
     * 待办列表
     *
     *  1.根据当前登录人查询出待办任务集合(这里查的不仅是处理人的,还有事用户组的也查出来了,可能之后需要做处理)
     *  2.遍历集合,获取每一个业务对象转vo
     *  3.分页返回
     * @param entity
     * @param userId
     * @return
     */
    @Override
    public List<TeacherOvertimeVO> findTodoTasks(String key, SchoolTeacherOvertime entity, String userId) {
        List<TeacherOvertimeVO> list = new ArrayList<>();
        //当前登录人待办任务集合
        List<Task> taskList = processService.findTodoList(userId, key);
        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查询出我们业务对象
            SchoolTeacherOvertime schoolTeacherOvertime = schoolTeacherOvertimeMapper.selectById(new Long(businessKey));
            if(StringUtils.isNull(schoolTeacherOvertime)){
                continue;
            }
            //转vo
            TeacherOvertimeVO teacherOvertimeVO = new TeacherOvertimeVO();
            BeanUtils.copyProperties(schoolTeacherOvertime,teacherOvertimeVO);
            teacherOvertimeVO.setTaskId(taskImpl.getId());

            if (SUSPENDSTATE_PENDING.equals(taskImpl.getSuspensionState())) {
                //挂起
                teacherOvertimeVO.setTaskName(PENDING);
            }else{
                teacherOvertimeVO.setTaskName(taskImpl.getName());
            }
            list.add(teacherOvertimeVO);
        }
        return list;
    }

    /**
     * @author lyric
     * @date 2021-10-10
     *
     *
     * @param key
     * @param entity
     * @param userId
     * @return
     *
     * 已办列表
     */
    @Override
    public List<TeacherOvertimeVO> findDoneTasks(String key, SchoolTeacherOvertime entity, String userId) {

        List<TeacherOvertimeVO> 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查询出我们业务对象
            SchoolTeacherOvertime schoolTeacherOvertime = schoolTeacherOvertimeMapper.selectById(new Long(businessKey));
            //转vo
            TeacherOvertimeVO teacherOvertimeVO = new TeacherOvertimeVO();
            BeanUtils.copyProperties(schoolTeacherOvertime,teacherOvertimeVO);
            list.add(teacherOvertimeVO);
        }
        return list;
    }
    /**
     * @author lyric
     * @date 2021-10-11
     * 设置候选组
     */
    public void setCandidateUser(String key,Map<String, Object> variables) {
        List<SysUser> userList = userService.selectUserListByRoleKey(key);
        List<String> userIds = userList.stream().map(o -> o.getUserId().toString()).collect(Collectors.toList());
        String candidateUsers = String.join(",", userIds);
        variables.put(CHARGEUSERIDS, candidateUsers);
    }
    @Override
    //subList手动分页，page为第几页，rows为每页个数
    public  List<TeacherOvertimeVO> subList(List<TeacherOvertimeVO> list, int page, int rows){
        List<TeacherOvertimeVO> listSort  = new ArrayList<>();
        int size=list.size();
        int pageStart=page==1?0:(page-1)*rows;//截取的开始位置
        int pageEnd=size<page*rows?size:page*rows;//截取的结束位置
        if(size>pageStart){
            listSort =list.subList(pageStart, pageEnd);
        }
        return listSort;
    }

    /**
     *
     * @author lyric
     * @date 2022/10/28 10:44
     * @param taskId
     * @param schoolTeacherOvertime
     * 销假
     */
    @Override
    public void cancelLeave(String taskId, SchoolTeacherOvertime schoolTeacherOvertime) {
        //结束任务
        taskService.complete(taskId);
        //修改实际开始时间,实际结束时间
        schoolTeacherOvertimeMapper.updateById(schoolTeacherOvertime);
    }
}
