package yangtz.cs.liu.wechat.controller.leave;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.core.utils.HolidayDateUtil;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SchoolTeacher;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.util.UserInfoUtil;
import com.ruoyi.system.service.ISysDeptService;
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.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.schoolgrade.SchoolGrade;
import yangtz.cs.liu.campus.domain.student.SchoolStudentLeave;
import yangtz.cs.liu.campus.domain.teacher.SchoolTeacherLeave;
import yangtz.cs.liu.campus.domain.temp.LeaveResultTemplate;
import yangtz.cs.liu.campus.domain.temp.TeacherLeaveTemplate;
import yangtz.cs.liu.campus.service.schoolgrade.ISchoolGradeMentorService;
import yangtz.cs.liu.campus.service.schoolgrade.ISchoolGradeService;
import yangtz.cs.liu.campus.service.student.ISchoolStudentService;
import yangtz.cs.liu.campus.service.teacher.ISchoolTeacherLeaveService;
import yangtz.cs.liu.campus.service.teacher.ISchoolTeacherService;
import yangtz.cs.liu.campus.service.workDay.ISchoolWorkDayService;
import yangtz.cs.liu.campus.vo.schoolgrade.GradeTreeSelect;
import yangtz.cs.liu.campus.vo.student.StudentLeaveVO;
import yangtz.cs.liu.campus.vo.teacher.SchoolTeacherVO;
import yangtz.cs.liu.campus.vo.teacher.TeacherLeaveVO;
import yangtz.cs.liu.wechat.domain.WxLoginBody;
import yangtz.cs.liu.wechat.domain.template.LeaveStateTemplate;
import yangtz.cs.liu.wechat.domain.template.LeaveTemplate;
import yangtz.cs.liu.wechat.service.api.IWxApiService;

import java.util.*;

import static com.core.constant.ProcessDefinition.STUDENTLEAVE;
import static com.core.constant.ProcessDefinition.TEACHERLEAVE;
import static yangtz.cs.liu.campus.constant.EmployeeType.TEACH;
import static yangtz.cs.liu.campus.constant.GradeConstant.NEWTERM;
import static yangtz.cs.liu.campus.constant.GradeConstant.SCHOOLLEADER;
import static yangtz.cs.liu.campus.constant.ProcessState.*;
import static yangtz.cs.liu.wechat.constant.ProcessTypeConstant.*;
import static yangtz.cs.liu.wechat.constant.ProcessTypeConstant.OTHER;

/**
 * @author lyric
 * @date 2022/11/16 15:09
 * <p>
 * 老师请假
 */
@RestController
@RequestMapping("/wx/teacherLeave")
public class WxTeacherLeaveController extends BaseController {

    @Autowired
    private ISchoolTeacherLeaveService schoolTeacherLeaveService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private IWxApiService wxApiService;

    @Autowired
    private IProcessService processService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private ISchoolGradeService schoolGradeService;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private ISchoolTeacherService schoolTeacherService;

    @Autowired
    private ISchoolWorkDayService dayService;

    @Autowired
    private UserInfoUtil userInfoUtil;

    @Autowired
    private TaskService taskService;


    //职工
    private static final String TYPE = "1";

    /**
     * 老师请假列表，传个用户id过来，该列表只查询当前登录教职工个人请假列表
     */
    @GetMapping("/list/{userId}")
    public TableDataInfo list(String submitState, SchoolTeacherLeave teacherLeave, @PathVariable Long userId) {
        teacherLeave.setTeacherId(userId);
        startPage();
        List<TeacherLeaveVO> list = schoolTeacherLeaveService.selectSchoolTeacherLeaveList(submitState, teacherLeave);
        return getDataTable(list);
    }

