package com.lesingle.edu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lesingle.edu.common.enums.ErrorCode;
import com.lesingle.edu.common.exception.BusinessException;
import com.alibaba.fastjson2.JSON;
import com.lesingle.edu.dto.request.LessonCreateRequest;
import com.lesingle.edu.dto.request.LessonUpdateRequest;
import com.lesingle.edu.dto.request.LessonProgressRequest;
import com.lesingle.edu.dto.request.StudentRecordRequest;
import com.lesingle.edu.dto.response.StudentRecordsResponse;
import com.lesingle.edu.dto.response.StudentWithRecordResponse;
import com.lesingle.edu.common.enums.LessonStatus;
import com.lesingle.edu.entity.Clazz;
import com.lesingle.edu.entity.Lesson;
import com.lesingle.edu.entity.Student;
import com.lesingle.edu.entity.LessonFeedback;
import com.lesingle.edu.entity.SchedulePlan;
import com.lesingle.edu.entity.StudentRecord;
import com.lesingle.edu.mapper.ClazzMapper;
import com.lesingle.edu.mapper.LessonFeedbackMapper;
import com.lesingle.edu.mapper.CoursePackageMapper;
import com.lesingle.edu.mapper.LessonMapper;
import com.lesingle.edu.mapper.SchedulePlanMapper;
import com.lesingle.edu.mapper.StudentRecordMapper;
import com.lesingle.edu.service.LessonService;
import com.lesingle.edu.service.StudentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class LessonServiceImpl extends ServiceImpl<LessonMapper, Lesson>
    implements LessonService {

    private final LessonMapper lessonMapper;
    private final StudentRecordMapper studentRecordMapper;
    private final LessonFeedbackMapper lessonFeedbackMapper;
    private final SchedulePlanMapper schedulePlanMapper;
    private final CoursePackageMapper coursePackageMapper;
    private final ClazzMapper clazzMapper;
    private final StudentService studentService;
    private final com.lesingle.edu.common.mapper.StudentRecordMapper studentRecordVoMapper;

    @Override
    @Transactional
    public Lesson createLesson(Long tenantId, LessonCreateRequest request) {
        Lesson lesson = new Lesson();
        lesson.setTenantId(tenantId);
        lesson.setCourseId(request.getCourseId());
        lesson.setClassId(request.getClassId());
        lesson.setTeacherId(request.getTeacherId());
        lesson.setTitle(request.getTitle());
        lesson.setLessonDate(request.getLessonDate());
        lesson.setStartTime(request.getStartTime());
        lesson.setEndTime(request.getEndTime());
        lesson.setLocation(request.getLocation());
        lesson.setNotes(request.getNotes());
        lesson.setStatus(LessonStatus.SCHEDULED.getCode());

        lessonMapper.insert(lesson);
        log.info("课程创建成功：id={}, title={}", lesson.getId(), lesson.getTitle());

        // 更新课程包统计：使用次数 +1
        if (request.getCourseId() != null) {
            coursePackageMapper.incrementUsageCount(request.getCourseId());
            log.info("课程包使用次数 +1: courseId={}", request.getCourseId());
        }
        return lesson;
    }

    @Override
    @Transactional
    public Lesson updateLesson(Long id, LessonUpdateRequest request) {
        Lesson lesson = getLessonById(id);

        if (StringUtils.hasText(request.getTitle())) {
            lesson.setTitle(request.getTitle());
        }
        if (request.getLessonDate() != null) {
            lesson.setLessonDate(request.getLessonDate());
        }
        if (request.getStartTime() != null) {
            lesson.setStartTime(request.getStartTime());
        }
        if (request.getEndTime() != null) {
            lesson.setEndTime(request.getEndTime());
        }
        if (request.getLocation() != null) {
            lesson.setLocation(request.getLocation());
        }
        if (StringUtils.hasText(request.getStatus())) {
            lesson.setStatus(request.getStatus());
        }
        if (request.getNotes() != null) {
            lesson.setNotes(request.getNotes());
        }

        lessonMapper.updateById(lesson);
        log.info("课程更新成功：id={}", id);
        return lesson;
    }

    @Override
    public Lesson getLessonById(Long id) {
        Lesson lesson = lessonMapper.selectById(id);
        if (lesson == null) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND, "课程不存在");
        }
        return lesson;
    }

    @Override
    public Page<Lesson> getLessonPage(Long tenantId, Integer pageNum, Integer pageSize, Long classId, Long teacherId, String status, LocalDate startDate, LocalDate endDate) {
        Page<Lesson> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Lesson> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(Lesson::getTenantId, tenantId);

        if (classId != null) {
            wrapper.eq(Lesson::getClassId, classId);
        }
        if (teacherId != null) {
            wrapper.eq(Lesson::getTeacherId, teacherId);
        }
        if (StringUtils.hasText(status)) {
            wrapper.eq(Lesson::getStatus, status);
        }
        if (startDate != null) {
            wrapper.ge(Lesson::getLessonDate, startDate);
        }
        if (endDate != null) {
            wrapper.le(Lesson::getLessonDate, endDate);
        }
        wrapper.orderByAsc(Lesson::getLessonDate, Lesson::getStartTime);

        return lessonMapper.selectPage(page, wrapper);
    }

    @Override
    public Page<Lesson> getTeacherLessons(Long teacherId, Integer pageNum, Integer pageSize, String status, LocalDate startDate, LocalDate endDate) {
        Page<Lesson> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Lesson> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(Lesson::getTeacherId, teacherId);

        if (StringUtils.hasText(status)) {
            wrapper.eq(Lesson::getStatus, status);
        }
        if (startDate != null) {
            wrapper.ge(Lesson::getLessonDate, startDate);
        }
        if (endDate != null) {
            wrapper.le(Lesson::getLessonDate, endDate);
        }
        wrapper.orderByDesc(Lesson::getCreatedAt, Lesson::getUpdatedAt);

        return lessonMapper.selectPage(page, wrapper);
    }

    @Override
    @Transactional
    public void deleteLesson(Long id) {
        getLessonById(id);
        lessonMapper.deleteById(id);
        log.info("课程删除成功：id={}", id);
    }

    @Override
    @Transactional
    public void startLesson(Long id) {
        Lesson lesson = getLessonById(id);
        lesson.setStatus(LessonStatus.IN_PROGRESS.getCode());
        lesson.setStartDatetime(LocalDateTime.now());
        lessonMapper.updateById(lesson);
        log.info("课程开始：id={}", id);
    }

    @Override
    @Transactional
    public void completeLesson(Long id) {
        Lesson lesson = getLessonById(id);
        lesson.setStatus(LessonStatus.COMPLETED.getCode());
        lesson.setEndDatetime(LocalDateTime.now());
        lessonMapper.updateById(lesson);
        log.info("课程完成：id={}", id);

        // 更新课程包统计：教师数量（去重统计）
        if (lesson.getCourseId() != null) {
            coursePackageMapper.updateTeacherCount(lesson.getCourseId());
            log.info("课程包教师数量已更新：courseId={}", lesson.getCourseId());
        }
    }

    @Override
    @Transactional
    public void cancelLesson(Long id) {
        Lesson lesson = getLessonById(id);
        lesson.setStatus(LessonStatus.CANCELLED.getCode());
        lessonMapper.updateById(lesson);
        log.info("课程取消：id={}", id);

        // 更新课程包统计：使用次数 -1（取消的课程不计入使用）
        if (lesson.getCourseId() != null) {
            coursePackageMapper.decrementUsageCount(lesson.getCourseId());
            log.info("课程包使用次数 -1: courseId={}", lesson.getCourseId());
        }
    }

    @Override
    @Transactional
    public void abandonLessonByTeacher(Long lessonId, Long teacherId, Long tenantId) {
        Lesson lesson = getLessonById(lessonId);
        if (!tenantId.equals(lesson.getTenantId())) {
            throw new BusinessException(ErrorCode.FORBIDDEN, "无权操作该课时");
        }
        if (!teacherId.equals(lesson.getTeacherId())) {
            throw new BusinessException(ErrorCode.FORBIDDEN, "无权操作该课时");
        }
        String st = lesson.getStatus();
        if (LessonStatus.COMPLETED.getCode().equals(st)) {
            throw new BusinessException(ErrorCode.BAD_REQUEST, "已完成的课程不可删除");
        }
        studentRecordMapper.delete(
                new LambdaQueryWrapper<StudentRecord>().eq(StudentRecord::getLessonId, lessonId));
        lessonFeedbackMapper.delete(
                new LambdaQueryWrapper<LessonFeedback>().eq(LessonFeedback::getLessonId, lessonId));
        // 与 cancelLesson 一致：仅当尚未处于「已取消」时回退使用次数（避免重复扣减）
        if (lesson.getCourseId() != null && !LessonStatus.CANCELLED.getCode().equals(st)) {
            coursePackageMapper.decrementUsageCount(lesson.getCourseId());
            log.info("退出上课删除课时，课程包使用次数 -1: courseId={}", lesson.getCourseId());
        }
        lessonMapper.deleteById(lessonId);
        log.info("教师退出上课，已删除课时记录 lessonId={}", lessonId);
    }

    @Override
    public List<Lesson> getTodayLessons(Long tenantId) {
        return lessonMapper.selectList(
                new LambdaQueryWrapper<Lesson>()
                        .eq(Lesson::getTenantId, tenantId)
                        .eq(Lesson::getLessonDate, LocalDate.now())
                        .in(Lesson::getStatus, LessonStatus.SCHEDULED.getCode(), LessonStatus.IN_PROGRESS.getCode())
                        .orderByAsc(Lesson::getStartTime)
        );
    }

    @Override
    public StudentRecordsResponse getStudentRecords(Long lessonId) {
        log.debug("获取学生记录列表，课程 ID: {}", lessonId);

        Lesson lesson = lessonMapper.selectById(lessonId);
        if (lesson == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "授课记录不存在");
        }

        String className = "";
        if (lesson.getClassId() != null) {
            Clazz clazz = clazzMapper.selectById(lesson.getClassId());
            className = clazz != null ? clazz.getName() : "";
        }

        List<Student> students = lesson.getClassId() != null
                ? studentService.getStudentListByClassId(lesson.getClassId())
                : List.of();

        List<StudentRecord> records = studentRecordMapper.selectList(
                new LambdaQueryWrapper<StudentRecord>()
                        .eq(StudentRecord::getLessonId, lessonId)
        );
        Map<Long, com.lesingle.edu.dto.response.StudentRecordResponse> recordMap = records.stream()
                .collect(Collectors.toMap(StudentRecord::getStudentId, studentRecordVoMapper::toVO, (a, b) -> a));

        List<StudentWithRecordResponse> studentWithRecords = students.stream()
                .map(s -> StudentWithRecordResponse.builder()
                        .id(s.getId())
                        .name(s.getName())
                        .gender(s.getGender())
                        .record(recordMap.get(s.getId()))
                        .build())
                .toList();

        return StudentRecordsResponse.builder()
                .lesson(StudentRecordsResponse.LessonInfo.builder()
                        .id(lesson.getId())
                        .status(lesson.getStatus())
                        .className(className)
                        .build())
                .students(studentWithRecords)
                .build();
    }

    @Override
    @Transactional
    public StudentRecord saveStudentRecord(Long lessonId, Long studentId, StudentRecordRequest request) {
        log.info("保存学生记录，课程 ID: {}, 学生 ID: {}", lessonId, studentId);

        // 先查询是否已存在
        StudentRecord record = studentRecordMapper.selectOne(
                new LambdaQueryWrapper<StudentRecord>()
                        .eq(StudentRecord::getLessonId, lessonId)
                        .eq(StudentRecord::getStudentId, studentId)
        );

        if (record == null) {
            record = new StudentRecord();
            record.setLessonId(lessonId);
            record.setStudentId(studentId);
            record.setAttendance(request.getAttendance());
            record.setFocus(request.getFocus());
            record.setParticipation(request.getParticipation());
            record.setInterest(request.getInterest());
            record.setUnderstanding(request.getUnderstanding());
            record.setDomainAchievements(request.getDomainAchievements());
            record.setPerformance(request.getPerformance());
            record.setNotes(request.getNotes());
            studentRecordMapper.insert(record);
            log.info("学生记录创建成功，ID: {}", record.getId());
        } else {
            if (request.getAttendance() != null) {
                record.setAttendance(request.getAttendance());
            }
            if (request.getFocus() != null) {
                record.setFocus(request.getFocus());
            }
            if (request.getParticipation() != null) {
                record.setParticipation(request.getParticipation());
            }
            if (request.getInterest() != null) {
                record.setInterest(request.getInterest());
            }
            if (request.getUnderstanding() != null) {
                record.setUnderstanding(request.getUnderstanding());
            }
            if (request.getDomainAchievements() != null) {
                record.setDomainAchievements(request.getDomainAchievements());
            }
            if (request.getPerformance() != null) {
                record.setPerformance(request.getPerformance());
            }
            if (request.getNotes() != null) {
                record.setNotes(request.getNotes());
            }
            studentRecordMapper.updateById(record);
            log.info("学生记录更新成功，ID: {}", record.getId());
        }

        return record;
    }

    @Override
    @Transactional
    public List<StudentRecord> batchSaveStudentRecords(Long lessonId, List<StudentRecordRequest> requests) {
        log.info("批量保存学生记录，课程 ID: {}, 记录数量：{}", lessonId, requests.size());

        List<StudentRecord> records = new ArrayList<>();
        for (StudentRecordRequest request : requests) {
            StudentRecord record = saveStudentRecord(lessonId, request.getStudentId(), request);
            records.add(record);
        }

        return records;
    }

    @Override
    public LessonFeedback getLessonFeedback(Long lessonId) {
        log.debug("获取课程反馈，课程 ID: {}", lessonId);

        return lessonFeedbackMapper.selectOne(
                new LambdaQueryWrapper<LessonFeedback>()
                        .eq(LessonFeedback::getLessonId, lessonId)
        );
    }

    @Override
    @Transactional
    public LessonFeedback submitFeedback(Long lessonId, Long teacherId, String content, Integer rating) {
        log.info("提交课程反馈，课程 ID: {}, 教师 ID: {}", lessonId, teacherId);

        // 先查询是否已存在
        LessonFeedback feedback = lessonFeedbackMapper.selectOne(
                new LambdaQueryWrapper<LessonFeedback>()
                        .eq(LessonFeedback::getLessonId, lessonId)
                        .eq(LessonFeedback::getTeacherId, teacherId)
        );

        if (feedback == null) {
            feedback = new LessonFeedback();
            feedback.setLessonId(lessonId);
            feedback.setTeacherId(teacherId);
            feedback.setContent(content);
            feedback.setRating(rating);
            lessonFeedbackMapper.insert(feedback);
            log.info("课程反馈创建成功，ID: {}", feedback.getId());
        } else {
            feedback.setContent(content);
            feedback.setRating(rating);
            lessonFeedbackMapper.updateById(feedback);
            log.info("课程反馈更新成功，ID: {}", feedback.getId());
        }

        return feedback;
    }

    @Override
    @Transactional
    public void saveLessonProgress(Long lessonId, LessonProgressRequest request) {
        log.info("保存课程进度，课程 ID: {}", lessonId);

        Lesson lesson = getLessonById(lessonId);

        if (request.getCurrentLessonId() != null) {
            lesson.setCurrentLessonId(request.getCurrentLessonId());
        }
        if (request.getCurrentStepId() != null) {
            lesson.setCurrentStepId(request.getCurrentStepId());
        }
        if (request.getLessonIds() != null) {
            lesson.setLessonIds(JSON.toJSONString(request.getLessonIds()));
        }
        if (request.getCompletedLessonIds() != null) {
            lesson.setCompletedLessonIds(JSON.toJSONString(request.getCompletedLessonIds()));
        }
        if (request.getProgressData() != null) {
            lesson.setProgressData(JSON.toJSONString(request.getProgressData()));
        }

        lessonMapper.updateById(lesson);
        log.info("课程进度保存成功，ID: {}", lessonId);
    }

    @Override
    public Lesson getLessonProgress(Long lessonId) {
        log.debug("获取课程进度，课程 ID: {}", lessonId);
        return getLessonById(lessonId);
    }

    @Override
    @Transactional
    public Lesson createLessonFromSchedule(Long schedulePlanId, Long teacherId) {
        log.info("从排课创建课时: schedulePlanId={}, teacherId={}", schedulePlanId, teacherId);

        // 检查排课是否存在
        SchedulePlan schedule = schedulePlanMapper.selectById(schedulePlanId);
        if (schedule == null) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND, "排课不存在");
        }

        // 验证教师
        if (!teacherId.equals(schedule.getTeacherId())) {
            throw new BusinessException(ErrorCode.FORBIDDEN, "您不是该课程的授课教师");
        }

        // 检查是否已创建课时
        Lesson existingLesson = lessonMapper.selectOne(
                new LambdaQueryWrapper<Lesson>()
                        .eq(Lesson::getSchedulePlanId, schedulePlanId)
        );
        if (existingLesson != null) {
            log.info("课时已存在: lessonId={}", existingLesson.getId());
            return existingLesson;
        }

        // 解析时间段
        LocalTime startTime = null;
        LocalTime endTime = null;
        if (schedule.getScheduledTime() != null) {
            String[] parts = schedule.getScheduledTime().split("-");
            if (parts.length == 2) {
                startTime = LocalTime.parse(parts[0].trim());
                endTime = LocalTime.parse(parts[1].trim());
            }
        }

        // 创建课时
        Lesson lesson = new Lesson();
        lesson.setTenantId(schedule.getTenantId());
        lesson.setSchedulePlanId(schedulePlanId);
        lesson.setCourseId(schedule.getCourseId());
        lesson.setClassId(schedule.getClassId());
        lesson.setTeacherId(teacherId);
        lesson.setTitle(schedule.getName());
        lesson.setLessonDate(schedule.getScheduledDate());
        lesson.setStartTime(startTime);
        lesson.setEndTime(endTime);
        lesson.setStatus(LessonStatus.SCHEDULED.getCode());
        lesson.setNotes(schedule.getNote());

        lessonMapper.insert(lesson);
        log.info("从排课创建课时成功: lessonId={}", lesson.getId());
        // 更新课程包统计：使用次数 +1
        if (schedule.getCourseId() != null) {
            coursePackageMapper.incrementUsageCount(schedule.getCourseId());
            log.info("课程包使用次数 +1: courseId={}", schedule.getCourseId());
        }

        return lesson;
    }

    @Override
    @Transactional
    public Lesson startLessonFromSchedule(Long schedulePlanId, Long teacherId) {
        log.info("从排课开始上课: schedulePlanId={}, teacherId={}", schedulePlanId, teacherId);

        // 创建或获取课时
        Lesson lesson = createLessonFromSchedule(schedulePlanId, teacherId);

        // 开始上课
        if (!LessonStatus.IN_PROGRESS.getCode().equals(lesson.getStatus())) {
            lesson.setStatus(LessonStatus.IN_PROGRESS.getCode());
            lesson.setStartDatetime(LocalDateTime.now());
            lessonMapper.updateById(lesson);
            log.info("课时开始: lessonId={}", lesson.getId());
        }

        return lesson;
    }

}
