package com.srs.routine.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.srs.common.core.domain.AjaxResult;
import com.srs.common.core.domain.entity.SysUser;
import com.srs.common.doman.dto.ProcessResultDto;
import com.srs.common.exception.ServiceException;
import com.srs.common.utils.DateUtils;
import com.srs.common.utils.SecurityUtils;
import com.srs.flowable.service.IFlowDefinitionService;
import com.srs.routine.domain.RtStuDisciplinaryApplication;
import com.srs.routine.domain.vo.ClassStuDisciplinaryDataStatistics;
import com.srs.routine.domain.vo.StuDisciplinaryPenaltyNumber;
import com.srs.routine.mapper.RtStuDisciplinaryApplicationMapper;
import com.srs.routine.service.IRtStuDisciplinaryApplicationService;
import com.srs.system.service.ISysUserService;
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 org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 学生处分申请Service业务层处理
 *
 * @author LSD
 * @date 2024-04-17
 */
@Service
@Slf4j
public class RtStuDisciplinaryApplicationServiceImpl extends ServiceImpl<RtStuDisciplinaryApplicationMapper, RtStuDisciplinaryApplication> implements IRtStuDisciplinaryApplicationService {
    @Autowired
    private RtStuDisciplinaryApplicationMapper rtStuDisciplinaryApplicationMapper;

    @Autowired
    ISysUserService sysUserService;

    /**
     * 查询学生处分申请
     *
     * @param applicationId 学生处分申请主键
     * @return 学生处分申请
     */
    @Override
    public RtStuDisciplinaryApplication selectRtStuDisciplinaryApplicationByApplicationId(Long applicationId) {
        return rtStuDisciplinaryApplicationMapper.selectRtStuDisciplinaryApplicationByApplicationId(applicationId);
    }

    /**
     * 查询学生处分申请列表
     *
     * @param rtStuDisciplinaryApplication 学生处分申请
     * @return 学生处分申请
     */
    @Override
    public List<RtStuDisciplinaryApplication> selectRtStuDisciplinaryApplicationList(RtStuDisciplinaryApplication rtStuDisciplinaryApplication) {
        return rtStuDisciplinaryApplicationMapper.selectRtStuDisciplinaryApplicationList(rtStuDisciplinaryApplication);
    }

    /**
     * 新增学生处分申请
     *
     * @param rtStuDisciplinaryApplication 学生处分申请
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertRtStuDisciplinaryApplication(RtStuDisciplinaryApplication rtStuDisciplinaryApplication) {

        rtStuDisciplinaryApplication.setCreateTime(DateUtils.getNowDate());

        rtStuDisciplinaryApplication.setApplicantName(SecurityUtils.getLoginUser().getUser().getNickName());

        rtStuDisciplinaryApplication.setApplicantId(SecurityUtils.getUserId());


        // 获取该学生在user表的id
        SysUser sysUser = sysUserService.selectUserByUserName(rtStuDisciplinaryApplication.getStuNo());
        if (sysUser == null) {
            throw new ServiceException("该学生不存在", 500);
        }
        rtStuDisciplinaryApplication.setStuId(sysUser.getUserId());
        rtStuDisciplinaryApplication.setStuName(sysUser.getNickName());

        int i = rtStuDisciplinaryApplicationMapper.insertRtStuDisciplinaryApplication(rtStuDisciplinaryApplication);

        if (rtStuDisciplinaryApplication.getSubmissionStatus() != null && rtStuDisciplinaryApplication.getSubmissionStatus() == 1) {

            // 开启工作流
            ProcessResultDto processResultDto = startLeaveProcess(rtStuDisciplinaryApplication);

            if (processResultDto != null) {
                rtStuDisciplinaryApplication.setProcessInstanceId(processResultDto.getProcessInstanceId());
                rtStuDisciplinaryApplication.setDeployId(processResultDto.getDeploymentId());
            }
            return rtStuDisciplinaryApplicationMapper.updateRtStuDisciplinaryApplication(rtStuDisciplinaryApplication);
        }
        return i;
    }

    /**
     * 计算违纪到期时间
     *
     * @param penaltyType   违纪等级
     * @param violationDate 处分时间
     * @return
     */
    private Date calculationDueDisposition(Long penaltyType, Date violationDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(violationDate);

        // 根据处分等级设置处分到期时间
        switch (penaltyType.intValue()) {
            case 0: // 警告
            case 1: // 严重警告
                calendar.add(Calendar.MONTH, 6); // 6个月后
                break;
            case 2: // 记过
                calendar.add(Calendar.MONTH, 9); // 9个月后
                break;
            case 3: // 留校察看
                calendar.add(Calendar.YEAR, 1); // 1年后
                break;
            default:
                // 处理未知的处分等级
                break;
        }

        return calendar.getTime();
    }

