package com.ruoyi.education.service.impl;

import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.education.mapper.EduCourseScheduleMapper;
import com.ruoyi.education.mapper.EduCourseClassMapper;
import com.ruoyi.education.domain.EduCourseSchedule;
import com.ruoyi.education.domain.EduCourseClass;
import com.ruoyi.education.service.IEduCourseScheduleService;

/**
 * 开课节次安排Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-09-26
 */
@Service
public class EduCourseScheduleServiceImpl implements IEduCourseScheduleService 
{
    @Autowired
    private EduCourseScheduleMapper eduCourseScheduleMapper;
    
    @Autowired
    private EduCourseClassMapper eduCourseClassMapper;

    /**
     * 查询开课节次安排
     * 
     * @param scheduleId 开课节次安排主键
     * @return 开课节次安排
     */
    @Override
    public EduCourseSchedule selectEduCourseScheduleByScheduleId(Long scheduleId)
    {
        return eduCourseScheduleMapper.selectEduCourseScheduleByScheduleId(scheduleId);
    }

    /**
     * 查询开课节次安排列表
     * 
     * @param eduCourseSchedule 开课节次安排
     * @return 开课节次安排
     */
    @Override
    public List<EduCourseSchedule> selectEduCourseScheduleList(EduCourseSchedule eduCourseSchedule)
    {
        return eduCourseScheduleMapper.selectEduCourseScheduleList(eduCourseSchedule);
    }

    /**
     * 新增开课节次安排
     * 
     * @param eduCourseSchedule 开课节次安排
     * @return 结果
     */
    @Override
    public int insertEduCourseSchedule(EduCourseSchedule eduCourseSchedule)
    {
        eduCourseSchedule.setCreateTime(DateUtils.getNowDate());
        return eduCourseScheduleMapper.insertEduCourseSchedule(eduCourseSchedule);
    }

    /**
     * 修改开课节次安排
     * 
     * @param eduCourseSchedule 开课节次安排
     * @return 结果
     */
    @Override
    public int updateEduCourseSchedule(EduCourseSchedule eduCourseSchedule)
    {
        eduCourseSchedule.setUpdateTime(DateUtils.getNowDate());
        return eduCourseScheduleMapper.updateEduCourseSchedule(eduCourseSchedule);
    }

    /**
     * 批量删除开课节次安排
     * 
     * @param scheduleIds 需要删除的开课节次安排主键
     * @return 结果
     */
    @Override
    public int deleteEduCourseScheduleByScheduleIds(Long[] scheduleIds)
    {
        return eduCourseScheduleMapper.deleteEduCourseScheduleByScheduleIds(scheduleIds);
    }

    /**
     * 删除开课节次安排信息
     * 
     * @param scheduleId 开课节次安排主键
     * @return 结果
     */
    @Override
    public int deleteEduCourseScheduleByScheduleId(Long scheduleId)
    {
        return eduCourseScheduleMapper.deleteEduCourseScheduleByScheduleId(scheduleId);
    }

    /**
     * 根据开课ID查询节次安排
     * 
     * @param classId 开课ID
     * @return 节次安排集合
     */
    @Override
    public List<EduCourseSchedule> selectScheduleByClassId(Long classId)
    {
        return eduCourseScheduleMapper.selectScheduleByClassId(classId);
    }

    /**
     * 根据开课ID删除节次安排
     * 
     * @param classId 开课ID
     * @return 结果
     */
    @Override
    public int deleteScheduleByClassId(Long classId)
    {
        return eduCourseScheduleMapper.deleteScheduleByClassId(classId);
    }

    /**
     * 查询指定教室的课程安排
     * 
     * @param classroomId 教室ID
     * @param semesterId 学期ID
     * @return 课程安排集合
     */
    @Override
    public List<EduCourseSchedule> selectScheduleByClassroom(Long classroomId, Long semesterId)
    {
        return eduCourseScheduleMapper.selectScheduleByClassroom(classroomId, semesterId);
    }

    /**
     * 查询指定教师的课程安排
     * 
     * @param teacherId 教师ID
     * @param semesterId 学期ID
     * @return 课程安排集合
     */
    @Override
    public List<EduCourseSchedule> selectScheduleByTeacher(Long teacherId, Long semesterId)
    {
        return eduCourseScheduleMapper.selectScheduleByTeacher(teacherId, semesterId);
    }

    /**
     * 查询指定学期的所有课程安排
     * 
     * @param semesterId 学期ID
     * @return 课程安排集合
     */
    @Override
    public List<EduCourseSchedule> selectScheduleBySemester(Long semesterId)
    {
        return eduCourseScheduleMapper.selectScheduleBySemester(semesterId);
    }

    /**
     * 检查时间冲突
     * 
     * @param eduCourseSchedule 节次安排
     * @return 结果
     */
    @Override
    public String checkTimeConflict(EduCourseSchedule eduCourseSchedule)
    {
        String classroomResult = checkClassroomTimeConflict(eduCourseSchedule);
        if (!"NO_CONFLICT".equals(classroomResult))
        {
            return classroomResult;
        }
        
        String teacherResult = checkTeacherTimeConflict(eduCourseSchedule);
        if (!"NO_CONFLICT".equals(teacherResult))
        {
            return teacherResult;
        }
        
        return "NO_CONFLICT";
    }

