package com.ym.mec.teacher.controller;

import com.alibaba.fastjson.JSON;
import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.ClassGroupStudentMapperDao;
import com.ym.mec.biz.dal.dao.StudentAttendanceDao;
import com.ym.mec.biz.dal.dto.*;
import com.ym.mec.biz.dal.entity.CourseSchedule;
import com.ym.mec.biz.dal.entity.SysConfig;
import com.ym.mec.biz.dal.enums.ClassGroupStudentStatusEnum;
import com.ym.mec.biz.dal.enums.GroupType;
import com.ym.mec.biz.dal.enums.StudentAttendanceStatusEnum;
import com.ym.mec.biz.dal.page.CourseHomeworkQueryInfo;
import com.ym.mec.biz.dal.page.CourseScheduleQueryInfo;
import com.ym.mec.biz.dal.page.EndCourseScheduleQueryInfo;
import com.ym.mec.biz.dal.page.StudentAttendanceQueryInfo;
import com.ym.mec.biz.service.CourseScheduleService;
import com.ym.mec.biz.service.StudentAttendanceService;
import com.ym.mec.biz.service.SysConfigService;
import com.ym.mec.common.controller.BaseController;
import com.ym.mec.common.entity.HttpResponseResult;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.QueryInfo;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author Joburgess
 * @Date 2019/9/27
 */
@Api(tags = "课程计划服务")
@RequestMapping("teacherCourseSchedule")
@RestController
public class TeacherCourseScheduleController extends BaseController {

    @Autowired
    private CourseScheduleService scheduleService;
    @Autowired
    private StudentAttendanceService studentAttendanceService;
    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private StudentAttendanceDao studentAttendanceDao;
    @Autowired
    private ClassGroupStudentMapperDao classGroupStudentMapperDao;

    @ApiOperation(value = "根据月份获取该月有课的日期")
    @GetMapping("/getCourseScheduleDateByMonth")
    public Object getCourseScheduleDateByMonth(@ApiParam(value = "月份", required = true) @RequestParam Date month,
                                               @ApiParam(value = "课程类型") String type) {
        if(Objects.isNull(month)){
            return failed(HttpStatus.FORBIDDEN, "请指定日期!");
        }
        return succeed(scheduleService.getCourseScheduleDateByTeacher(month,type));
    }

    @ApiOperation(value = "根据日期获取当日排课")
    @GetMapping("/getCourseSchedulesWithDate")
    public Object getCourseSchedulesWithDate(@ApiParam(value = "日期", required = true) Date date,
                                             @ApiParam(value = "课程类型") String type){
        if(Objects.isNull(date)){
            return failed("请指定日期!");
        }
        SysUser user = sysUserFeignService.queryUserInfo();
        if(null==user){
            return failed(HttpStatus.FORBIDDEN, "请登录");
        }
        SysConfig sysConfig = sysConfigService.findByParamName(SysConfigService.ENABLE_STUDENT_ATTENDANCE_TIME_RANGE);
        SysConfig offlineSignInEarlyForwardTime = sysConfigService.findByParamName(SysConfigService.OFFLINE_SIGN_IN_EARLY_FORWARD_TIME);
        SysConfig sysConfigVip = sysConfigService.findByParamName(SysConfigService.ENABLE_STUDENT_ATTENDANCE_TIME_RANGE_VIP);
        SysConfig courseBeforeBufferTime = sysConfigService.findByParamName(SysConfigService.COURSE_BEFORE_BUFFER_TIME);
        SysConfig courseAfterBufferTime = sysConfigService.findByParamName(SysConfigService.COURSE_AFTER_BUFFER_TIME);
        SysConfig studentAttendanceAfterTimeConfig = sysConfigService.findByParamName(SysConfigService.ENABLE_STUDENT_ATTENDANCE_BEFOR_COURSE_START_TIME_RANGE_VIP);
        List<CourseScheduleDto> teacherCourseSchedulesWithDate = scheduleService.getTeacherCourseSchedulesWithDate(user.getId(),date,type);
        Map<String,Object> result = new HashMap<>();
        result.put("rows",teacherCourseSchedulesWithDate);
        result.put("appealHoursRange",4);
        result.put("offlineSignInEarlyForwardTime", offlineSignInEarlyForwardTime.getParanValue(Integer.class));
        result.put("enableStudentAttendanceTimeRange",sysConfig.getParanValue(Integer.class));
        result.put("enableStudentAttendanceTimeRangeVip",sysConfigVip.getParanValue(Integer.class));
        result.put("joinRoomBeforeTime",studentAttendanceAfterTimeConfig.getParanValue(Integer.class));
        result.put("courseBeforeBufferTime", courseBeforeBufferTime.getParanValue(Integer.class));
        result.put("courseAfterBufferTime", courseAfterBufferTime.getParanValue(Integer.class));
        return succeed(result);
    }