    /**
     * 修改学生处分申请
     *
     * @param rtStuDisciplinaryApplication 学生处分申请
     * @return 结果
     */
    @Override
    public int updateRtStuDisciplinaryApplication(RtStuDisciplinaryApplication rtStuDisciplinaryApplication) {

        rtStuDisciplinaryApplication.setUpdateTime(DateUtils.getNowDate());
        rtStuDisciplinaryApplication.setUpdateBy(SecurityUtils.getUsername());

        //if (rtStuDisciplinaryApplication.getViolationDate() != null) {
            // 设置 处分到期时间
            //rtStuDisciplinaryApplication.setExpirationDate(calculationDueDisposition(rtStuDisciplinaryApplication.getPenaltyType(), rtStuDisciplinaryApplication.getViolationDate()));
            rtStuDisciplinaryApplication.setExpirationDate(calculationDueDisposition(rtStuDisciplinaryApplication.getPenaltyType(), rtStuDisciplinaryApplication.getDisciplinaryDate()));
       // }

        if (rtStuDisciplinaryApplication.getSubmissionStatus() != null && rtStuDisciplinaryApplication.getSubmissionStatus() == 1) {

            // 开启工作流
            ProcessResultDto processResultDto = startLeaveProcess(rtStuDisciplinaryApplication);
            if (processResultDto != null) {
                rtStuDisciplinaryApplication.setProcessInstanceId(processResultDto.getProcessInstanceId());
                rtStuDisciplinaryApplication.setDeployId(processResultDto.getDeploymentId());
            }
        }
        return rtStuDisciplinaryApplicationMapper.updateRtStuDisciplinaryApplication(rtStuDisciplinaryApplication);
    }

    @Override
    public int editRtStuDisciplinaryApplication(RtStuDisciplinaryApplication rtStuDisciplinaryApplication) {
        rtStuDisciplinaryApplication.setUpdateTime(DateUtils.getNowDate());
        rtStuDisciplinaryApplication.setUpdateBy(SecurityUtils.getUsername());
        //if (rtStuDisciplinaryApplication.getViolationDate() != null) {
            // 设置 处分到期时间
            //rtStuDisciplinaryApplication.setExpirationDate(calculationDueDisposition(rtStuDisciplinaryApplication.getPenaltyType(), rtStuDisciplinaryApplication.getViolationDate()));
            rtStuDisciplinaryApplication.setExpirationDate(calculationDueDisposition(rtStuDisciplinaryApplication.getPenaltyType(), rtStuDisciplinaryApplication.getDisciplinaryDate()));
       // }
        return rtStuDisciplinaryApplicationMapper.updateRtStuDisciplinaryApplication(rtStuDisciplinaryApplication);
    }

    /**
     * 批量删除学生处分申请
     *
     * @param applicationIds 需要删除的学生处分申请主键
     * @return 结果
     */
    @Override
    public int deleteRtStuDisciplinaryApplicationByApplicationIds(Long[] applicationIds) {
        return rtStuDisciplinaryApplicationMapper.deleteRtStuDisciplinaryApplicationByApplicationIds(applicationIds);
    }

