package com.srs.routine.service.impl;

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

import com.srs.common.annotation.DataScope;
import com.srs.common.core.domain.AjaxResult;
import com.srs.common.doman.dto.ProcessResultDto;
import com.srs.common.doman.vo.TeacherVo;
import com.srs.common.enums.ApplicationStatus;
import com.srs.common.enums.LeaveCancellationStatus;
import com.srs.common.enums.OperationResult;
import com.srs.common.enums.OperationType;
import com.srs.common.utils.DateUtils;
import com.srs.common.utils.SecurityUtils;
import com.srs.flowable.service.IFlowDefinitionService;
import com.srs.routine.domain.RtStuLeaveOperationRecords;
import com.srs.routine.domain.dto.LeaveApplicationApprovalDto;
import com.srs.routine.domain.vo.*;
import com.srs.routine.domain.dto.StuLeaveApplicationDto;
import com.srs.routine.mapper.RtStuLeaveOperationRecordsMapper;
import com.srs.system.mapper.SysUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.IdentityService;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import com.srs.routine.mapper.RtStuLeaveApplicationMapper;
import com.srs.routine.domain.RtStuLeaveApplication;
import com.srs.routine.service.IRtStuLeaveApplicationService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 学生请假申请Service业务层处理
 *
 * @author LSD
 * @date 2024-03-30
 */
@Service
@Slf4j
public class RtStuLeaveApplicationServiceImpl extends ServiceImpl<RtStuLeaveApplicationMapper, RtStuLeaveApplication> implements IRtStuLeaveApplicationService {
    @Autowired
    private RtStuLeaveApplicationMapper rtStuLeaveApplicationMapper;

    @Autowired
    private RtStuLeaveOperationRecordsMapper rtStuLeaveOperationRecordsMapper;

    @Autowired
    SysUserMapper sysUserMapper;

    /**
     * 查询学生请假申请
     *
     * @param leaveApplicationId 学生请假申请主键
     * @return 学生请假申请
     */
    @Override
    public RtStuLeaveApplication selectRtStuLeaveApplicationByLeaveApplicationId(Long leaveApplicationId) {
        return rtStuLeaveApplicationMapper.selectRtStuLeaveApplicationByLeaveApplicationId(leaveApplicationId);
    }

    /**
     * 查询学生请假申请列表
     *
     * @param rtStuLeaveApplication 学生请假申请
     * @return 学生请假申请
     */
    @Override
    public List<RtStuLeaveApplication> selectRtStuLeaveApplicationList(RtStuLeaveApplication rtStuLeaveApplication) {
        return rtStuLeaveApplicationMapper.selectRtStuLeaveApplicationList(rtStuLeaveApplication);
    }

    /**
     * 查询学生请假申请列表
     *
     * @param dto 学生请假申请
     * @return 学生请假申请
     */
    @Override
    public List<StuLeaveApplicationVo> getRtStuLeaveApplicationListDto(StuLeaveApplicationDto dto) {
        return rtStuLeaveApplicationMapper.selectRtStuLeaveApplicationListByDto(dto);
    }

    @Override
    @DataScope(userAlias = "u")
    public List<StuLeaveApplicationVo> getRtStuLeaveApplicationListVo(StuLeaveApplicationDto dto) {
        return rtStuLeaveApplicationMapper.selectRtStuLeaveApplicationListVo(dto);
    }

