package com.yonge.cooleshow.biz.dal.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yonge.cooleshow.biz.dal.dao.CourseScheduleDao;
import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
import com.yonge.cooleshow.biz.dal.dto.search.HomeworkSearch;
import com.yonge.cooleshow.biz.dal.dto.search.MyCourseSearch;
import com.yonge.cooleshow.biz.dal.dto.search.PracticeTeacherSearch;
import com.yonge.cooleshow.biz.dal.entity.CourseCalendarEntity;
import com.yonge.cooleshow.biz.dal.entity.CourseSchedule;
import com.yonge.cooleshow.biz.dal.entity.TeacherSubjectPrice;
import com.yonge.cooleshow.biz.dal.vo.*;
import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.enums.YesOrNoEnum;
import com.yonge.toolset.base.page.PageInfo;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

/**
 * 老师课程表(CourseSchedule)表服务接口
 *
 * @author hgw
 * @since 2022-03-18 15:29:11
 */
public interface CourseScheduleService extends IService<CourseSchedule> {

    CourseScheduleDao getDao();

    /**
     * 老师端-首页-我的课程-直播课
     *
     * @param param 传入参数
     *              <p> - classDate 年月
     *              <p> - row 条数
     *              <p> - page 页数
     *              <p> - status 课程状态 NOT_START未开始 ING进行中 COMPLETE已完成
     */
    PageInfo<TeacherLiveCourseInfoVo> queryTeacherLiveCourse(Map<String, Object> param);

    /**
     * 校验该学生大于当前时间并未开始的课程时间和传入时间段有没有交集
     *
     * @param studentId 学生id
     * @param startTime 新增课程 开始时间
     * @param endTime   新增课程 结束时间
     * @return true 被占用 false 没有被占用
     */
    boolean checkStudentCourseTime(Long studentId, Date startTime, Date endTime);

    /**
     * 校验老师这个时间段有没有被占用-校验课时
     *
     * @param teacherId 老师id
     * @param startTime 新增课程 开始时间
     * @param endTime   新增课程 结束时间
     * @return true 被占用 false 没有被占用
     */
    boolean checkTeacherCourseTime(Long teacherId, Date startTime, Date endTime);

    /**
     * 查询这个课程列表中时间是否有重叠
     * <p>案例：1
     * <p>已有9:00~ 10:00 课程
     * <p>新增课程 09:10~ 09:40
     * <p>返回 true
     *
     * <p>案例：2
     * <p>已有9:00~ 10:00 课程
     * <p>新增课程 08:45~ 09:40
     * <p>返回 true
     *
     * <p>案例：3
     * <p>已有9:00~ 10:00 课程
     * <p>新增课程 10:00~ 10:40
     * <p>返回 false
     *
     * @param list         时间列表
     * @param startTimeFun 获取现课程开始时间
     * @param endTimeFun   获取现课程结束时间
     * @param startTime    新增课程开始时间
     * @param endTime      新增课程结束时间
     * @return true 被占用 false 没有被占用
     */
    <T> boolean checkCourseTime(List<T> list, Function<T, Date> startTimeFun, Function<T, Date> endTimeFun,
                                Date startTime, Date endTime);

    /**
     * 创建直播课时选课时的日历
     * <P>主要查询该老师目前的课程时间
     * <P>根据传入的单课时时长将时间分片后来匹配数据库中课程时间，得到每日空余时间
     *
     * @param param 传入参数
     *              <p> - teacherId 老师id
     *              <p> - year 年
     *              <p> - month 月
     *              <p> - singleCourseMinutes 单课时时长(不包含休息时间)
     *              <p> - freeCourseMinutes 单课时休息时长
     * @return 返回传入时间当月每日的剩余时间段
     */
    List<CourseCalendarEntity> createLiveCourseCalendar(Map<String, Object> param);

    /**
     * 根据年份获取当年节假日
     *
     * @param year 年
     * @return 年月日
     */
    List<String> getHoliday(int year);

    /**
     * 生成陪练课日历-用于学生购买指定老师陪练课
     *
     * @param param 传入参数
     *              <p> - teacherId 老师id
     *              <p> - studentId 学生id
     *              <p> - year 年
     *              <p> - month 月
     *              <p> - day 日
     * @return 返回传入时间当月每日的剩余时间段
     */
    List<CourseCalendarEntity> createPracticeCourseCalender(Map<String, Object> param);

