package yangtz.cs.liu.campus.controller.student;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.core.utils.HolidayDateUtil;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysUserService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.persistence.entity.TaskEntityImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import yangtz.cs.liu.activiti.domain.HistoricActivity;
import yangtz.cs.liu.activiti.service.IProcessService;
import yangtz.cs.liu.campus.domain.schoolClass.SchoolClass;
import yangtz.cs.liu.campus.domain.schoolgrade.SchoolGrade;
import yangtz.cs.liu.campus.domain.student.SchoolStudent;
import yangtz.cs.liu.campus.domain.student.SchoolStudentLeave;
import yangtz.cs.liu.campus.domain.student.SchoolStudentParent;
import yangtz.cs.liu.campus.domain.temp.LeaveResultTemplate;
import yangtz.cs.liu.campus.service.schoolClass.ISchoolClassService;
import yangtz.cs.liu.campus.service.schoolgrade.ISchoolGradeMentorService;
import yangtz.cs.liu.campus.service.schoolgrade.ISchoolGradeService;
import yangtz.cs.liu.campus.service.student.ISchoolStudentLeaveService;
import yangtz.cs.liu.campus.service.student.ISchoolStudentParentService;
import yangtz.cs.liu.campus.service.student.ISchoolStudentService;
import yangtz.cs.liu.campus.service.teacher.ISchoolTeacherService;
import yangtz.cs.liu.campus.util.VxTemlateSendApi;
import yangtz.cs.liu.campus.vo.student.SchoolStudentVO;
import yangtz.cs.liu.campus.vo.student.StudentLeaveVO;
import yangtz.cs.liu.wechat.domain.TemplateInfo;
import yangtz.cs.liu.wechat.domain.template.LeaveStateTemplate;
import yangtz.cs.liu.wechat.domain.template.LeaveTemplate;
import yangtz.cs.liu.wechat.domain.template.StudentLeaveTemplate;
import yangtz.cs.liu.wechat.service.api.IWxApiService;
import yangtz.cs.liu.wechat.utils.DateUtil;

import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.core.constant.ProcessDefinition.*;
import static yangtz.cs.liu.campus.constant.ProcessState.*;
import static yangtz.cs.liu.campus.constant.ProcessState.XIAOJIA;
import static yangtz.cs.liu.campus.constant.SumbitType.SUMBIT;

/**
 * 学生请假Controller
 *
 * @author ruoyi
 * @date 2022-09-27
 */
@RestController
@RequestMapping("/school/studentLeave")
public class SchoolStudentLeaveController extends BaseController {
    @Autowired
    private ISchoolStudentLeaveService schoolStudentLeaveService;

    @Autowired
    private IProcessService processService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private IWxApiService wxApiService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private ISchoolGradeMentorService gradeMentorService;

    @Autowired
    private ISchoolGradeService gradeService;

    @Autowired
    private ISchoolClassService schoolClassService;

    @Autowired
    private ISchoolStudentService schoolStudentService;

    @Autowired
    private ISchoolStudentParentService schoolStudentParentService;

    @Autowired
    private ISchoolTeacherService teacherService;


    /**
     * 学生请假列表
     *
     * @param
     * @return
     */
    @GetMapping("/list")
    public TableDataInfo list(@RequestParam("submitState") String submitState, StudentLeaveVO studentLeave) {
        try {
            startPage();
            studentLeave.setApplyUserId(getUserId());
            List<StudentLeaveVO> list = schoolStudentLeaveService.queryList(submitState, studentLeave);
            return getDataTable(list);
        } catch (Exception e) {
            throw new ServiceException("查询失败");
        }
    }

    /**
     * 新增
     *
     * @param schoolStudentLeave
     * @return
     */
    @PostMapping("/add")
    public AjaxResult add(@RequestBody @Validated SchoolStudentLeave schoolStudentLeave) {
        schoolStudentLeave.setApplyUserId(getUserId());
        schoolStudentLeave.setApplyUser(getUsername());
        return toAjax(schoolStudentLeaveService.save(schoolStudentLeave));
    }