    /**
     * 新增学生请假申请
     *
     * @param rtStuLeaveApplication 学生请假申请
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertRtStuLeaveApplication(RtStuLeaveApplication rtStuLeaveApplication) {
        rtStuLeaveApplication.setCreateBy(SecurityUtils.getUsername());
        rtStuLeaveApplication.setCreateTime(DateUtils.getNowDate());

        int i = rtStuLeaveApplicationMapper.insertRtStuLeaveApplication(rtStuLeaveApplication);

        if (rtStuLeaveApplication.getLeaveStatus() != null && rtStuLeaveApplication.getLeaveStatus().equals("1")) {

            ProcessResultDto processResultDto = startLeaveProcess(rtStuLeaveApplication);

            if (processResultDto!=null) {
                rtStuLeaveApplication.setProcessInstanceId(processResultDto.getProcessInstanceId());
                rtStuLeaveApplication.setDeployId(processResultDto.getDeploymentId());
                rtStuLeaveApplicationMapper.updateRtStuLeaveApplication(rtStuLeaveApplication);
            }
        }

        return i;
    }

    /**
     * 修改学生请假申请
     *
     * @param rtStuLeaveApplication 学生请假申请
     * @return 结果
     */
    @Override
    public int updateRtStuLeaveApplication(RtStuLeaveApplication rtStuLeaveApplication) {
        rtStuLeaveApplication.setUpdateTime(DateUtils.getNowDate());
        rtStuLeaveApplication.setUpdateBy(SecurityUtils.getUsername());

        if (rtStuLeaveApplication.getLeaveStatus() != null && rtStuLeaveApplication.getLeaveStatus().equals("1")) {

            ProcessResultDto processResultDto = startLeaveProcess(rtStuLeaveApplication);

            if (processResultDto!=null) {
                rtStuLeaveApplication.setProcessInstanceId(processResultDto.getProcessInstanceId());
                rtStuLeaveApplication.setDeployId(processResultDto.getDeploymentId());
            }
        }
        return rtStuLeaveApplicationMapper.updateRtStuLeaveApplication(rtStuLeaveApplication);

    }

    @Override
    public int editRtStuLeaveApplication(RtStuLeaveApplication rtStuLeaveApplication) {
        rtStuLeaveApplication.setUpdateTime(DateUtils.getNowDate());
        rtStuLeaveApplication.setUpdateBy(SecurityUtils.getUsername());
        return rtStuLeaveApplicationMapper.updateRtStuLeaveApplication(rtStuLeaveApplication);
    }


    @Autowired
    IFlowDefinitionService flowDefinitionService;

    @Autowired
    TaskService taskService;

    @Autowired
    IdentityService identityService;

    /**
     * 开启请假工作流
     *
     * @param rtStuLeaveApplication
     */
    private ProcessResultDto startLeaveProcess(RtStuLeaveApplication rtStuLeaveApplication) {

        Map<String, Object> variables = new HashMap<>();
        variables.put("leaveApplicationId", rtStuLeaveApplication.getLeaveApplicationId().toString());
        variables.put("leaveDays", rtStuLeaveApplication.getLeaveDays());
        variables.put("stuId", rtStuLeaveApplication.getStuId());
        TeacherVo counselorInfo = rtStuLeaveApplicationMapper.getCounselorInfo(rtStuLeaveApplication.getStuId());
        // 把辅导员的userId放到approval中
        variables.put("approval", counselorInfo.getUserId());
        variables.put("deptId", counselorInfo.getDeptId());

        //flow_m4npextk:28:257686 flow_m4npextk:31:755004
        AjaxResult ajaxResult = flowDefinitionService.startProcessInstanceById("flow_m4npextk:32:975062", variables);
        String code = ajaxResult.get("code").toString();
        if (code.equals("200")) {

            log.info("流程启动成功");

            Object obj = ajaxResult.get("data");
            ProcessResultDto dto = (ProcessResultDto) obj;

            // 操作工作流
            // 设置当前用户
            identityService.setAuthenticatedUserId(SecurityUtils.getUserId().toString());
            // 查询待办任务列表
            List<Task> tasks = taskService.createTaskQuery()
                    .processInstanceId(dto.getProcessInstanceId())
                    .taskAssignee(SecurityUtils.getUserId().toString())
                    .active()
                    .list();
            // 保存审核结果到任务变量中
            variables.put("approved", true);
            // 完成待办任务列表
            for (Task task : tasks) {
                String taskId = task.getId();
                String leaveId = taskService.getVariable(taskId, "leaveApplicationId").toString();
                if (leaveId.equals(rtStuLeaveApplication.getLeaveApplicationId().toString())) {
                    taskService.complete(task.getId(), variables);
                }
            }

            // todo 企业微信推送消息


            return dto;
        } else {
            return null;
        }
    }