    IPage<MyCourseVo> queryTeacherPracticeCourse(IPage<MyCourseVo> page, MyCourseSearch search);

    /**
     * 老师未布置的课程作业数量
     * 陪练课 课程状态为完成，有学生考勤记录 没有布置作业
     *
     * @param homeworkSearch 查询信息
     * @return number
     */
    Integer countTeacherNoDecorateHomework(HomeworkSearch homeworkSearch);

    Set<String> queryCourseSchedule(MyCourseSearch search);

    IPage<MyCourseVo> queryStudentPracticeCourse(IPage<MyCourseVo> page, MyCourseSearch search);

    /**
     * 检查课程是否属于老师
     *
     * @param teacherId 老师id
     * @param courseId  课程id
     * @return boolean true 属于老师
     */
    boolean checkTeacherCourseSchedule(Long teacherId, Long courseId);

    Set<String> queryCourseScheduleStudent(MyCourseSearch search);

    /**
     * 检查学生是否购买课程
     *
     * @param studentId 学生id
     * @param courseId  课程id
     * @return boolean true 购买
     */
    boolean checkStudentCourseSchedule(Long studentId, Long courseId);

    Map<String, Object> queryCourseUser(MyCourseSearch search);

    IPage<PracticeTeacherVo> teacherList(IPage<PracticeTeacherVo> page, PracticeTeacherSearch search);

    Map<String, Object> queryCourseTeacher(MyCourseSearch search);

    /**
     * 学生-查询直播课
     *
     * @param param 传入参数
     *              <p> - studentId 学生id
     *              <p> - courseState 课程状态 NOT_START未开始 ING进行中 COMPLETE已完成 CANCEL已取消
     *              <p> - classDate 查询时间-年月
     *              <p> - subjectId 声部id
     */
    PageInfo<CourseStudent> queryStudentLiveCourse(Map<String, Object> param);

    HttpResponseResult<OrderCreateRes> buyPracticeCourse(OrderReq.OrderReqInfo orderReqInfo);

    void buyPracticeCourseSuccess(UserOrderDetailVo orderParam);

    void buyPracticeCourseFailed(UserOrderDetailVo orderParam);

    void courseAdjust(CourseAdjustVo adjustVo, Long teacherId);

    StudentHomePage queryLiveAndVideo(Long studentId, Long teacherId, YesOrNoEnum appAuditVersion);

    List<TeacherSubjectPrice> teacherSubjectPrice(Long teacherId);

    /**
     * 本周剩余的课时
     *
     * @param userId 老师id
     * @return 剩余课时数
     */
    Integer getWeekNotStart(Long userId);

    /**
     * 本周未布置课后作业数
     *
     * @param userId 老师id
     * @return 本周未布置课后作业数
     */
    Integer getHomeworkNotDecorate(Long userId);

    /**
     * 老师未课后评价课程数
     *
     * @param userId 老师id
     * @return 老师未课后评价课程数
     */
    Integer getNotRepliedCourseSchedule(Long userId);

    /**
     * 老师本周收到的评价
     *
     * @param userId 老师id
     * @return 老师本周收到的评价
     */
    Integer getWeekStudentRepliedCourseSchedule(Long userId);

    void courseRemind();

    /**
     * 发送"当日陪练课未评价/布置作业
     * （每晚9点30，已评价/已布置不发）"
     */
    void sendTodayNotRepliedAndNotDecorateHomework();

    Map<String, String> selectRoomConfig();

    List<Long> getTeacherId(Integer amount);

    void scheduleTask();

    void teacherSalaryTask();

    PianoRoomTimeVo selectRemainTime(Long teacherId);

    PageInfo<CourseStudentVo> selectStudent(Map<String, Object> param);

    void arrangeCourse(ArrangeCourseVo arrangeCourseVo, Long teacherId);

    Map<String, Object> selectConsumeTime(String month, Long teacherId);

    PageInfo<CourseScheduleRecordVo> selectConsumeTimeList(Map<String, Object> param);

    void deleteCourse(Map<String, Object> param);

    void updateCourseTime(Map<String, Object> param);

    void updateCourseStudent(Map<String, Object> param);

    PageInfo<CourseScheduleRecordVo> selectCourseList(Map<String, Object> param);

    IPage<PianoClassVo> queryPianoClass(IPage<PianoClassVo> page, MyCourseSearch search);
}