    /**
     * 修改
     *
     * @param schoolStudentLeave
     * @return
     */
    @PutMapping("/edit")
    public AjaxResult edit(@RequestBody @Validated SchoolStudentLeave schoolStudentLeave) {
        if (StringUtils.isNull(schoolStudentLeave.getId())) {
            AjaxResult.error("学生请假id未传");
        }
        return toAjax(schoolStudentLeaveService.updateById(schoolStudentLeave));
    }

    /**
     * 查询详情
     *
     * @param id
     * @return
     */
    @GetMapping("/queryOne/{id}")
    public AjaxResult queryOne(@PathVariable("id") Long id) {
        SchoolStudentLeave studentLeave = schoolStudentLeaveService.getById(id);
        StudentLeaveVO leaveVo = new StudentLeaveVO();
        BeanUtils.copyProperties(studentLeave,leaveVo);
        if (StringUtils.isNotBlank(studentLeave.getInstanceId())) {
            List<Task> taskList = taskService.createTaskQuery()
                    .processInstanceId(studentLeave.getInstanceId())
                    .list();    // 例如请假会签，会同时拥有多个任务
            if (!CollectionUtils.isEmpty(taskList)) {
                TaskEntityImpl task = (TaskEntityImpl) taskList.get(0);
                leaveVo.setTaskId(task.getId());
                if (task.getSuspensionState() == 2) {
                    leaveVo.setTaskName("已挂起");
                    leaveVo.setSuspendState("2");
                } else {
                    leaveVo.setTaskName(task.getName());
                    leaveVo.setSuspendState("1");
                }
            } else {
                // 已办结或者已撤销
                leaveVo.setTaskName("已结束");
            }
        } else {
            leaveVo.setTaskName("未启动");
        }
        return AjaxResult.success(leaveVo);
    }

    /**
     * 删除
     *
     * @param ids
     * @return
     */
    @DeleteMapping("/delete/{ids}")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult delete(@PathVariable("ids") List<Long> ids) {
        return toAjax(schoolStudentLeaveService.removeByIds(ids));
    }

    /**
     * 导出
     *
     * @param ids
     * @return
     */
    @PostMapping("/export/{ids}")
    public void export(HttpServletResponse response, @PathVariable("ids") List<Long> ids) {
        List<SchoolStudentLeave> list = schoolStudentLeaveService.listByIds(ids);
        ExcelUtil<SchoolStudentLeave> util = new ExcelUtil<>(SchoolStudentLeave.class);
        util.exportExcel(response, list, "学生请假");
    }

    //导出全部
    @PostMapping("/export")
    public void exportAll(HttpServletResponse response, SchoolStudentLeave schoolStudentLeave) {
        LambdaQueryWrapper<SchoolStudentLeave> lqw = new LambdaQueryWrapper<>();
        lqw
                .orderByDesc(SchoolStudentLeave::getCreateTime)
        ;
        List<SchoolStudentLeave> list = schoolStudentLeaveService.list(lqw);
        ExcelUtil<SchoolStudentLeave> util = new ExcelUtil<>(SchoolStudentLeave.class);
        util.exportExcel(response, list, "学生请假");
    }