    /**
     * 检查教室时间冲突
     * 
     * @param eduCourseSchedule 节次安排
     * @return 结果
     */
    @Override
    public String checkClassroomTimeConflict(EduCourseSchedule eduCourseSchedule)
    {
        if (eduCourseSchedule.getClassroomId() == null || eduCourseSchedule.getWeekday() == null ||
            eduCourseSchedule.getPeriodStart() == null || eduCourseSchedule.getPeriodEnd() == null)
        {
            return "NO_CONFLICT";
        }
        
        EduCourseClass courseClass = eduCourseClassMapper.selectEduCourseClassByClassId(eduCourseSchedule.getClassId());
        if (courseClass == null)
        {
            return "NO_CONFLICT";
        }
        
        int conflictCount = eduCourseScheduleMapper.checkClassroomTimeConflict(
            eduCourseSchedule.getClassroomId(),
            eduCourseSchedule.getWeekday(),
            eduCourseSchedule.getPeriodStart(),
            eduCourseSchedule.getPeriodEnd(),
            eduCourseSchedule.getWeeks(),
            eduCourseSchedule.getScheduleId()
        );
        
        return conflictCount > 0 ? "CLASSROOM_CONFLICT" : "NO_CONFLICT";
    }

    /**
     * 检查教师时间冲突
     * 
     * @param eduCourseSchedule 节次安排
     * @return 结果
     */
    @Override
    public String checkTeacherTimeConflict(EduCourseSchedule eduCourseSchedule)
    {
        if (eduCourseSchedule.getClassId() == null || eduCourseSchedule.getWeekday() == null ||
            eduCourseSchedule.getPeriodStart() == null || eduCourseSchedule.getPeriodEnd() == null)
        {
            return "NO_CONFLICT";
        }
        
        EduCourseClass courseClass = eduCourseClassMapper.selectEduCourseClassByClassId(eduCourseSchedule.getClassId());
        if (courseClass == null || courseClass.getTeacherId() == null)
        {
            return "NO_CONFLICT";
        }
        
        int conflictCount = eduCourseScheduleMapper.checkTeacherTimeConflict(
            courseClass.getTeacherId(),
            eduCourseSchedule.getWeekday(),
            eduCourseSchedule.getPeriodStart(),
            eduCourseSchedule.getPeriodEnd(),
            eduCourseSchedule.getWeeks(),
            eduCourseSchedule.getScheduleId()
        );
        
        return conflictCount > 0 ? "TEACHER_CONFLICT" : "NO_CONFLICT";
    }

    /**
     * 校验节次设置是否合理
     * 
     * @param eduCourseSchedule 节次安排
     * @return 结果
     */
    @Override
    public String checkPeriodValid(EduCourseSchedule eduCourseSchedule)
    {
        if (eduCourseSchedule.getWeekday() == null || eduCourseSchedule.getWeekday() < 1 || eduCourseSchedule.getWeekday() > 7)
        {
            return "INVALID_WEEKDAY";
        }
        
        if (eduCourseSchedule.getPeriodStart() == null || eduCourseSchedule.getPeriodStart() < 1 || eduCourseSchedule.getPeriodStart() > 12)
        {
            return "INVALID_PERIOD_START";
        }
        
        if (eduCourseSchedule.getPeriodEnd() == null || eduCourseSchedule.getPeriodEnd() < 1 || eduCourseSchedule.getPeriodEnd() > 12)
        {
            return "INVALID_PERIOD_END";
        }
        
        if (eduCourseSchedule.getPeriodStart() > eduCourseSchedule.getPeriodEnd())
        {
            return "PERIOD_START_AFTER_END";
        }
        
        if (eduCourseSchedule.getPeriodEnd() - eduCourseSchedule.getPeriodStart() > 3)
        {
            return "PERIOD_TOO_LONG";
        }
        
        return "VALID";
    }

    /**
     * 生成课表数据 - 按教室
     * 
     * @param classroomId 教室ID
     * @param semesterId 学期ID
     * @return 课表数据
     */
    @Override
    public List<EduCourseSchedule> generateClassroomTimetable(Long classroomId, Long semesterId)
    {
        return eduCourseScheduleMapper.generateClassroomTimetable(classroomId, semesterId);
    }

    /**
     * 生成课表数据 - 按教师
     * 
     * @param teacherId 教师ID
     * @param semesterId 学期ID
     * @return 课表数据
     */
    @Override
    public List<EduCourseSchedule> generateTeacherTimetable(Long teacherId, Long semesterId)
    {
        return eduCourseScheduleMapper.generateTeacherTimetable(teacherId, semesterId);
    }