    @ApiOperation(value = "根据月份获取该月历史有课的日期")
    @GetMapping("/getHistoryCourseScheduleDateByMonth")
    public Object getHistoryCourseScheduleDateByTeacher(@ApiParam(value = "月份", required = true) @RequestParam Date month) {
        SysUser user = sysUserFeignService.queryUserInfo();
        if(null==user){
            return failed(HttpStatus.FORBIDDEN, "请登录");
        }
        if(Objects.isNull(month)){
            return failed(HttpStatus.FORBIDDEN, "请指定日期!");
        }
        return succeed(scheduleService.getHistoryCourseScheduleDateByTeacher(user.getId(),month));
    }

    @ApiOperation(value = "根据日期获取当日历史课程")
    @GetMapping("/getHistoryCourseSchedulesWithDate")
    public Object getHistoryCourseSchedulesWithDate(@ApiParam(value = "日期", required = true) Date date){
        if(Objects.isNull(date)){
            return failed("请指定日期!");
        }
        SysUser user = sysUserFeignService.queryUserInfo();
        if(null==user){
            return failed(HttpStatus.FORBIDDEN, "请登录");
        }
        List<CourseScheduleDto> teacherCourseSchedulesWithDate = scheduleService.getTeacherHistoryCourseSchedulesWithDate(user.getId(),date);
        Map<String,Object> result = new HashMap<>();
        result.put("rows",teacherCourseSchedulesWithDate);
        result.put("appealDaysRange",1);
        result.put("complaintsDaysRange",1);
        return succeed(result);
    }

    @ApiOperation(value = "根据课程ID查询打卡界面课程详情")
    @GetMapping("/getCurrentCourseDetail")
    public Object getCurrentCourseDetail(Long courseID){
        if(Objects.isNull(courseID)){
            return failed("请指定课程!");
        }
        return succeed(scheduleService.getCurrentCourseDetail(courseID));
    }

    @ApiOperation(value = "获取老师指定班级的排课")
    @GetMapping("/queryTeacherClassCourseSchedule")
    public Object queryTeacherClassCourseSchedule(CourseScheduleQueryInfo queryInfo){
        return succeed(scheduleService.queryTeacherClassCourseSchedule(queryInfo));
    }

    @ApiOperation(value = "获取老师指定班级的排课")
    @GetMapping("/queryTeacherVipClassCourseSchedule")
    public Object queryTeacherVipClassCourseSchedule(CourseScheduleQueryInfo queryInfo){
        Map<String,Object> result = new HashMap<>();
        result.put("rows",scheduleService.queryTeacherVipClassCourseSchedule(queryInfo));
        result.put("appealHoursRange",4);
        return succeed(result);
    }

    @ApiOperation(value = "获取点名详情头部信息")
    @GetMapping("/findCourseAttendanceDetailHeadInfo")
    public Object findCourseAttendanceDetailHeadInfo(Long courseScheduleId){
        return succeed(scheduleService.findCourseAttendanceDetailHeadInfo(courseScheduleId));
    }

    @ApiOperation(value = "根据课程获取当前课程的学生列表")
    @GetMapping("/getCurrentCourseStudents")
    public Object getCurrentCourseStudents(StudentAttendanceQueryInfo queryInfo){
        if(Objects.isNull(queryInfo.getClassGroupId())){
            return failed("请指定班级!");
        }
        queryInfo.setFilterStatus(StudentAttendanceStatusEnum.DROP_OUT);
        return succeed(studentAttendanceService.getCurrentCourseStudents(queryInfo));
    }

    @ApiOperation(value = "课程批量调整")
    @PostMapping("/batchUpdateCourseSchedule")
    public Object batchUpdateCourseSchedule(@RequestBody BatchInsertCoursesDto batchInsertCoursesDto){
        scheduleService.batchUpdateCourseSchedule(batchInsertCoursesDto);
        return succeed();
    }