    /**
     * 提交申请
     */
    @PostMapping("/submitApply/{id}")
    public AjaxResult submitApply(@PathVariable("id") Long id) {
        SchoolStudentLeave schoolStudentLeave = schoolStudentLeaveService.getById(id);
//        schoolStudentLeave.setApplyUserId(getUserId());
        schoolStudentLeave.setApplyTime(DateUtils.getNowDate());
        if (StringUtils.isNull(schoolStudentLeave)) {
            throw new ServiceException("提交申请失败,未查询到相关信息");
        }
        String userName = getUsername();
        schoolStudentLeaveService.submitApply(schoolStudentLeave, userName, STUDENTLEAVE, new HashMap<>());

        //转换时间
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Date time = schoolStudentLeave.getApplyTime();
        String applyTime = format.format(time);

        //获取openid
        String openId = userService.getOpenIdByUserId(schoolStudentLeave.getHandUserId());
        Map<String,Object> map = new HashMap<>();
        map.put("toUserOpenId",openId);
        map.put("applyTime",applyTime);
        map.put("remark","请假原因：" + schoolStudentLeave.getLeaveReason());
        map.put("applyUser",schoolStudentLeave.getStudentName());

        Date leaveStartTime = schoolStudentLeave.getStartTime();
        Date leaveEndTime = schoolStudentLeave.getEndTime();
        Double hours = DateUtil.getHoursBetween2Date(leaveStartTime, leaveEndTime);
        String content = "";
        if (hours < 24.0) content = hours + "小时";
        else {
            Integer t1 = (int) (hours / 24);
            Double d2 = hours - 24 * t1;
            if (d2 == 0.0) content = t1 + "天";
            else content = t1 + "天" + d2 + "小时";
        }

        map.put("content",content);
        map.put("first","您有一个待审批的请假事项");
        VxTemlateSendApi.sendVxTemlate(map);

        /** 提交请假模板消息 */
//        LeaveTemplate leaveTemplate = new LeaveTemplate();
//        leaveTemplate.setIdentity(0);
//        leaveTemplate.setToUserOpenId(openId);
//        leaveTemplate.setReasonForLeave(schoolStudentLeave.getLeaveReason());
//        leaveTemplate.setLeaveStartTime(schoolStudentLeave.getStartTime());
//        leaveTemplate.setLeaveEndTime(schoolStudentLeave.getEndTime());
//        leaveTemplate.setUserName(schoolStudentLeave.getStudentName());

        return AjaxResult.success("提交成功");
    }

    /**
     * 待办事项列表
     */
    @GetMapping("/taskList")
    public TableDataInfo taskList(SchoolStudentLeave entity) {
        String userId = getUserId().toString();
        List<StudentLeaveVO> list = schoolStudentLeaveService.findTodoTasks(STUDENTLEAVE, entity, userId);
        //int total = processService.getTodoTotal(STUDENTLEAVE, userId);
        return getTaskTable(list, list.size());
    }

    /**
     * 完成任务
     * 请假小于等于3天，只需要班主任审批，班主任销假
     * 请假大于3 天，需要班主任审批-级部主任审批，班主任销假、
     */
    @PostMapping("/complete/{taskId}/{instanceId}")
    public AjaxResult complete(@PathVariable("taskId") String taskId, @PathVariable("instanceId") String instanceId, @RequestBody Map<String, Object> variables) {

        LambdaQueryWrapper<SchoolStudentLeave> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SchoolStudentLeave::getInstanceId, instanceId);
        SchoolStudentLeave leave = schoolStudentLeaveService.getOne(lqw);
        variables.put("totalTime", leave.getTotalTime());
        processService.completeTask(taskId, instanceId, variables);
        String comment = (String) variables.get("comment");
        Boolean flag = Boolean.parseBoolean(variables.get("pass").toString());
        //Boolean flag = (boolean) variables.get("pass");