    /**
     * 查询详情
     *
     * @param id
     * @return
     */
    @GetMapping("/queryOne/{id}")
    public AjaxResult queryOne(@PathVariable("id") Long id) {
        SchoolTeacherLeave leave = schoolTeacherLeaveService.getById(id);
        TeacherLeaveVO vo = new TeacherLeaveVO();
        BeanUtils.copyProperties(leave, vo);
        if (!leave.getApplyType().equals(TYPE)) {
            //用于教师显示请假天数X天Y节课
            String dayCourse = HolidayDateUtil.dayCourse(leave.getTotalTime());
            vo.setDayCourse(dayCourse);
        }
        //设置标题
        String title = "";
        if (leave.getType().equals(PUBNUM)) {
            title += PUB;
        } else if (leave.getType().equals(THINGNUM)) {
            title += THING;
        } else if (leave.getType().equals(ILLNESSNUM)) {
            title += ILLNESS;
        } else if (leave.getType().equals(MARRYNUM)) {
            title += MARRY;
        } else if (leave.getType().equals(LOSENUM)) {
            title += LOSE;
        } else if (leave.getType().equals(MATERNITYNUM)) {
            title += MATERNITY;
        } else if (leave.getType().equals(OTHERNUM)) {
            title += OTHER;
        }
        title += "-" + leave.getApplyOrgname() + "-" + leave.getTeacherName();
        vo.setTitle(title);
        //获取教师手机号
        SchoolTeacher teacher = schoolTeacherService.getById(leave.getTeacherId());
        vo.setTeacherTel(teacher.getTeacherTel());
        return AjaxResult.success(vo);
    }

    /**
     * 新增
     *
     * @param schoolTeacherLeave
     * @return
     */
    @PostMapping("/add")
    public AjaxResult add(@RequestBody @Validated SchoolTeacherLeave schoolTeacherLeave) {
        schoolTeacherLeaveService.judgeHandUser(schoolTeacherLeave);
        schoolTeacherLeave.setState(SAVE);
        //获取当前请假人
        schoolTeacherLeave.setApplyUserId(schoolTeacherLeave.getTeacherId());
        schoolTeacherLeave.setApplyUser(schoolTeacherLeave.getTeacherName());
        //获取当前用户是教工还是职工
        SysUser user = userService.selectUserById(schoolTeacherLeave.getTeacherId());
        schoolTeacherLeave.setApplyType(user.getEmployeeType());
        schoolTeacherLeaveService.judgeDate(schoolTeacherLeave);
        return toAjax(schoolTeacherLeaveService.save(schoolTeacherLeave));
    }

    @PostMapping("/submit")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult submit(@RequestBody @Validated SchoolTeacherLeave schoolTeacherLeave) {
        schoolTeacherLeaveService.judgeHandUser(schoolTeacherLeave);
        schoolTeacherLeave.setState(SAVE);
        //获取当前请假人
        schoolTeacherLeave.setApplyUserId(schoolTeacherLeave.getTeacherId());
        schoolTeacherLeave.setApplyUser(schoolTeacherLeave.getTeacherName());
        //获取当前用户是教工还是职工
        SysUser user = userService.selectUserById(schoolTeacherLeave.getTeacherId());
        schoolTeacherLeave.setApplyType(user.getEmployeeType());
        schoolTeacherLeaveService.judgeDate(schoolTeacherLeave);
        schoolTeacherLeaveService.save(schoolTeacherLeave);
        AjaxResult ajax = submission(schoolTeacherLeave.getId());
        return ajax;
    }

    @PostMapping("/submitApply/{id}")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult submitApply(@PathVariable("id") Long id) {
        AjaxResult ajax = submission(id);
        return ajax;
    }

    public AjaxResult submission(Long id){
        SchoolTeacherLeave schoolTeacherLeave = schoolTeacherLeaveService.getById(id);
        if (StringUtils.isNull(schoolTeacherLeave)) {
            throw new ServiceException("提交申请失败,未查询到相关信息");
        }
        schoolTeacherLeave.setApplyTime(DateUtils.getNowDate());
        schoolTeacherLeaveService.submitApply(schoolTeacherLeave, userInfoUtil.getTeacherName(), TEACHERLEAVE, new HashMap<>());

        /** 发送申请通知 */
        LeaveTemplate leaveTemplate = new LeaveTemplate();
        String openId = userService.getOpenIdByUserId(id);
//        openId = "oIDgU6allYyjHw5CmVO0MboRo6i8";
        leaveTemplate.setIdentity(1);
        leaveTemplate.setToUserOpenId(openId);
        leaveTemplate.setReasonForLeave(schoolTeacherLeave.getReasonForLeave());
        leaveTemplate.setLeaveStartTime(schoolTeacherLeave.getStartTime());
        leaveTemplate.setLeaveEndTime(schoolTeacherLeave.getEndTime());
        leaveTemplate.setUserName(schoolTeacherLeave.getTeacherName());

        return AjaxResult.success(wxApiService.sendTemplate(leaveTemplate));
    }