    @ApiOperation(value = "课时调整")
    @PostMapping(value = "/classStartDateAdjust",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Object classStartDateAdjust(ClassDateAdjustDto classDateAdjustDto){
        if(Objects.isNull(classDateAdjustDto.getId())){
            return failed("请指定课程!");
        }
        if(classDateAdjustDto.getStartClassTime().before(new Date())){
            return failed("课程开始时间不能小于当前时间");
        }
        CourseSchedule oldCourseSchedule = scheduleService.get(classDateAdjustDto.getId());
        if(Objects.isNull(oldCourseSchedule)){
            return failed("未找到指定课程");
        }
        if(oldCourseSchedule.getGroupType() != GroupType.VIP){
        	return failed("客户端只能调整VIP课");
        }
        Date now = new Date();
        
        //默认开课前4小时内，可调整，如果全员请假，可在当天24小时前调整
        SysConfig advanceLeaveHoursConfig = sysConfigService.findByParamName(SysConfigService.ENABLE_TEACHER_COURSE_ADJUST_DEFAULT_HOURS);
        Integer advanceLeaveHours=advanceLeaveHoursConfig.getParanValue(Integer.class);
        
        List<Long> newCourseScheduleIds = new ArrayList<Long>();
        newCourseScheduleIds.add(oldCourseSchedule.getId());
        List<Map<Long, Integer>> courseLeaveStudentNumMaps = studentAttendanceDao.countCourseLeaveStudentNumWithFourHoursAgo(newCourseScheduleIds, advanceLeaveHours);
        Map<Long,Long> courseLeaveStudentNumMap = MapUtil.convertIntegerMap((courseLeaveStudentNumMaps));

        List<Integer> classGroupIds = new ArrayList<Integer>();
        classGroupIds.add(oldCourseSchedule.getClassGroupId());
        List<Map<Integer, Integer>> classGroupStudentNumMaps = classGroupStudentMapperDao.countClassGroupsStudentNum(classGroupIds, ClassGroupStudentStatusEnum.NORMAL);
        Map<Integer, Long> classGroupStudentNumMap = MapUtil.convertIntegerMap(classGroupStudentNumMaps);

        Long normalStudentNum = classGroupStudentNumMap.get(oldCourseSchedule.getClassGroupId());
        Long courseLeaveStudentNum = courseLeaveStudentNumMap.get(oldCourseSchedule.getId());
        if(oldCourseSchedule.getGroupType().equals(GroupType.VIP)
                &&Objects.nonNull(courseLeaveStudentNum)
                &&Objects.nonNull(normalStudentNum)
                &&courseLeaveStudentNum.intValue()==normalStudentNum.intValue()){
            if(!DateUtil.isSameDay(now,oldCourseSchedule.getStartClassTime())&&now.after(oldCourseSchedule.getStartClassTime())){
                throw new BizException("当前时间不可对相关课程进行调整");
            }
        }else{
            if(DateUtil.addHours(now,advanceLeaveHours).after(oldCourseSchedule.getStartClassTime())){
                throw new BizException("请在课程开始前{}小时进行调整",advanceLeaveHours);
            }
        }
        
        /*if (oldCourseSchedule.getGroupType().equals(GroupType.VIP)) {
            vipGroupService.checkVipCourseIsInScore(Long.valueOf(oldCourseSchedule.getMusicGroupId()));
        }*/
        
        if(Objects.isNull(classDateAdjustDto.getClassGroupId())){
            classDateAdjustDto.setClassGroupId(oldCourseSchedule.getClassGroupId());
        }
        List<CourseSchedule> courseSchedules=new ArrayList<>();
        courseSchedules.add(classDateAdjustDto);
        scheduleService.courseAdjust(courseSchedules);
        return succeed();
    }

    @ApiOperation(value = "对外课时调整")
    @PostMapping(value = "/updateCourseScheduleOfComm",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Object updateCourseScheduleOfComm(CourseSchedule courseSchedule){
    	CourseSchedule oldCourseSchedule = scheduleService.get(courseSchedule.getId());
        if(Objects.isNull(oldCourseSchedule)){
            return failed("未找到指定课程");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date date = new Date();
		String endDateStr = DateUtil.format(oldCourseSchedule.getClassDate(), "yyyy-MM-dd") + " " + DateUtil.format(oldCourseSchedule.getStartClassTime(), "HH:mm:ss");
		if (DateUtil.stringToDate(endDateStr, sdf).before(date)) {
			throw new BizException("调整失败，未开始的课程才能调整");
		}
		
		endDateStr = DateUtil.format(courseSchedule.getClassDate(), "yyyy-MM-dd") + " " + DateUtil.format(courseSchedule.getStartClassTime(), "HH:mm:ss");
		if (DateUtil.stringToDate(endDateStr, sdf).before(date)) {
			throw new BizException("调整失败，只能调整到未来的时间");
		}
		
        if(Objects.isNull(courseSchedule.getClassGroupId())){
            courseSchedule.setClassGroupId(oldCourseSchedule.getClassGroupId());
        }
        List<CourseSchedule> courseSchedules=new ArrayList<>();
        courseSchedules.add(courseSchedule);
        scheduleService.courseAdjust(courseSchedules);
        return succeed();
    }

    @ApiOperation(value = "课时交换")
    @PostMapping(value = "/courseSwap",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Object courseSwap(Long courseScheduleId1,Long courseScheduleId2){
        if(Objects.isNull(courseScheduleId1)||Objects.isNull(courseScheduleId2)){
            return failed("请指定课程!");
        }
        scheduleService.courseSwap(courseScheduleId1,courseScheduleId2);
        return succeed();
    }

    @GetMapping("/statisticsInfo")
    @ApiOperation("历史考勤统计-头信息")
    public Object getStatisticsInfo(Integer classGroupId) {
        return succeed(studentAttendanceService.getStatisticsInfo(classGroupId));
    }

    @GetMapping("/statisticsList")
    @ApiOperation("历史考勤统计-考勤列表")
    public Object statisticsList(CourseHomeworkQueryInfo queryInfo) {
        return succeed(studentAttendanceService.statisticsList(queryInfo));
    }

    @ApiOperation(value = "终极课表获取")
    @GetMapping("/superFindCourseSchedules")
    public Object superFindCourseSchedules(EndCourseScheduleQueryInfo queryInfo){
        return succeed(scheduleService.endFindCourseSchedules(queryInfo));
    }

    @ApiOperation(value = "教师端中间页课程评价数据获取")
    @GetMapping("/teacherCourseRemarkInfo")
    public Object teacherCourseRemarkInfo(Long courseScheduleId){
        return succeed(scheduleService.teacherCourseRemarkInfo(courseScheduleId));
    }

    @ApiOperation(value = "教师端中间页课程评价数据提交")
    @PostMapping("/teacherCourseRemarkCommit")
    public Object teacherCourseRemarkCommit(@RequestBody TeacherRemarkCommitDto teacherRemarkCommitDto){
        scheduleService.teacherCourseRemarkCommit(teacherRemarkCommitDto);
        return succeed();
    }

    @ApiOperation(value = "教师端中间页网络教室头部详情")
    @GetMapping("/teacherCourseHeadInfo")
    public Object teacherCourseHeadInfo(Long courseScheduleId){
        return succeed(scheduleService.teacherCourseHeadInfo(courseScheduleId));
    }

    @ApiOperation(value = "教师端中间页网络教室课程进度列表")
    @GetMapping("/teacherCourseRates")
    public Object teacherCourseRates(Long courseScheduleId){
        return succeed(scheduleService.teacherCourseRates(courseScheduleId));
    }

    @ApiOperation(value = "课时使用记录列表")
    @GetMapping("/teacherCourseMinutes")
    public Object teacherCourseMinutes(QueryInfo queryInfo){
        return succeed(scheduleService.teacherCourseMinutes(queryInfo));
    }

    @ApiOperation(value = "课程批量调整检测-仅时间")
    @PostMapping("/courseAdjustOnlyWithClassDateCheck")
    public HttpResponseResult courseAdjustOnlyWithClassDateCheck(@RequestBody VipGroupCourseAdjustInfoDto vipGroupCourseAdjustInfo){
        return succeed(scheduleService.courseAdjustOnlyWithClassDateCheck(vipGroupCourseAdjustInfo));
    }

    @ApiOperation(value = "课程批量调整")
    @PostMapping("/courseAdjustOnlyWithClassDate")
    public HttpResponseResult courseAdjustOnlyWithClassDate(@RequestBody List<CourseSchedule> courseSchedules){
        SysUser user = sysUserFeignService.queryUserInfo();
        if(null==user){
            return failed(HttpStatus.FORBIDDEN, "请登录");
        }
        scheduleService.courseAdjustOnlyWithClassDate(courseSchedules,user.getId());
        return succeed();
    }

}