        /**判断流程是否结束,如果结束则更新学生请假状态*/
        ProcessInstance rpi = runtimeService
                .createProcessInstanceQuery()//创建流程实例查询对象
                .processInstanceId(instanceId)
                .singleResult();
        if (rpi == null) {
            if (flag) {
                leave.setState(PASS);
            } else {
                leave.setState(REFUSE);
            }
            schoolStudentLeaveService.updateById(leave);

            //获取请假申请人openId
            //String openId = userService.getOpenIdByUserId(parent.getUserId());
            String openId = schoolStudentParentService.getOpenIdById(leave.getApplyUserId());

            Map<String,Object> map = new HashMap<>();
            map.put("toUserOpenId",openId);
            map.put("first","您好，" + leave.getStudentName() + "同学的请假申请已回复");
            map.put("content","已驳回");
            map.put("remark","审批留言： " + comment);
            VxTemlateSendApi.sendVxTemlate(map);

            //正常的话，销假有自己的接口，能进到这一步，一般是班主任或者级部主任驳回了请假申请
//            LeaveResultTemplate resultTemplate = new LeaveResultTemplate();
//            resultTemplate.setFirst("您好，" + leave.getStudentName() + "同学的请假申请已回复");
//            resultTemplate.setResult("已驳回");
//            resultTemplate.setRemark("审批留言： " + comment);
//            SchoolStudentParent parent = schoolStudentParentService.getById(leave.getApplyUserId());
//
//            resultTemplate.setToUserOpenId(openId);
//            List<HistoricActivity> list = processService.selectHistoryList(instanceId, new HistoricActivity());
//            if (StringUtils.isNotNull(list) && list.size() > 0) {
//                HistoricActivity activity = list.get(0);
//                resultTemplate.setAuditTime(activity.getEndTime());
//            }
//            wxApiService.sendLeaveResultTemplate(resultTemplate);
            return AjaxResult.success("审批完成");
        }

        /** 发送申请通知 */

        Map<String,Object> map = new HashMap<>();

//        StudentLeaveTemplate template = new StudentLeaveTemplate();
        String openId = "";
//        template.setType(leave.getType());
//        template.setReasonForLeave(leave.getLeaveReason());
//        template.setStudentName(leave.getStudentName());
//        SchoolStudent ss = schoolStudentService.getById(leave.getStudentId());
//        SchoolClass sc = schoolClassService.getById(ss.getClassId());
//        template.setClassName(sc.getClassAlias());
//        template.setLeaveStartTime(leave.getStartTime());
//        template.setLeaveEndTime(leave.getEndTime());
        //流程没结束，目前已到级部主任或者等待销假
        List<Task> taskList = taskService.createTaskQuery()
                .processInstanceId(leave.getInstanceId())
                .list();    // 例如请假会签，会同时拥有多个任务
        if (!CollectionUtils.isEmpty(taskList)) {
            TaskEntityImpl task = (TaskEntityImpl) taskList.get(0);

            //级部主任审批
            if (JIBU.equals(task.getName())) {
//                template.setFirst("您好，您有请假申请等待审批。");
                map.put("first","您好，您有请假申请等待审批。");
                //openId = userService.getOpenIdByUserId(leave.getHandUserId2());
                openId = teacherService.getOpenIdByUserId(leave.getHandUserId2());
            }
            //等待班主任销假
            if (XIAOJIA.equals(task.getName())) {
//                template.setFirst("您好，您有请假申请等待销假。");
                map.put("first","您好，您有请假申请等待销假。");
                //openId = userService.getOpenIdByUserId(leave.getHandUserId());
                openId = teacherService.getOpenIdByUserId(leave.getHandUserId());
            }
        }
//        template.setToUserOpenId(openId);
//        wxApiService.sendStudentLeaveTemplate(template);

        //申请时间
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Date time = leave.getApplyTime();
        String applyTime = format.format(time);