    /**
     * 修改
     *
     * @param schoolTeacherLeave
     * @return
     */
    @PutMapping("/edit")
    public AjaxResult edit(@RequestBody @Validated SchoolTeacherLeave schoolTeacherLeave) {
        if (StringUtils.isNull(schoolTeacherLeave.getId())) {
            return AjaxResult.error("老师请假id未传");
        }
        schoolTeacherLeaveService.judgeDate(schoolTeacherLeave);
        schoolTeacherLeaveService.judgeHandUser(schoolTeacherLeave);
        //return toAjax(schoolTeacherLeaveService.updateById(schoolTeacherLeave));
        return toAjax(schoolTeacherLeaveService.editLeave(schoolTeacherLeave));
    }

    /**
     * 删除
     *
     * @param ids
     * @return
     */
    @DeleteMapping("/delete/{ids}")
    public AjaxResult delete(@PathVariable("ids") List<Long> ids) {
        return toAjax(schoolTeacherLeaveService.removeByIds(ids));
    }

    /**
     * 提交申请
     */
    @Log(title = "请假业务", businessType = BusinessType.UPDATE)
    @PostMapping("/submitApply")
    public AjaxResult submitApply(@RequestBody @Validated SchoolTeacherLeave schoolTeacherLeave) {
        /** 请假申请 */
        String applyUser = schoolTeacherLeave.getApplyUser();
        schoolTeacherLeave.setApplyTime(DateUtils.getNowDate());
        schoolTeacherLeaveService.submitApply(schoolTeacherLeave, applyUser, TEACHERLEAVE, new HashMap<>());

        /** 发送老师请假模板 */
       /* LeaveTemplate leaveTemplate = new LeaveTemplate();
        String openId = userService.getOpenIdByUserId(schoolTeacherLeave.getHandUserId1());
        leaveTemplate.setIdentity(1);
        leaveTemplate.setToUserOpenId(openId);
        leaveTemplate.setReasonForLeave(schoolTeacherLeave.getReasonForLeave());
        leaveTemplate.setLeaveStartTime(schoolTeacherLeave.getStartTime());
        leaveTemplate.setLeaveEndTime(schoolTeacherLeave.getEndTime());
        leaveTemplate.setUserName(schoolTeacherLeave.getTeacherName());
        return AjaxResult.success(wxApiService.sendTemplate(leaveTemplate));*/
        /** 发送申请通知 */
        TeacherLeaveTemplate template = new TeacherLeaveTemplate();
        //String openId = userService.getOpenIdByUserId(schoolTeacherLeave.getHandUserId1());
        String openId = schoolTeacherService.getOpenIdByUserId(schoolTeacherLeave.getHandUserId1());
        template.setUserType(schoolTeacherLeave.getApplyType());
        template.setToUserOpenId(openId);
        //template.setReasonForLeave(schoolTeacherLeave.getReasonForLeave());
        template.setType(schoolTeacherLeave.getType());
        template.setLeaveStartTime(schoolTeacherLeave.getStartTime());
        template.setLeaveEndTime(schoolTeacherLeave.getEndTime());
        template.setStartSort(schoolTeacherLeave.getStartSort());
        template.setEndSort(schoolTeacherLeave.getEndSort());
        template.setUserName(schoolTeacherLeave.getTeacherName());
        return AjaxResult.success(wxApiService.sendTeacherLeaveTemplate(template));
    }

    /**
     * 待办事项列表
     */
    @GetMapping("/taskList/{userId}")
    public TableDataInfo taskList(@PathVariable("userId") String userId, SchoolTeacherLeave entity) {
        List<TeacherLeaveVO> list = schoolTeacherLeaveService.findTodoTasks(TEACHERLEAVE, entity, userId);
        int total = processService.getTodoTotal(TEACHERLEAVE, userId);
        return getTaskTable(list, total);
    }

    /**
     * 完成任务
     */
    @PostMapping("/complete/{taskId}/{instanceId}/{userId}")
    public AjaxResult complete(@PathVariable("taskId") String taskId,
                               @PathVariable("instanceId") String instanceId,
                               @PathVariable("userId") String userId,
                               @RequestBody Map<String, Object> variables) {
        LambdaQueryWrapper<SchoolTeacherLeave> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SchoolTeacherLeave::getInstanceId, instanceId);
        SchoolTeacherLeave application = schoolTeacherLeaveService.getOne(lqw);
        variables.put("totalTime", application.getTotalTime());
        processService.completeWxTask(taskId, instanceId, userId, variables);