    /**
     * 批量删除学生请假申请
     *
     * @param leaveApplicationIds 需要删除的学生请假申请主键
     * @return 结果
     */
    @Override
    public int deleteRtStuLeaveApplicationByLeaveApplicationIds(Long[] leaveApplicationIds) {
        return rtStuLeaveApplicationMapper.deleteRtStuLeaveApplicationByLeaveApplicationIds(leaveApplicationIds);
    }

    /**
     * 删除学生请假申请信息
     *
     * @param leaveApplicationId 学生请假申请主键
     * @return 结果
     */
    @Override
    public int deleteRtStuLeaveApplicationByLeaveApplicationId(Long leaveApplicationId) {
        return rtStuLeaveApplicationMapper.deleteRtStuLeaveApplicationByLeaveApplicationId(leaveApplicationId);
    }

    @Override
    public StuLeaveApplicationDetailsVo selectRtStuLeaveApplicationDetailsByLeaveApplicationId(Long leaveApplicationId) {
        StuLeaveApplicationDetailsVo stuLeaveApplicationDetailsVo = rtStuLeaveApplicationMapper.selectRtStuLeaveApplicationDetailsByLeaveApplicationId(leaveApplicationId);
        return stuLeaveApplicationDetailsVo;
    }

    @Override
    public StuInfoReturnVo getStuInfo(String stuNo) {
        if (stuNo == null || stuNo.equals("") || "null".equals(stuNo)) {
            return null;
        }
        StuInfoReturnVo stuInfoReturnVo = rtStuLeaveApplicationMapper.selectStuInfoReturn(stuNo);
        if (stuInfoReturnVo != null) {
            return stuInfoReturnVo;
        } else {
            return null;
        }
    }

    @Override
    public int approval(LeaveApplicationApprovalDto dto) {
        RtStuLeaveApplication rtStuLeaveApplication = rtStuLeaveApplicationMapper.selectRtStuLeaveApplicationByLeaveApplicationId(dto.getLeaveApplicationId());
        if (rtStuLeaveApplication != null) {
            rtStuLeaveApplication.setStatus(ApplicationStatus.APPROVED.getCode());
            rtStuLeaveApplication.setUpdateBy(SecurityUtils.getUsername());
            rtStuLeaveApplication.setUpdateTime(DateUtils.getNowDate());
            rtStuLeaveApplicationMapper.updateRtStuLeaveApplication(rtStuLeaveApplication);

            RtStuLeaveOperationRecords records = new RtStuLeaveOperationRecords();
            records.setLeaveApplicationId(rtStuLeaveApplication.getLeaveApplicationId());
            records.setOperationType(OperationType.TUTOR_APPROVAL.getCode());
            records.setOperationResult(OperationResult.SUCCESS.getCode());
            records.setSignature(dto.getSignature());
            records.setSignatureDate(dto.getSignatureDate());
            records.setComments(dto.getComments());
            records.setCreateBy(SecurityUtils.getUsername());
            records.setCreateTime(DateUtils.getNowDate());

            return rtStuLeaveOperationRecordsMapper.insert(records);
        }
        return 0;

    }

    @Override
    public int refuse(LeaveApplicationApprovalDto dto) {
        RtStuLeaveApplication rtStuLeaveApplication = rtStuLeaveApplicationMapper.selectRtStuLeaveApplicationByLeaveApplicationId(dto.getLeaveApplicationId());
        if (rtStuLeaveApplication != null) {
            rtStuLeaveApplication.setStatus(ApplicationStatus.DISAGREED.getCode());
            rtStuLeaveApplication.setCounselorComments(dto.getComments());
            rtStuLeaveApplication.setUpdateBy(SecurityUtils.getUsername());
            rtStuLeaveApplication.setUpdateTime(DateUtils.getNowDate());

            int i = rtStuLeaveApplicationMapper.updateRtStuLeaveApplication(rtStuLeaveApplication);
            if (i > 0) {
                RtStuLeaveOperationRecords records = new RtStuLeaveOperationRecords();
                records.setLeaveApplicationId(rtStuLeaveApplication.getLeaveApplicationId());
                records.setOperationType(OperationType.TUTOR_APPROVAL.getCode());
                records.setOperationResult(OperationResult.FAILURE.getCode());
                records.setSignature(dto.getSignature());
                records.setSignatureDate(DateUtils.getNowDate());
                records.setComments(dto.getComments());
                records.setCreateBy(SecurityUtils.getUsername());
                records.setCreateTime(DateUtils.getNowDate());

                i += rtStuLeaveOperationRecordsMapper.insert(records);
            }
            return i;
        }
        return 0;
    }