    /**
     * 删除学生处分申请信息
     *
     * @param applicationId 学生处分申请主键
     * @return 结果
     */
    @Override
    public int deleteRtStuDisciplinaryApplicationByApplicationId(Long applicationId) {
        return rtStuDisciplinaryApplicationMapper.deleteRtStuDisciplinaryApplicationByApplicationId(applicationId);
    }

    @Override
    public RtStuDisciplinaryApplication getDisciplinaryApplicationByProcInsId(String procInsId) {
        RtStuDisciplinaryApplication rtStuDisciplinaryApplication = rtStuDisciplinaryApplicationMapper.selectDisciplinaryApplicationByProcInsId(procInsId);
        return rtStuDisciplinaryApplication;
    }

    @Override
    public List<ClassStuDisciplinaryDataStatistics> getClassDisciplinaryNumber() {
        return rtStuDisciplinaryApplicationMapper.selectClassDisciplinaryNumber(SecurityUtils.getUsername());
    }

    @Override
    public Boolean selectRtStuDisciplinaryApplicationByStuNo(String stuNo) {
        RtStuDisciplinaryApplication rtStuDisciplinaryApplication = rtStuDisciplinaryApplicationMapper.selectRtStuDisciplinaryApplicationByStuNo(stuNo);
        if (rtStuDisciplinaryApplication != null) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public StuDisciplinaryPenaltyNumber getStuDisciplinaryApplicationByPenaltyNumber(Long penaltyNumber) {
        StuDisciplinaryPenaltyNumber stuDisciplinaryPenaltyNumber = rtStuDisciplinaryApplicationMapper.selectStuDisciplinaryApplicationByPenaltyNumber(penaltyNumber);
        if (stuDisciplinaryPenaltyNumber != null){
            return stuDisciplinaryPenaltyNumber;
        }else{
            throw new ServiceException("未找到相关处分文号信息");
        }
    }

    @Override
    public List<RtStuDisciplinaryApplication> getRtStuDisciplinaryApplicationListByStuNo(RtStuDisciplinaryApplication rtStuDisciplinaryApplication) {
        rtStuDisciplinaryApplication.setStuNo(SecurityUtils.getUsername());
        return rtStuDisciplinaryApplicationMapper.selectRtStuDisciplinaryApplicationList(rtStuDisciplinaryApplication);
    }

    @Override
    public List<RtStuDisciplinaryApplication> selectRtStuDisciplinaryApplicationListByXW(RtStuDisciplinaryApplication rtStuDisciplinaryApplication) {
        return rtStuDisciplinaryApplicationMapper.selectRtStuDisciplinaryApplicationListXW(rtStuDisciplinaryApplication);
    }

    @Autowired
    IFlowDefinitionService flowDefinitionService;

    @Autowired
    TaskService taskService;

    @Autowired
    IdentityService identityService;

    /**
     * 开启处分工作流
     *
     * @param rtStuDisciplinaryApplication
     */
    private ProcessResultDto startLeaveProcess(RtStuDisciplinaryApplication rtStuDisciplinaryApplication) {

        Map<String, Object> variables = new HashMap<>();
        variables.put("applicationId", rtStuDisciplinaryApplication.getApplicationId().toString());
        variables.put("penaltyType", rtStuDisciplinaryApplication.getPenaltyType());
        variables.put("stuId", rtStuDisciplinaryApplication.getStuId());
        // 把辅导员的userId放到approval中
        variables.put("approval", SecurityUtils.getUserId());
        variables.put("deptId", SecurityUtils.getDeptId());

        // todo 企业微信推送消息

        AjaxResult ajaxResult = flowDefinitionService.startProcessInstanceById("flow_n27gxm4k:7:257682", 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 applicationId = taskService.getVariable(taskId, "applicationId").toString();
                if (applicationId.equals(rtStuDisciplinaryApplication.getApplicationId().toString())) {
                    taskService.complete(task.getId(), variables);
                }
            }

            return dto;
        } else {
            return null;
        }

    }
    @Override
    public  String getviolationDate(String stuNo){
        return  rtStuDisciplinaryApplicationMapper.getviolationDate(stuNo);
    }

}
