package com.qxgmat.controller.admin;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.nuliji.tools.*;
import com.nuliji.tools.exception.ParameterException;
import com.qxgmat.data.constants.enums.ExperienceDayRange;
import com.qxgmat.data.constants.enums.ExperienceScoreRange;
import com.qxgmat.data.constants.enums.module.CourseModule;
import com.qxgmat.data.constants.enums.module.ProductType;
import com.qxgmat.data.constants.enums.status.AnswerStatus;
import com.qxgmat.data.constants.enums.status.DirectionStatus;
import com.qxgmat.data.constants.enums.trade.RecordSource;
import com.qxgmat.data.constants.enums.user.DataType;
import com.qxgmat.data.constants.enums.user.MoneyRange;
import com.qxgmat.data.dao.entity.*;
import com.qxgmat.data.relation.entity.CourseNoStatRelation;
import com.qxgmat.data.relation.entity.CourseStudentNumberRelation;
import com.qxgmat.dto.admin.extend.*;
import com.qxgmat.dto.admin.request.*;
import com.qxgmat.dto.admin.response.*;
import com.qxgmat.help.ShiroHelp;
import com.qxgmat.service.ManagerService;
import com.qxgmat.service.UsersService;
import com.qxgmat.service.extend.CourseExtendService;
import com.qxgmat.service.extend.MessageExtendService;
import com.qxgmat.service.extend.OrderFlowService;
import com.qxgmat.service.extend.ToolsService;
import com.qxgmat.service.inline.*;
import com.qxgmat.task.AsyncTask;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

@RestController("AdminClassController")
@RequestMapping("/admin/course")
public class CourseController {
    @Autowired
    private ShiroHelp shiroHelp;

    @Autowired
    private CourseService courseService;

    @Autowired
    private CourseNoService courseNoService;

    @Autowired
    private CoursePackageService coursePackageService;

    @Autowired
    private CourseDataService courseDataService;

    @Autowired
    private CourseDataHistoryService courseDataHistoryService;

    @Autowired
    private CourseExperienceService courseExperienceService;

    @Autowired
    private CourseTeacherService courseTeacherService;

    @Autowired
    private CourseTimeService courseTimeService;

    @Autowired
    private PreviewPaperService previewPaperService;

    @Autowired
    private PreviewAssignService previewAssignService;

    @Autowired
    private UserAskCourseService userAskCourseService;

    @Autowired
    private ManagerLogService managerLogService;

    @Autowired
    private ManagerService managerService;

    @Autowired
    private UsersService usersService;

    @Autowired
    private UserOrderRecordService userOrderRecordService;

    @Autowired
    private UserCourseRecordService userCourseRecordService;

    @Autowired
    private CourseExtendService courseExtendService;

    @Autowired
    private OrderFlowService orderFlowService;

    @Autowired
    private ToolsService toolsService;

    @Autowired
    private MessageExtendService messageExtendService;

    @Autowired
    private AsyncTask asyncTask;

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @ApiOperation(value = "添加课程", httpMethod = "POST")
    public Response<Course> add(@RequestBody @Validated Course dto, HttpServletRequest request) {
        Course entity = Transform.convert(dto, Course.class);
        entity = courseService.add(entity);
        managerLogService.log(request);
        return ResponseHelp.success(Transform.convert(entity, Course.class));
    }