    @Override
    public int reject(LeaveApplicationApprovalDto dto) {
        RtStuLeaveApplication rtStuLeaveApplication = rtStuLeaveApplicationMapper.selectRtStuLeaveApplicationByLeaveApplicationId(dto.getLeaveApplicationId());
        if (rtStuLeaveApplication != null) {
            rtStuLeaveApplication.setStatus(ApplicationStatus.REJECTED.getCode());
            rtStuLeaveApplication.setCounselorComments(dto.getComments());
            rtStuLeaveApplication.setUpdateBy(SecurityUtils.getUsername());
            rtStuLeaveApplication.setUpdateTime(DateUtils.getNowDate());

            int i = rtStuLeaveApplicationMapper.updateRtStuLeaveApplication(rtStuLeaveApplication);
            if (i > 0) {
                RtStuLeaveOperationRecords records = new RtStuLeaveOperationRecords();
                records.setLeaveApplicationId(rtStuLeaveApplication.getLeaveApplicationId());
                records.setOperationType(OperationType.TUTOR_APPROVAL.getCode());
                records.setOperationResult(OperationResult.REJECT.getCode());
                records.setSignature(dto.getSignature());
                records.setSignatureDate(DateUtils.getNowDate());
                records.setComments(dto.getComments());
                records.setCreateBy(SecurityUtils.getUsername());
                records.setCreateTime(DateUtils.getNowDate());

                i += rtStuLeaveOperationRecordsMapper.insert(records);
            }
            return i;
        }
        return 0;
    }

    @Override
    public int cancellation(LeaveApplicationApprovalDto dto) {
        RtStuLeaveApplication rtStuLeaveApplication = rtStuLeaveApplicationMapper.selectRtStuLeaveApplicationByLeaveApplicationId(dto.getLeaveApplicationId());
        if (rtStuLeaveApplication != null) {
            rtStuLeaveApplication.setCancellation(LeaveCancellationStatus.CANCEL_REQUESTED.getCode());
            rtStuLeaveApplication.setCounselorComments(dto.getComments());
            rtStuLeaveApplication.setUpdateBy(SecurityUtils.getUsername());
            rtStuLeaveApplication.setUpdateTime(DateUtils.getNowDate());

            int i = rtStuLeaveApplicationMapper.updateRtStuLeaveApplication(rtStuLeaveApplication);
            if (i > 0) {
                RtStuLeaveOperationRecords records = new RtStuLeaveOperationRecords();
                records.setLeaveApplicationId(rtStuLeaveApplication.getLeaveApplicationId());
                records.setOperationType(OperationType.STUDENT_LEAVE_CANCEL_REQUEST.getCode());
                records.setOperationResult(OperationResult.SUCCESS.getCode());
                records.setSignature(dto.getSignature());
                records.setSignatureDate(DateUtils.getNowDate());
                records.setComments(dto.getComments());
                records.setCreateBy(SecurityUtils.getUsername());
                records.setCreateTime(DateUtils.getNowDate());

                i += rtStuLeaveOperationRecordsMapper.insertRtStuLeaveOperationRecords(records);
            }
            return i;
        }

        return 0;
    }