        map.put("toUserOpenId",openId);
        map.put("applyTime",applyTime);
        map.put("remark","请假原因：" + leave.getLeaveReason());
        map.put("applyUser",leave.getStudentName());
        Date leaveStartTime = leave.getStartTime();
        Date leaveEndTime = leave.getEndTime();
        Double hours = DateUtil.getHoursBetween2Date(leaveStartTime, leaveEndTime);
        String content = "";
        if (hours < 24.0) content = hours + "小时";
        else {
            Integer t1 = (int) (hours / 24);
            Double d2 = hours - 24 * t1;
            if (d2 == 0.0) content = t1 + "天";
            else content = t1 + "天" + d2 + "小时";
        }
        map.put("content",content);
        VxTemlateSendApi.sendVxTemlate(map);
        return AjaxResult.success("审批完成");
    }

    /**
     * @author lyric
     * @date 2022/10/28 10:18
     * 销假
     */
    @PostMapping("/cancelLeave/{taskId}")
    public AjaxResult cancelLeave(@PathVariable("taskId") String taskId, @RequestBody SchoolStudentLeave schoolStudentLeave) {
        schoolStudentLeaveService.cancelLeave(taskId, schoolStudentLeave);
        return AjaxResult.success();
    }

    /**
     * 班主任销假
     * 需要传入返校日期revokeTime
     * 正在用
     */
    @PostMapping("/cancel/{taskId}/{instanceId}")
    public AjaxResult cancel(@PathVariable("taskId") String taskId, @PathVariable("instanceId") String instanceId, @RequestBody SchoolStudentLeave schoolStudentLeave) {
        if (StringUtils.isNull(schoolStudentLeave.getRevokeTime())) {
            throw new ServiceException("销假时间为空");
        }
        schoolStudentLeaveService.cancel(taskId, instanceId, schoolStudentLeave);
        LambdaQueryWrapper<SchoolStudentLeave> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SchoolStudentLeave::getInstanceId, instanceId);
        SchoolStudentLeave leave = schoolStudentLeaveService.getOne(lqw);

        //获取请假申请人openId
        //String openId = userService.getOpenIdByUserId(parent.getUserId());
        String openId = schoolStudentParentService.getOpenIdById(leave.getApplyUserId());

        Map<String,Object> map = new HashMap<>();
        map.put("toUserOpenId",openId);
        map.put("remark",leave.getStudentName() + "同学已返校");
        map.put("content","已销假");
        map.put("first","您好，" + leave.getStudentName() + "同学的销假申请已回复");
        VxTemlateSendApi.sendVxTemlate(map);