        Boolean flag = (boolean) variables.get("pass");
        ProcessInstance rpi = runtimeService
                .createProcessInstanceQuery()//创建流程实例查询对象
                .processInstanceId(instanceId)
                .singleResult();
        //说明流程实例结束了
        if (rpi == null) {
            if (flag) {
                application.setState(PASS);
            } else {
                application.setState(REFUSE);
            }
            schoolTeacherLeaveService.updateById(application);
            //请假结果模板消息
            LeaveResultTemplate resultTemplate = new LeaveResultTemplate();
            resultTemplate.setFirst("您好，您的请假申请已回复。");
            resultTemplate.setResult(flag ? "已批准 ": "已驳回");
            resultTemplate.setRemark("审批留言： "+ variables.get("comment"));
            //获取请假教师openId
            //String openId = userService.getOpenIdByUserId(application.getTeacherId());
            String openId = schoolTeacherService.getOpenIdByUserId(application.getTeacherId());
            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());
            }
            return AjaxResult.success(wxApiService.sendLeaveResultTemplate(resultTemplate));
        }


        /** 推送成功申请或者申请失败模板 */
        /*LeaveStateTemplate template = new LeaveStateTemplate();
        Date date = new Date();
        String format = DateFormatUtils.format(date, "yyyy/MM/dd HH:mm");
        template.setHandTime(format);
        template.setState(flag == Boolean.TRUE ? "请求通过" : "请求未通过");
        template.setIdentity(0);
        template.setName(application.getTeacherName());*/
        /** 发送申请通知 */
        TeacherLeaveTemplate template = new TeacherLeaveTemplate();
        String openId = "";
        template.setUserType(application.getApplyType());
        //template.setReasonForLeave(schoolTeacherLeave.getReasonForLeave());
        template.setType(application.getType());
        template.setLeaveStartTime(application.getStartTime());
        template.setLeaveEndTime(application.getEndTime());
        template.setStartSort(application.getStartSort());
        template.setEndSort(application.getEndSort());
        template.setUserName(application.getTeacherName());

        //流程没结束，目前已到分管领导或主要领导
        List<Task> taskList = taskService.createTaskQuery()
                .processInstanceId(application.getInstanceId())
                .list();    // 例如请假会签，会同时拥有多个任务
        if (!CollectionUtils.isEmpty(taskList)) {
            TaskEntityImpl task = (TaskEntityImpl) taskList.get(0);

            //分管领导
            if(FENGUAN.equals(task.getName())){
                //openId = userService.getOpenIdByUserId(application.getHandUserId2());
                openId = schoolTeacherService.getOpenIdByUserId(application.getHandUserId2());
            }
            //主要
            if(ZHUYAO.equals(task.getName())){
                //openId = userService.getOpenIdByUserId(application.getHandUserId3());
                openId = schoolTeacherService.getOpenIdByUserId(application.getHandUserId3());
            }
        }
        template.setToUserOpenId(openId);
        return AjaxResult.success(wxApiService.sendTeacherLeaveTemplate(template));
    }

    /**
     * @author lyric
     * @date 2022/11/16 15:23
     * 销假,不用销假
     */
    @PostMapping("/cancelLeave/{taskId}")
    public AjaxResult cancelLeave(@PathVariable("taskId") String taskId, @RequestBody SchoolTeacherLeave schoolTeacherLeave) {
        schoolTeacherLeaveService.cancelLeave(taskId, schoolTeacherLeave);
        return AjaxResult.success();
    }

    /**
     * @author lyric
     * @date 2022/11/16 15:30
     * 老师请假 --> 我的已办列表
     */
    @GetMapping("/taskDoneList/{userId}")
    public TableDataInfo teacherTaskDoneList(@PathVariable("userId") String userId, SchoolTeacherLeave entity) {
        List<TeacherLeaveVO> list = schoolTeacherLeaveService.findDoneTasks(TEACHERLEAVE, entity, getUserId().toString());
        int total = processService.getDoneTotal(TEACHERLEAVE, userId);
        return getTaskTable(list, total);
    }

    /**
     * 教职工请假新增或修改页，根据登录人职工类型，判断返回级部信息还是处室信息
     */
    @GetMapping("/getList/{userId}")
    public AjaxResult getList(@PathVariable Long userId) {
        SysUser user = userService.selectUserById(userId);
        String employeeType = user.getEmployeeType();
        //是教工
        if (employeeType.equals(TEACH)) {
            SchoolGrade schoolGrade = new SchoolGrade();
            //查询当前学年的级部信息
            schoolGrade.setSfzxxn(NEWTERM);
            List<SchoolGrade> list = schoolGradeService.queryList(schoolGrade);
            List<GradeTreeSelect> gradeTreeSelectList = new ArrayList<>();
            if (StringUtils.isNotNull(list)) {
                gradeTreeSelectList = schoolGradeService.buildGradeTreeList(list);
            }
            return AjaxResult.success(gradeTreeSelectList);
        }
        //职工
        return AjaxResult.success(deptService.selectDeptTreeList(new SysDept()));
    }

    /**
     * 获取当前登录人所在部门或级部
     * */
    @GetMapping("/getDeptOrGrade/{userId}")
    public AjaxResult getDeptOrGrade(@PathVariable Long userId) {
        SysUser user = userService.selectUserById(userId);
        String employeeType = user.getEmployeeType();
        //是教工
        if(employeeType.equals(TEACH)){
            //判断所在班级所在级部（存在一个老师跨几个级部教学，比如体育老师，所以获取教授班级所在级部，随便选择某个级部即可）
            return AjaxResult.success(schoolGradeService.getGradeId(userId));
        }
        //职工
        return AjaxResult.success(user.getDeptId());
    }

    /**
     * 获取级部主任或处室主任，传已选级部或处室
     */
    @GetMapping("/getDeptLeader/{applyOrgid}/{userId}")
    public TableDataInfo getLeader(@PathVariable("applyOrgid") Long applyOrgid,
                                   @PathVariable("userId") Long userId,
                                   SchoolTeacherVO teacherVO) {
        SysUser user = userService.selectUserById(userId);
        startPage();
        return getDataTable(schoolTeacherLeaveService.getLeader(applyOrgid, user.getEmployeeType(),teacherVO));
    }

    /**
     * 获取校领导
     */
    @GetMapping("/getSchoolLeader")
    public TableDataInfo getSchoolLeader(SchoolTeacherVO teacherVO) {
        startPage();
        return getDataTable(schoolTeacherService.getSectionLeader(null, SCHOOLLEADER,teacherVO));
    }

    /**
     * 请假总时长，返回值x.x天
     * 教工传参，请假开始日期（年月日）及第几节课，结束日期及第几节课
     * 职工传参，请假开始时间，结束时间（年月日 时分秒）
     */
    @GetMapping("/getTotalTime/{userId}")
    public AjaxResult getTotalTime(@PathVariable Long userId, SchoolTeacherLeave schoolTeacherLeave) {
        AjaxResult ajax = AjaxResult.success();
        double day = 0.0;
        //判断用户是职工还是教工
        String employeeType = userService.selectUserById(userId).getEmployeeType();
        schoolTeacherLeave.setApplyType(employeeType);
        schoolTeacherLeaveService.judgeDate(schoolTeacherLeave);
        //获取周末，节假日日期
        List<String> restList = dayService.getHolidayList(schoolTeacherLeave.getStartTime(), schoolTeacherLeave.getEndTime(), TYPE);
        //如果是教工
        if (employeeType.equals(TEACH)) {
            //int courseNum = teacherLeaveDeal(schoolTeacherLeave,restList);
            int courseNum = schoolTeacherLeaveService.teacherLeaveDeal(schoolTeacherLeave, restList);
            if (courseNum < 0) {
                throw new ServiceException("请假时间异常，请检查");
            }
            day = courseNum / 8.0;
            //教工显示X天Y节课
            String dayCourse = HolidayDateUtil.dayCourse(day);
            ajax.put("data", day);
            ajax.put("dayCourse", dayCourse);
            return ajax;
        }

        //职工
        //double hours = workerLeaveDeal(schoolTeacherLeave,restList);
        double hours = schoolTeacherLeaveService.workerLeaveDeal(schoolTeacherLeave, restList);
        if (hours < 0) {
            throw new ServiceException("请假时间异常，请检查");
        }
        day = hours / 7.25;
        String d = String.format("%.3f", day);
        ajax.put("data", d);
        return ajax;
    }

}