    @Override
    public int verify(LeaveApplicationApprovalDto dto) {
        RtStuLeaveApplication rtStuLeaveApplication = rtStuLeaveApplicationMapper.selectRtStuLeaveApplicationByLeaveApplicationId(dto.getLeaveApplicationId());

        if (rtStuLeaveApplication != null) {
            rtStuLeaveApplication.setCancellation(LeaveCancellationStatus.CANCELED.getCode());
            rtStuLeaveApplication.setCounselorComments(dto.getComments());
            rtStuLeaveApplication.setUpdateBy(SecurityUtils.getUsername());
            rtStuLeaveApplication.setUpdateTime(DateUtils.getNowDate());

            int i = rtStuLeaveApplicationMapper.updateRtStuLeaveApplication(rtStuLeaveApplication);
            if (i > 0) {
                RtStuLeaveOperationRecords records = new RtStuLeaveOperationRecords();
                records.setLeaveApplicationId(rtStuLeaveApplication.getLeaveApplicationId());
                records.setOperationType(OperationType.TUTOR_LEAVE_CANCEL_VERIFICATION.getCode());
                records.setOperationResult(OperationResult.SUCCESS.getCode());
                records.setSignature(dto.getSignature());
                records.setSignatureDate(DateUtils.getNowDate());
                records.setComments(dto.getComments());
                records.setCreateBy(SecurityUtils.getUsername());
                records.setCreateTime(DateUtils.getNowDate());

                i += rtStuLeaveOperationRecordsMapper.insertRtStuLeaveOperationRecords(records);

                RtStuLeaveOperationRecords records1 = new RtStuLeaveOperationRecords();
                records1.setLeaveApplicationId(rtStuLeaveApplication.getLeaveApplicationId());
                records1.setOperationType(OperationType.END.getCode());
                records1.setOperationResult(OperationResult.SUCCESS.getCode());
                records1.setCreateBy(SecurityUtils.getUsername());
                records1.setCreateTime(DateUtils.getNowDate());

                i += rtStuLeaveOperationRecordsMapper.insertRtStuLeaveOperationRecords(records1);

            }
            return i;
        }
        return 0;
    }

    @Override
    public int verifyDisagree(LeaveApplicationApprovalDto dto) {
        RtStuLeaveApplication rtStuLeaveApplication = rtStuLeaveApplicationMapper.selectRtStuLeaveApplicationByLeaveApplicationId(dto.getLeaveApplicationId());

        if (rtStuLeaveApplication != null) {
            rtStuLeaveApplication.setCounselorComments(dto.getComments());
            rtStuLeaveApplication.setUpdateBy(SecurityUtils.getUsername());
            rtStuLeaveApplication.setUpdateTime(DateUtils.getNowDate());

            int i = rtStuLeaveApplicationMapper.updateRtStuLeaveApplication(rtStuLeaveApplication);
            if (i > 0) {
                RtStuLeaveOperationRecords records = new RtStuLeaveOperationRecords();
                records.setLeaveApplicationId(rtStuLeaveApplication.getLeaveApplicationId());
                records.setOperationType(OperationType.TUTOR_LEAVE_CANCEL_VERIFICATION.getCode());
                records.setOperationResult(OperationResult.FAILURE.getCode());
                records.setSignature(dto.getSignature());
                records.setSignatureDate(DateUtils.getNowDate());
                records.setComments(dto.getComments());
                records.setCreateBy(SecurityUtils.getUsername());
                records.setCreateTime(DateUtils.getNowDate());

                i += rtStuLeaveOperationRecordsMapper.insertRtStuLeaveOperationRecords(records);
            }
            return i;
        }
        return 0;
    }

    @Override
    public StuLeaveApplicationDetailsVo getLeaveApplicationByProcInsId(String procInsId) {
        return rtStuLeaveApplicationMapper.selectLeaveApplicationByProcInsId(procInsId);
    }

    @Override
    public List<ClassStuLeaveDataStatistics> selectClassLeaveNumber(String tNo) {
        return rtStuLeaveApplicationMapper.selectClassLeaveNumber(tNo);
    }

    @Override
    public List<StuLeaveApplicationVo> getRtStuLeaveApplicationListByXW(StuLeaveApplicationDto rtStuLeaveApplication) {
        return rtStuLeaveApplicationMapper.getRtStuLeaveApplicationListByXW(rtStuLeaveApplication);
    }
}