//        LeaveResultTemplate resultTemplate = new LeaveResultTemplate();
//        resultTemplate.setFirst("您好，" + leave.getStudentName() + "同学的销假申请已回复");
//        resultTemplate.setResult("已销假");
//        resultTemplate.setRemark(leave.getStudentName() + "同学已返校");
//        SchoolStudentParent parent = schoolStudentParentService.getById(leave.getApplyUserId());
//
//        resultTemplate.setToUserOpenId(openId);
//        List<HistoricActivity> list = processService.selectHistoryList(instanceId, new HistoricActivity());
//        if (StringUtils.isNotNull(list) && list.size() > 0) {
//            HistoricActivity activity = list.get(0);
//            resultTemplate.setAuditTime(activity.getEndTime());
//        }
//        wxApiService.sendLeaveResultTemplate(resultTemplate);
        return AjaxResult.success("销假完成");
    }

    /**
     * 我的已办列表
     */
    @GetMapping("/taskDoneList")
    public TableDataInfo taskDoneList(SchoolStudentLeave entity) {
        String userId = getUserId().toString();
        List<StudentLeaveVO> list = schoolStudentLeaveService.findDoneTasks(STUDENTLEAVE, entity, getUserId().toString());
        int total = processService.getDoneTotal(STUDENTLEAVE, userId);
        return getTaskTable(list, total);
    }

    /**
     * 班主任工作-学生请假查看
     */
    @GetMapping("/classList")
    public TableDataInfo classList(SchoolStudentLeave entity) {
        String userId = getUserId().toString();
        List<StudentLeaveVO> list = schoolStudentLeaveService.findHeaderTasks(STUDENTLEAVE, entity, userId);
        return getDataTable(list);
    }

    /**
     * 级部工作-学生请假查看
     */
    @GetMapping("/gradeList")
    public TableDataInfo gradeList(SchoolStudentLeave entity) {
        //获取当前学年
        /*int schoolYear = HolidayDateUtil.getSchoolYear();
        List<SchoolGrade> gradeIds = gradeMentorService.selectGrades(getUserId(),schoolYear);
        if(StringUtils.isNull(gradeIds) || gradeIds.size() == 0){
            throw new ServiceException("非级部成员，无法查看");
        }*/
        List<SchoolGrade> gradeIds = gradeMentorService.selectGradeList(getUserId());
        if (StringUtils.isNull(gradeIds) || gradeIds.size() == 0) {
            //若管理员此时不是级部成员，则查出所有级部
            if (1L == getUserId()) {
                LambdaQueryWrapper<SchoolGrade> lqw = new LambdaQueryWrapper<>();
                lqw.orderByAsc(SchoolGrade::getGradeValue);
                gradeIds = gradeService.list(lqw);
                if (StringUtils.isNull(gradeIds) || gradeIds.size() == 0) {
                    throw new ServiceException("暂无级部信息，查询不出级部下的任何信息");
                }
            } else {
                throw new ServiceException("您不在任何级部工作，无法查看级部下的任何信息");
            }
        }
        //获取级部id并排重
        List<Long> idList = gradeIds.stream().map(SchoolGrade::getId).distinct().collect(Collectors.toList());
        List<SchoolClass> schoolClassList = schoolClassService.getClassList(idList, new SchoolClass());
        if (StringUtils.isNull(schoolClassList) || schoolClassList.size() == 0) {
            return getDataTable(new ArrayList<>());
        }
        //获取班级id并排重
        List<Long> classIdList = schoolClassList.stream().map(SchoolClass::getId).distinct().collect(Collectors.toList());
        List<SchoolStudentVO> studentVOList = schoolStudentService.getGradeStudent(classIdList, new SchoolStudentVO());
        if (StringUtils.isNull(studentVOList) || studentVOList.size() == 0) {
            return getDataTable(new ArrayList<>());
        }
        //获取学生id并排重
        List<Long> studentIdList = studentVOList.stream().map(SchoolStudentVO::getId).distinct().collect(Collectors.toList());
        List<SchoolStudentLeave> list = schoolStudentLeaveService.gradeList(studentIdList, entity);
        return getDataTable(list);
    }


    /**
     * 获取最新学年值
     */
    public int getNewYear() {
        Calendar cal = Calendar.getInstance();
        //获取当前年月
        int nowYear = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1;
        //设置当前学期
        int term = 1;
        //2-7为第二学期，8-1为第一学期
        //如果当前月份小于8月，则该学年应为当前年-1 到 当前年,例如当前年月为2023年7月，则该学年为2022-2023年的第二学期
        if (month < 8) {
            nowYear = nowYear - 1;
        }
        if (month >= 2 && month < 8) {
            term = 2;
        }
        return nowYear;
    }

    //教师工作-学生请假查看
    @GetMapping("/teacherClassList")
    public TableDataInfo teacherClassList(SchoolStudentLeave entity) {
        //获取教师所在班级id
        List<Long> classIdList = schoolClassService.getTeacherClasses(getUserId());
        if (StringUtils.isNull(classIdList) || classIdList.size() == 0) {
            return getDataTable(new ArrayList<>());
        }
        List<SchoolStudentVO> studentVOList = schoolStudentService.getGradeStudent(classIdList, new SchoolStudentVO());
        if (StringUtils.isNull(studentVOList) || studentVOList.size() == 0) {
            return getDataTable(new ArrayList<>());
        }
        //获取学生id并排重
        List<Long> studentIdList = studentVOList.stream().map(SchoolStudentVO::getId).distinct().collect(Collectors.toList());
        List<SchoolStudentLeave> list = schoolStudentLeaveService.gradeList(studentIdList, entity);
        return getDataTable(list);
    }
}