    /**
     * 批量添加节次安排
     * 
     * @param classId 开课ID
     * @param scheduleList 节次安排列表
     * @return 结果
     */
    @Override
    @Transactional
    public int batchAddSchedule(Long classId, List<EduCourseSchedule> scheduleList)
    {
        if (scheduleList == null || scheduleList.isEmpty())
        {
            return 0;
        }
        
        for (EduCourseSchedule schedule : scheduleList)
        {
            schedule.setClassId(classId);
            schedule.setCreateBy(SecurityUtils.getUsername());
        }
        
        return eduCourseScheduleMapper.batchInsertSchedule(scheduleList);
    }

    /**
     * 复制节次安排
     * 
     * @param sourceClassId 源开课ID
     * @param targetClassId 目标开课ID
     * @return 结果
     */
    @Override
    @Transactional
    public int copySchedule(Long sourceClassId, Long targetClassId)
    {
        List<EduCourseSchedule> sourceSchedules = eduCourseScheduleMapper.selectScheduleByClassId(sourceClassId);
        if (sourceSchedules.isEmpty())
        {
            return 0;
        }
        
        List<EduCourseSchedule> targetSchedules = new ArrayList<>();
        for (EduCourseSchedule sourceSchedule : sourceSchedules)
        {
            EduCourseSchedule targetSchedule = new EduCourseSchedule();
            targetSchedule.setClassId(targetClassId);
            targetSchedule.setWeekday(sourceSchedule.getWeekday());
            targetSchedule.setPeriodStart(sourceSchedule.getPeriodStart());
            targetSchedule.setPeriodEnd(sourceSchedule.getPeriodEnd());
            targetSchedule.setWeeks(sourceSchedule.getWeeks());
            targetSchedule.setClassroomId(sourceSchedule.getClassroomId());
            targetSchedule.setRemark(sourceSchedule.getRemark());
            targetSchedule.setCreateBy(SecurityUtils.getUsername());
            targetSchedules.add(targetSchedule);
        }
        
        return eduCourseScheduleMapper.batchInsertSchedule(targetSchedules);
    }

    /**
     * 自动排课
     * 
     * @param classId 开课ID
     * @param semesterId 学期ID
     * @param courseHours 课程总学时
     * @return 结果
     */
    @Override
    public String autoSchedule(Long classId, Long semesterId, Integer courseHours)
    {
        return "AUTO_SCHEDULE_NOT_IMPLEMENTED";
    }

    /**
     * 获取时间段统计信息
     * 
     * @param semesterId 学期ID
     * @return 统计结果
     */
    @Override
    public Object getTimeSlotStatistics(Long semesterId)
    {
        List<EduCourseSchedule> scheduleList = eduCourseScheduleMapper.selectScheduleBySemester(semesterId);
        
        Map<String, Object> statistics = new HashMap<>();
        Map<String, Integer> weekdayCount = new HashMap<>();
        Map<String, Integer> periodCount = new HashMap<>();
        
        for (EduCourseSchedule schedule : scheduleList)
        {
            String weekdayKey = "weekday_" + schedule.getWeekday();
            weekdayCount.put(weekdayKey, weekdayCount.getOrDefault(weekdayKey, 0) + 1);
            
            for (int period = schedule.getPeriodStart(); period <= schedule.getPeriodEnd(); period++)
            {
                String periodKey = "period_" + period;
                periodCount.put(periodKey, periodCount.getOrDefault(periodKey, 0) + 1);
            }
        }
        
        statistics.put("totalSchedules", scheduleList.size());
        statistics.put("weekdayDistribution", weekdayCount);
        statistics.put("periodDistribution", periodCount);
        
        return statistics;
    }

    /**
     * 检查周次范围是否合理
     * 
     * @param weeks 周次字符串
     * @return 结果
     */
    @Override
    public String checkWeeksValid(String weeks)
    {
        if (StringUtils.isEmpty(weeks))
        {
            return "VALID";
        }
        
        Pattern pattern = Pattern.compile("^[0-9,-]+$");
        if (!pattern.matcher(weeks).matches())
        {
            return "INVALID_FORMAT";
        }
        
        String[] ranges = weeks.split(",");
        for (String range : ranges)
        {
            if (range.contains("-"))
            {
                String[] parts = range.split("-");
                if (parts.length != 2)
                {
                    return "INVALID_RANGE";
                }
                try
                {
                    int start = Integer.parseInt(parts[0].trim());
                    int end = Integer.parseInt(parts[1].trim());
                    if (start <= 0 || end <= 0 || start > end || end > 25)
                    {
                        return "INVALID_WEEK_NUMBER";
                    }
                }
                catch (NumberFormatException e)
                {
                    return "INVALID_NUMBER";
                }
            }
            else
            {
                try
                {
                    int week = Integer.parseInt(range.trim());
                    if (week <= 0 || week > 25)
                    {
                        return "INVALID_WEEK_NUMBER";
                    }
                }
                catch (NumberFormatException e)
                {
                    return "INVALID_NUMBER";
                }
            }
        }
        
        return "VALID";
    }
}