    @RequestMapping(value = "/edit", method = RequestMethod.PUT)
    @ApiOperation(value = "编辑课程", httpMethod = "PUT")
    public Response<Boolean> edit(@RequestBody @Validated Course dto, HttpServletRequest request) {
        Course entity = Transform.convert(dto, Course.class);
        entity = courseService.edit(entity);
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/delete", method = RequestMethod.DELETE)
    @ApiOperation(value = "删除课程", httpMethod = "DELETE")
    public Response<Boolean> delete(@RequestParam int id, HttpServletRequest request) {
        Course entity = courseService.get(id);
        courseService.delete(id);
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/detail", method = RequestMethod.GET)
    @ApiOperation(value = "获取课程", httpMethod = "GET")
    public Response<Course> detail(@RequestParam int id,HttpSession session) {
        Course entity = courseService.get(id);
        return ResponseHelp.success(Transform.convert(entity, Course.class));
    }

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    @ApiOperation(value = "课程列表", httpMethod = "GET")
    public Response<PageMessage<CourseListDto>> list(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = false) Integer[] ids,
            @RequestParam(required = false) String keyword,
            @RequestParam(required = false) String courseModule,
            @RequestParam(required = false) Integer structId,
            @RequestParam(required = false) Boolean excludeVs,
            @RequestParam(required = false) Boolean excludeOnline,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction,
            HttpSession session) {
        Page<Course> p;
        if (ids != null && ids.length > 0){
            p = courseService.select(ids);
        }else{
            p = courseService.listAdmin(page, size, keyword, CourseModule.ValueOf(courseModule), structId, excludeVs, excludeOnline, order, DirectionStatus.ValueOf(direction));
        }
        List<CourseListDto> pr = Transform.convert(p, CourseListDto.class);

        return ResponseHelp.success(pr, page, size, p.getTotal());
    }

    @RequestMapping(value = "/package/add", method = RequestMethod.POST)
    @ApiOperation(value = "添加套餐", httpMethod = "POST")
    public Response<CoursePackage> addPackage(@RequestBody @Validated CoursePackageDto dto, HttpServletRequest request) {
        CoursePackage entity = Transform.dtoToEntity(dto);
        entity = coursePackageService.add(entity);
        managerLogService.log(request);
        return ResponseHelp.success(Transform.convert(entity, CoursePackage.class));
    }
    @RequestMapping(value = "/package/edit", method = RequestMethod.PUT)
    @ApiOperation(value = "编辑套餐", httpMethod = "PUT")
    public Response<Boolean> editPackage(@RequestBody @Validated CoursePackageDto dto, HttpServletRequest request) {
        CoursePackage entity = Transform.dtoToEntity(dto);
        entity = coursePackageService.edit(entity);
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/package/delete", method = RequestMethod.DELETE)
    @ApiOperation(value = "删除套餐", httpMethod = "DELETE")
    public Response<Boolean> deletePackage(@RequestParam int id, HttpServletRequest request) {
        coursePackageService.delete(id);
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/package/detail", method = RequestMethod.GET)
    @ApiOperation(value = "获取套餐", httpMethod = "GET")
    public Response<CoursePackage> detailPackage(@RequestParam int id,HttpSession session) {
        CoursePackage entity = coursePackageService.get(id);
        return ResponseHelp.success(Transform.convert(entity, CoursePackage.class));
    }

    @RequestMapping(value = "/package/list", method = RequestMethod.GET)
    @ApiOperation(value = "套餐列表", httpMethod = "GET")
    public Response<PageMessage<CoursePackage>> listPackage(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = false) String keyword,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction,
            HttpSession session) {
        Page<CoursePackage> p = coursePackageService.listAdmin(page, size, keyword, order, DirectionStatus.ValueOf(direction));
        List<CoursePackage> pr = Transform.convert(p, CoursePackage.class);
        return ResponseHelp.success(pr, page, size, p.getTotal());
    }

    @RequestMapping(value = "/data/add", method = RequestMethod.POST)
    @ApiOperation(value = "添加资料", httpMethod = "POST")
    public Response<CourseData> addData(@RequestBody @Validated CourseDataDto dto, HttpServletRequest request) {
        CourseData entity = Transform.dtoToEntity(dto);
        entity = courseDataService.add(entity);
        managerLogService.log(request);
        return ResponseHelp.success(Transform.convert(entity, CourseData.class));
    }

    @RequestMapping(value = "/data/edit", method = RequestMethod.PUT)
    @ApiOperation(value = "编辑资料", httpMethod = "PUT")
    public Response<Boolean> editData(@RequestBody @Validated CourseDataDto dto, HttpServletRequest request) {
        CourseData entity = Transform.dtoToEntity(dto);
        entity = courseDataService.edit(entity);
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/data/delete", method = RequestMethod.DELETE)
    @ApiOperation(value = "删除资料", httpMethod = "DELETE")
    public Response<Boolean> deleteData(@RequestParam int id, HttpServletRequest request) {
        courseDataService.delete(id);
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/data/detail", method = RequestMethod.GET)
    @ApiOperation(value = "获取资料", httpMethod = "GET")
    public Response<CourseData> detailData(@RequestParam int id,HttpSession session) {
        CourseData entity = courseDataService.get(id);
        return ResponseHelp.success(Transform.convert(entity, CourseData.class));
    }

    @RequestMapping(value = "/data/list", method = RequestMethod.GET)
    @ApiOperation(value = "资料列表", httpMethod = "GET")
    public Response<PageMessage<CourseData>> listData(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = false) String keyword,
            @RequestParam(required = false) Integer structId,
            @RequestParam(required = false) String dataType,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction,
            HttpSession session) {
        Page<CourseData> p = courseDataService.listAdmin(page, size, keyword, structId, DataType.ValueOf(dataType), order, DirectionStatus.ValueOf(direction));
        List<CourseData> pr = Transform.convert(p, CourseData.class);
        return ResponseHelp.success(pr, page, size, p.getTotal());
    }

    @RequestMapping(value = "/data/history/add", method = RequestMethod.POST)
    @ApiOperation(value = "添加资料历史", httpMethod = "POST")
    public Response<CourseDataHistory> addDataHistory(@RequestBody @Validated CourseDataHistoryDto dto, HttpServletRequest request) {
        CourseDataHistory entity = Transform.dtoToEntity(dto);
        entity = courseDataHistoryService.add(entity);
        CourseData in = courseDataService.get(entity.getDataId());
        CourseData tmp = CourseData.builder()
                .id(entity.getDataId())
                .build();
        if(in.getLatestTime() == null){
            tmp.setLatestTime(entity.getTime());
            courseDataService.edit(tmp);
        }else if(entity.getTime().after(in.getLatestTime())){
            tmp.setLatestTime(entity.getTime());
            courseDataService.edit(tmp);
        }
        asyncTask.postDataUpdate(entity.getId());
        managerLogService.log(request);
        return ResponseHelp.success(Transform.convert(entity, CourseDataHistory.class));
    }

    @RequestMapping(value = "/data/history/edit", method = RequestMethod.PUT)
    @ApiOperation(value = "编辑资料历史", httpMethod = "PUT")
    public Response<Boolean> editDataHistory(@RequestBody @Validated CourseDataHistoryDto dto, HttpServletRequest request) {
        CourseDataHistory entity = Transform.dtoToEntity(dto);
        entity = courseDataHistoryService.edit(entity);
        CourseData in = courseDataService.get(entity.getDataId());
        CourseData tmp = CourseData.builder()
                .id(entity.getDataId())
                .build();
        if(in.getLatestTime() == null){
            tmp.setLatestTime(entity.getTime());
            courseDataService.edit(tmp);
        }else if(entity.getTime().after(in.getLatestTime())){
            tmp.setLatestTime(entity.getTime());
            courseDataService.edit(tmp);
        }
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/data/history/delete", method = RequestMethod.DELETE)
    @ApiOperation(value = "删除资料历史", httpMethod = "DELETE")
    public Response<Boolean> deleteDataHistory(@RequestParam int id, HttpServletRequest request) {
        courseDataHistoryService.delete(id);
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/data/history/list", method = RequestMethod.GET)
    @ApiOperation(value = "资料历史列表", httpMethod = "GET")
    public Response<PageMessage<CourseDataHistory>> listDataHistory(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = true) Integer dataId,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction,
            HttpSession session) {
        Page<CourseDataHistory> p = courseDataHistoryService.listByData(page, size, dataId);
        List<CourseDataHistory> pr = Transform.convert(p, CourseDataHistory.class);
        return ResponseHelp.success(pr, page, size, p.getTotal());
    }

    @RequestMapping(value = "/experience/add", method = RequestMethod.POST)
    @ApiOperation(value = "添加心经", httpMethod = "POST")
    public Response<CourseExperience> addExperience(@RequestBody @Validated CourseExperienceDto dto, HttpServletRequest request) {
        CourseExperience entity = Transform.dtoToEntity(dto);
        entity = courseExperienceService.add(entity);
        managerLogService.log(request);
        return ResponseHelp.success(Transform.convert(entity, CourseExperience.class));
    }

    @RequestMapping(value = "/experience/edit", method = RequestMethod.PUT)
    @ApiOperation(value = "编辑心经", httpMethod = "PUT")
    public Response<Boolean> editExperience(@RequestBody @Validated CourseExperienceDto dto, HttpServletRequest request) {
        CourseExperience entity = Transform.dtoToEntity(dto);
        entity = courseExperienceService.edit(entity);
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/experience/delete", method = RequestMethod.DELETE)
    @ApiOperation(value = "删除心经", httpMethod = "DELETE")
    public Response<Boolean> deleteExperience(@RequestParam int id, HttpServletRequest request) {
        courseExperienceService.delete(id);
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/experience/detail", method = RequestMethod.GET)
    @ApiOperation(value = "获取心经", httpMethod = "GET")
    public Response<CourseExperience> detailExperience(@RequestParam int id,HttpSession session) {
        CourseExperience entity = courseExperienceService.get(id);
        return ResponseHelp.success(Transform.convert(entity, CourseExperience.class));
    }

    @RequestMapping(value = "/experience/list", method = RequestMethod.GET)
    @ApiOperation(value = "心经列表", httpMethod = "GET")
    public Response<PageMessage<CourseExperienceListDto>> listExperience(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = false) Integer userId,
            @RequestParam(required = false) String keyword,
            @RequestParam(required = false) String prepareStatus,
            @RequestParam(required = false) String experienceScore,
            @RequestParam(required = false) String experienceDay,
            @RequestParam(required = false) String experiencePercent,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction,
            HttpSession session) {
        Page<CourseExperience> p = courseExperienceService.listAdmin(page, size, userId, keyword, prepareStatus, ExperienceScoreRange.ValueOf(experienceScore), ExperienceDayRange.ValueOf(experienceDay), experiencePercent, order, DirectionStatus.ValueOf(direction));
        List<CourseExperienceListDto> pr = Transform.convert(p, CourseExperienceListDto.class);

        // 绑定用户
        Collection userIds = Transform.getIds(p, CourseExperience.class, "userId");
        List<User> userList = usersService.select(userIds);
        Transform.combine(pr, userList, CourseExperienceListDto.class, "userId", "user", User.class, "id", UserExtendDto.class);

        return ResponseHelp.success(pr, page, size, p.getTotal());
    }

    @RequestMapping(value = "/teacher/add", method = RequestMethod.POST)
    @ApiOperation(value = "添加老师", httpMethod = "POST")
    public Response<CourseTeacher> addTeacher(@RequestBody @Validated CourseTeacherDto dto, HttpServletRequest request) {
        CourseTeacher entity = Transform.dtoToEntity(dto);
        entity = courseTeacherService.add(entity);
        managerLogService.log(request);
        return ResponseHelp.success(Transform.convert(entity, CourseTeacher.class));
    }

    @RequestMapping(value = "/teacher/edit", method = RequestMethod.PUT)
    @ApiOperation(value = "编辑教师", httpMethod = "PUT")
    public Response<Boolean> editTeacher(@RequestBody @Validated CourseTeacherDto dto, HttpServletRequest request) {
        CourseTeacher entity = Transform.dtoToEntity(dto);
        entity = courseTeacherService.edit(entity);
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/teacher/delete", method = RequestMethod.DELETE)
    @ApiOperation(value = "删除教师", httpMethod = "DELETE")
    public Response<Boolean> deleteTeacher(@RequestParam int id, HttpServletRequest request) {
        courseTeacherService.delete(id);
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/teacher/detail", method = RequestMethod.GET)
    @ApiOperation(value = "获取教师", httpMethod = "GET")
    public Response<CourseTeacher> detailTeacher(@RequestParam int id,HttpSession session) {
        CourseTeacher entity = courseTeacherService.get(id);
        return ResponseHelp.success(Transform.convert(entity, CourseTeacher.class));
    }

    @RequestMapping(value = "/teacher/list", method = RequestMethod.GET)
    @ApiOperation(value = "教师列表", httpMethod = "GET")
    public Response<PageMessage<CourseTeacher>> listTeacher(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = false) Integer courseId,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction,
            HttpSession session) {
        Page<CourseTeacher> p = courseTeacherService.listAdmin(page, size, courseId);
        return ResponseHelp.success(p, page, size, p.getTotal());
    }

    @RequestMapping(value = "/no/add", method = RequestMethod.POST)
    @ApiOperation(value = "添加课时", httpMethod = "POST")
    public Response<CourseNo> addNo(@RequestBody @Validated CourseNoDto dto, HttpServletRequest request) {
        // 查询课时
        CourseNo entity = Transform.dtoToEntity(dto);
        entity = courseNoService.addNo(entity);
        // 统计课时数
        CourseNoStatRelation relation = courseNoService.statCourse(dto.getCourseId());
        courseService.edit(Course.builder().id(dto.getCourseId()).noNumber(relation.getNumber()).time(relation.getNumber()).build());
        managerLogService.log(request);
        return ResponseHelp.success(Transform.convert(entity, CourseNo.class));
    }

    @RequestMapping(value = "/no/edit", method = RequestMethod.PUT)
    @ApiOperation(value = "编辑课时", httpMethod = "PUT")
    public Response<Boolean> editNo(@RequestBody @Validated CourseNoDto dto, HttpServletRequest request) {
        // 调整课时顺序
        CourseNo entity = Transform.dtoToEntity(dto);
        entity = courseNoService.editNo(entity);// 统计课时数
        CourseNoStatRelation relation = courseNoService.statCourse(dto.getCourseId());
        courseService.edit(Course.builder().id(dto.getCourseId()).noNumber(relation.getNumber()).time(relation.getNumber()).build());

        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/no/delete", method = RequestMethod.DELETE)
    @ApiOperation(value = "删除课时", httpMethod = "DELETE")
    public Response<Boolean> deleteNo(@RequestParam int id, HttpServletRequest request) {
        CourseNo in = courseNoService.get(id);
        courseNoService.deleteNo(id);
        // 统计课时数
        CourseNoStatRelation relation = courseNoService.statCourse(in.getCourseId());
        courseService.edit(Course.builder().id(in.getCourseId()).noNumber(relation.getNumber()).time(relation.getNumber()).build());
        // 删除对应预习作业关系
        previewPaperService.removeCourseNo(in.getCourseId(), in.getId());
        previewAssignService.removeCourseNo(in.getCourseId(), in.getId());
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/no/detail", method = RequestMethod.GET)
    @ApiOperation(value = "获取课时", httpMethod = "GET")
    public Response<CourseNo> detailNo(@RequestParam int id,HttpSession session) {
        CourseNo entity = courseNoService.get(id);
        return ResponseHelp.success(Transform.convert(entity, CourseNo.class));
    }

    @RequestMapping(value = "/no/all", method = RequestMethod.GET)
    @ApiOperation(value = "课时列表", httpMethod = "GET")
    public Response<List<CourseNo>> listNo(
            @RequestParam(required = false) Integer courseId,
            HttpSession session) {
        List<CourseNo> p = courseNoService.allCourse(courseId);
        return ResponseHelp.success(p);
    }

    @RequestMapping(value = "/time/add", method = RequestMethod.POST)
    @ApiOperation(value = "添加课时", httpMethod = "POST")
    public Response<CourseTime> addTime(@RequestBody @Validated CourseTimeDto dto, HttpServletRequest request) {
        CourseTime entity = Transform.dtoToEntity(dto);
        entity = courseTimeService.add(entity);
        managerLogService.log(request);
        return ResponseHelp.success(Transform.convert(entity, CourseTime.class));
    }

    @RequestMapping(value = "/time/edit", method = RequestMethod.PUT)
    @ApiOperation(value = "编辑课时", httpMethod = "PUT")
    public Response<Boolean> editTime(@RequestBody @Validated CourseTimeDto dto, HttpServletRequest request) {
        CourseTime entity = Transform.dtoToEntity(dto);
        entity = courseTimeService.edit(entity);
        // 修改所有学员记录
        userOrderRecordService.changeStudentTime(entity.getCourseId(), dto.getId(), entity.getStartTime(), entity.getEndTime());
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/time/delete", method = RequestMethod.DELETE)
    @ApiOperation(value = "删除课时", httpMethod = "DELETE")
    public Response<Boolean> deleteTime(@RequestParam int id, HttpServletRequest request) {
        CourseTime in = courseTimeService.get(id);
        courseTimeService.delete(id);
        // 删除对应预习作业关系
        previewAssignService.removeCourseTime(in.getCourseId(), in.getId());
        // todo 删除对应学生关系
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/time/detail", method = RequestMethod.GET)
    @ApiOperation(value = "获取课时", httpMethod = "GET")
    public Response<CourseTime> detailTime(@RequestParam int id,HttpSession session) {
        CourseTime entity = courseTimeService.get(id);
        return ResponseHelp.success(Transform.convert(entity, CourseTime.class));
    }

    @RequestMapping(value = "/time/list", method = RequestMethod.GET)
    @ApiOperation(value = "课时列表", httpMethod = "GET")
    public Response<PageMessage<CourseTimeInfoDto>> listTime(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = false) Integer[] ids,
            @RequestParam(required = false) Integer courseId,
            @RequestParam(required = false) String keyword,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction,
            HttpSession session) {

        Page<CourseTime> p;
        if (ids != null && ids.length > 0){
            p = courseTimeService.select(ids);
        }else{
            p = courseTimeService.listAdmin(page, size, courseId, keyword);
        }
        List<CourseTimeInfoDto> pr = Transform.convert(p, CourseTimeInfoDto.class);

        // 绑定学生数量
        Collection timeIds = Transform.getIds(p, CourseTime.class, "id");
        List<CourseStudentNumberRelation> relations = userOrderRecordService.groupByCourse(timeIds);
        Map map = Transform.getMap(relations, CourseStudentNumberRelation.class, "id", "number");
        Transform.combine(pr, map, CourseTimeInfoDto.class, "id", "studentNumber");

        return ResponseHelp.success(pr, page, size, p.getTotal());
    }

    @RequestMapping(value = "/student/online/add", method = RequestMethod.POST)
    @ApiOperation(value = "添加学员", httpMethod = "POST")
    public Response<UserOrderRecord> addStudentOnline(@RequestBody @Validated CourseStudentOnlineDto dto, HttpServletRequest request) {
        UserOrderRecord entity = Transform.dtoToEntity(dto);

        CourseTime courseTime = courseTimeService.get(dto.getTimeId());
        if (courseTime == null){
            throw new ParameterException("时间段错误");
        }
        entity.setSource(RecordSource.BACKEND.key);
        entity.setProductType(ProductType.COURSE.key);
        entity.setTimeId(dto.getTimeId());
        entity.setProductId(dto.getCourseId());
        entity.setUseStartTime(courseTime.getStartTime());
        entity.setUseEndTime(courseTime.getEndTime());
        // 计算有效期
        entity.setUseExpireDays((int)(courseTime.getEndTime().getTime() - courseTime.getStartTime().getTime())/86400000);

        // 默认回答时间
        JSONObject askInfo = toolsService.getAskTime(BigDecimal.valueOf(0));
        if (askInfo != null )entity.setAskTime(askInfo.getIntValue("hour") * 3600);

        entity = userOrderRecordService.addStudent(entity);
        managerLogService.log(request);
        return ResponseHelp.success(Transform.convert(entity, UserOrderRecord.class));
    }

    @RequestMapping(value = "/student/online/edit", method = RequestMethod.PUT)
    @ApiOperation(value = "编辑学员", httpMethod = "PUT")
    public Response<Boolean> editStudentOnline(@RequestBody @Validated CourseStudentOnlineDto dto, HttpServletRequest request) {
        UserOrderRecord entity = Transform.dtoToEntity(dto);
        entity = userOrderRecordService.edit(entity);
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/student/online/delete", method = RequestMethod.DELETE)
    @ApiOperation(value = "删除学员", httpMethod = "DELETE")
    public Response<Boolean> deleteStudentOnline(@RequestParam int id, HttpServletRequest request) {
        userOrderRecordService.delete(id);
        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/student/online/detail", method = RequestMethod.GET)
    @ApiOperation(value = "获取学员", httpMethod = "GET")
    public Response<UserOrderRecord> detailStudentOnline(@RequestParam int id,HttpSession session) {
        UserOrderRecord entity = userOrderRecordService.get(id);
        return ResponseHelp.success(Transform.convert(entity, UserOrderRecord.class));
    }

    @RequestMapping(value = "/student/online/list", method = RequestMethod.GET)
    @ApiOperation(value = "课时学员", httpMethod = "GET")
    public Response<PageMessage<CourseStudentOnlineListDto>> listStudentOnline(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = false) Integer courseId,
            @RequestParam(required = false) Integer timeId,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction,
            HttpSession session) {
        Page<UserOrderRecord> p = userOrderRecordService.listAdminByOnline(page, size, courseId, timeId);
        List<CourseStudentOnlineListDto> pr = Transform.convert(p, CourseStudentOnlineListDto.class);

        // 绑定用户
        Collection userIds = Transform.getIds(p, UserOrderRecord.class, "userId");
        List<User> userList = usersService.select(userIds);
        Transform.combine(pr, userList, CourseStudentOnlineListDto.class, "userId", "user", User.class, "id", UserExtendDto.class);

        // 绑定时间段
        Collection timeIds = Transform.getIds(p, UserOrderRecord.class, "no");
        List<CourseTime> timeList = courseTimeService.select(timeIds);
        Transform.combine(pr, timeList, CourseStudentOnlineListDto.class, "no", "time", CourseTime.class, "id", CourseTimeExtendDto.class);

        return ResponseHelp.success(pr, page, size, p.getTotal());
    }

    @RequestMapping(value = "/student/vs/add", method = RequestMethod.POST)
    @ApiOperation(value = "添加vs学员", httpMethod = "POST")
    private Response<Boolean> addStudentVs(@RequestBody @Validated UserCourseRecordDto dto){
        UserOrderRecord entity = Transform.dtoToEntity(dto);
        Course course = courseService.get(dto.getCourseId());
        entity.setProductType(ProductType.COURSE.key);
        entity.setOrderId(0);
        entity.setProductId(dto.getCourseId());
        entity.setTeacherId(dto.getTeacherId());
        entity.setSource(RecordSource.BACKEND.key);
        entity.setNumber(dto.getNumber());
        entity.setExpireDays(course.getExpireDays());
        entity.setUseExpireDays(courseExtendService.computeExpire(dto.getNumber(), course));
        // 预约后开通: 有效期开通后计算
        orderFlowService.addRecord(entity);

        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/student/vs/edit", method = RequestMethod.PUT)
    @ApiOperation(value = "修改vs学员", httpMethod = "PUT")
    private Response<Boolean> editStudentVs(@RequestBody @Validated UserCourseRecordDto dto){
        UserOrderRecord entity = Transform.dtoToEntity(dto);
        UserOrderRecord in = userOrderRecordService.get(entity.getId());
        if (in.getIsUsed() > 0 && !in.getNumber().equals(dto.getNumber())){
            // 已开通,重新计算有效期
            Course course = courseService.get(dto.getCourseId());
            Integer expireDay = courseExtendService.computeExpire(dto.getNumber(), course);
            entity.setEndTime(Tools.addDate(in.getStartTime(), expireDay));
            entity.setNumber(dto.getNumber());
            entity.setUseExpireDays(expireDay);
        }
        userOrderRecordService.edit(entity);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/student/vs/delete", method = RequestMethod.DELETE)
    @ApiOperation(value = "删除vs学员", httpMethod = "DELETE")
    private Response<Boolean> deleteStudentVs(@RequestParam int id){
        userOrderRecordService.delete(id);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/student/vs/list", method = RequestMethod.GET)
    @ApiOperation(value = "获取vs学员", httpMethod = "GET")
    private Response<PageMessage<UserCourseStudentRecordInfoDto>> listStudentVs(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = false) Integer courseId,
            @RequestParam(required = false) Integer userId,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction
    ){
        Page<UserOrderRecord> p = userOrderRecordService.listWithStudentAdmin(page, size, courseId, userId);
        List<UserCourseStudentRecordInfoDto> pr = Transform.convert(p, UserCourseStudentRecordInfoDto.class);

        // 绑定用户
        Collection userIds = Transform.getIds(p, UserOrderRecord.class, "userId");
        List<User> userList = usersService.select(userIds);
        Transform.combine(pr, userList, UserCourseStudentRecordInfoDto.class, "userId", "user", User.class, "id", UserExtendDto.class);

        // 绑定教师
        Collection teacherIds = Transform.getIds(p, UserOrderRecord.class, "teacherId");
        List<CourseTeacher> teacherList = courseTeacherService.select(teacherIds);
        Transform.combine(pr, teacherList, UserCourseStudentRecordInfoDto.class, "teacherId", "teacher", CourseTeacher.class, "id", CourseTeacherExtendDto.class);

        return ResponseHelp.success(pr, page, size, p.getTotal());
    }

    @RequestMapping(value = "/study/list", method = RequestMethod.GET)
    @ApiOperation(value = "获取学习记录", httpMethod = "GET")
    private Response<PageMessage<UserCourseStudyRecordInfoDto>> listStudy(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = false) Integer[] ids,
            @RequestParam(required = false) String courseModule,
            @RequestParam(required = false) Integer structId,
            @RequestParam(required = false) Integer courseId,
            @RequestParam(required = false) Integer userId,
            @RequestParam(required = false) String teacher,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction
    ){
        Page<UserOrderRecord> p;
        if (ids != null && ids.length > 0){
            p = userOrderRecordService.select(ids);
        }else{
            p = userOrderRecordService.listWithStudyAdmin(page, size, courseModule != null ? new String[]{courseModule} : null, structId, courseId, userId, teacher, order, DirectionStatus.ValueOf(direction));
        }
        List<UserCourseStudyRecordInfoDto> pr = Transform.convert(p, UserCourseStudyRecordInfoDto.class);

        // 绑定用户
        Collection userIds = Transform.getIds(p, UserOrderRecord.class, "userId");
        List<User> userList = usersService.select(userIds);
        Transform.combine(pr, userList, UserCourseStudyRecordInfoDto.class, "userId", "user", User.class, "id", UserExtendDto.class);

        // 绑定课程
        Map courseMap = Transform.getMap(p, UserOrderRecord.class, "id", "productId");
        Transform.combine(pr, courseMap, UserCourseStudyRecordInfoDto.class, "id", "courseId");
        Collection courseIds = Transform.getIds(p, UserOrderRecord.class, "productId");
        List<Course> courseList = courseService.select(courseIds);
        Transform.combine(pr, courseList, UserCourseStudyRecordInfoDto.class, "courseId", "course", Course.class, "id", CourseExtendDto.class);

        // 绑定老师
        Collection teacherIds = Transform.getIds(p, UserOrderRecord.class, "teacherId");
        List<CourseTeacher> teacherList = courseTeacherService.select(teacherIds);
        Map teacherMap = Transform.getMap(teacherList, CourseTeacher.class,"id", "realname");
        Transform.combine(pr, teacherMap, UserCourseStudyRecordInfoDto.class, "teacherId", "teacher");

        // 学习记录
        Collection recordIds = Transform.getIds(p, UserOrderRecord.class, "id");
        List<UserCourseRecord> userCourseRecordList = userCourseRecordService.listWithLast(recordIds);
        Map recordMap = Transform.getMap(userCourseRecordList, UserCourseRecord.class,"recordId", "createTime");
        Transform.combine(pr, recordMap, UserCourseStudyRecordInfoDto.class, "id", "lastTime");

        return ResponseHelp.success(pr, page, size, p.getTotal());
    }



    @RequestMapping(value = "/ask/edit", method = RequestMethod.PUT)
    @ApiOperation(value = "修改提问信息", httpMethod = "PUT")
    public Response<Boolean> edit(@RequestBody @Validated UserAskCourseDto dto, HttpServletRequest request) {
        UserAskCourse entity = Transform.dtoToEntity(dto);
        UserAskCourse in = userAskCourseService.get(entity.getId());
        // 调整回答
        if(entity.getAnswer() != null && (!entity.getAnswer().isEmpty() || !in.getAnswer().equals(entity.getAnswer()))){
            entity.setAnswerTime(new Date());
            entity.setAnswerStatus(AnswerStatus.ANSWER.index);
            Manager manager = shiroHelp.getLoginManager();
            entity.setManagerId(manager.getId());
            User user = usersService.get(in.getUserId());
            messageExtendService.sendAskCourse(user, entity);
        }
        if (dto.getIgnoreStatus() != null && dto.getIgnoreStatus() > 0){
            entity.setAnswerStatus(AnswerStatus.IGNORE.index);
        }

        entity = userAskCourseService.edit(entity);

        if (dto.getOther() !=null && dto.getOther().length > 0){
            // 更新回答排序
            userAskCourseService.updateOrder(dto.getOther());
        }

        managerLogService.log(request);
        return ResponseHelp.success(true);
    }

    @RequestMapping(value = "/ask/detail", method = RequestMethod.GET)
    @ApiOperation(value = "提问详情", httpMethod = "GET")
    public Response<UserAskCourseDetailDto> detail(@RequestParam int id, HttpServletRequest request) {
        UserAskCourse entity = userAskCourseService.get(id);
        UserAskCourseDetailDto dto = Transform.convert(entity, UserAskCourseDetailDto.class);

        if (entity.getManagerId() != null && entity.getManagerId() > 0){
            Manager manager = managerService.get(entity.getManagerId());
            if (manager != null)
                dto.setManager(Transform.convert(manager, ManagerExtendDto.class));
        }

        User user = usersService.get(entity.getUserId());
        dto.setUser(Transform.convert(user, UserExtendDto.class));

        Course course = courseService.get(entity.getCourseId());
        dto.setCourse(Transform.convert(course, CourseExtendDto.class));

        CourseNo courseNo = courseNoService.get(entity.getCourseNoId());
        dto.setCourseNo(Transform.convert(courseNo, CourseNoExtendDto.class));

        // 所有回答
        List<UserAskCourse> userAskList = userAskCourseService.listByCoursePosition(entity.getCourseNoId(), entity.getPosition(), true);
        dto.setOthers(Transform.convert(userAskList, UserAskCourseExtendDto.class));
        return ResponseHelp.success(dto);
    }

    @RequestMapping(value = "/ask/list", method = RequestMethod.GET)
    @ApiOperation(value = "提问列表", httpMethod = "GET")
    public Response<PageMessage<UserAskCourseListDto>> list(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = false) Integer structId,
            @RequestParam(required = false) Integer courseId,
            @RequestParam(required = false) Integer answerStatus,
            @RequestParam(required = false) Integer showStatus,
            @RequestParam(required = false) Integer userId,
            @RequestParam(required = false) Integer moneyRang,
            @RequestParam(required = false) String startTime,
            @RequestParam(required = false) String endTime,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction,
            HttpSession session) {
        Page<UserAskCourse> p = userAskCourseService.listAdmin(page, size, structId, courseId, AnswerStatus.ValueOf(answerStatus), showStatus, userId, MoneyRange.ValueOf(moneyRang), startTime, endTime, order, DirectionStatus.ValueOf(direction));
        List<UserAskCourseListDto> pr = Transform.convert(p, UserAskCourseListDto.class);

        // 绑定用户
        Collection userIds = Transform.getIds(p, UserAskQuestion.class, "userId");
        List<User> userList = usersService.select(userIds);
        Transform.combine(pr, userList, UserAskQuestionListDto.class, "userId", "user", User.class, "id", UserExtendDto.class);

        // 绑定管理员
        Collection managerIds = Transform.getIds(p, UserAskQuestion.class, "managerId");
        List<Manager> managerList = managerService.select(managerIds);
        Transform.combine(pr, managerList, UserAskQuestionListDto.class, "managerId", "manager", Manager.class, "id", ManagerExtendDto.class);

        // 绑定课程
        Collection courseIds = Transform.getIds(p, UserAskCourse.class, "courseId");
        List<Course> courseList = courseService.select(courseIds);
        Transform.combine(pr, courseList, UserAskCourseListDto.class, "courseId", "course", Course.class, "id", CourseExtendDto.class);

        // 绑定课时
        Collection courseNoIds = Transform.getIds(p, UserAskCourse.class, "courseNoId");
        List<CourseNo> courseNoList = courseNoService.select(courseNoIds);
        Transform.combine(pr, courseNoList, UserAskCourseListDto.class, "courseNoId", "courseNo", CourseNo.class, "id", CourseNoExtendDto.class);

        return ResponseHelp.success(pr, page, size, p.getTotal());
    }
}