package com.lesingle.edu.controller.school;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lesingle.edu.common.annotation.Log;
import com.lesingle.edu.common.enums.ClassTeacherRole;
import com.lesingle.edu.common.enums.LogModule;
import com.lesingle.edu.common.enums.LogOperationType;
import com.lesingle.edu.common.mapper.ClassMapper;
import com.lesingle.edu.common.response.PageResult;
import com.lesingle.edu.common.response.Result;
import com.lesingle.edu.common.security.SecurityUtils;
import com.lesingle.edu.dto.request.ClassCreateRequest;
import com.lesingle.edu.dto.request.ClassUpdateRequest;
import com.lesingle.edu.dto.request.AddClassTeacherRequest;
import com.lesingle.edu.dto.request.UpdateClassTeacherRequest;
import com.lesingle.edu.common.mapper.StudentMapper;
import com.lesingle.edu.dto.response.ClassResponse;
import com.lesingle.edu.dto.response.ClassTeacherResponse;
import com.lesingle.edu.dto.response.StudentResponse;
import com.lesingle.edu.entity.Clazz;
import com.lesingle.edu.entity.ClassTeacher;
import com.lesingle.edu.entity.Lesson;
import com.lesingle.edu.entity.ParentStudent;
import com.lesingle.edu.entity.Student;
import com.lesingle.edu.entity.Teacher;
import com.lesingle.edu.mapper.ClassTeacherMapper;
import com.lesingle.edu.mapper.ParentMapper;
import com.lesingle.edu.mapper.ParentStudentMapper;
import com.lesingle.edu.mapper.LessonMapper;
import com.lesingle.edu.service.ClassService;
import com.lesingle.edu.service.StudentService;
import com.lesingle.edu.service.TeacherService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@Tag(name = "School - Class", description = "Class Management APIs for School")
@Slf4j
@RestController
@RequestMapping("/api/v1/school/classes")
@RequiredArgsConstructor
public class SchoolClassController {

    private final ClassService classService;
    private final ClassMapper classMapper;
    private final ClassTeacherMapper classTeacherMapper;
    private final StudentService studentService;
    private final StudentMapper studentMapper;
    private final TeacherService teacherService;
    private final LessonMapper lessonMapper;
    private final ParentMapper parentMapper;
    private final ParentStudentMapper parentStudentMapper;

    @Operation(summary = "Create class")
    @Log(module = LogModule.CLASS, type = LogOperationType.CREATE, description = "创建新班级")
    @PostMapping
    public Result<ClassResponse> createClass(@Valid @RequestBody ClassCreateRequest request) {
        Long tenantId = SecurityUtils.getCurrentTenantId();
        Clazz clazz = classService.createClass(tenantId, request);
        return Result.success(classMapper.toVO(clazz));
    }

    @Operation(summary = "Update class")
    @Log(module = LogModule.CLASS, type = LogOperationType.UPDATE, description = "修改班级信息")
    @PutMapping("/{id}")
    public Result<ClassResponse> updateClass(@PathVariable Long id, @RequestBody ClassUpdateRequest request) {
        Long tenantId = SecurityUtils.getCurrentTenantId();
        Clazz clazz = classService.updateClassWithTenantCheck(id, tenantId, request);
        return Result.success(classMapper.toVO(clazz));
    }

    @Operation(summary = "Get class by ID")
    @GetMapping("/{id}")
    public Result<ClassResponse> getClass(@PathVariable Long id) {
        Long tenantId = SecurityUtils.getCurrentTenantId();
        Clazz clazz = classService.getClassByIdWithTenantCheck(id, tenantId);
        ClassResponse vo = classMapper.toVO(clazz);

        // 填充教师列表
        List<ClassTeacher> classTeachers = classTeacherMapper.selectList(
                new LambdaQueryWrapper<ClassTeacher>().eq(ClassTeacher::getClassId, id));
        vo.setTeachers(buildClassTeacherResponseList(classTeachers));

        return Result.success(vo);
    }

    @Operation(summary = "Get class page")
    @GetMapping
    public Result<PageResult<ClassResponse>> getClassPage(
            @RequestParam(required = false, defaultValue = "1") Integer pageNum,
            @RequestParam(required = false, defaultValue = "100") Integer pageSize,
            @RequestParam(required = false) String keyword,
            @RequestParam(required = false) String grade,
            @RequestParam(required = false) String status) {
        Long tenantId = SecurityUtils.getCurrentTenantId();
        Page<Clazz> page = classService.getClassPage(tenantId, pageNum, pageSize, keyword, grade, status);
        List<ClassResponse> voList = classMapper.toVO(page.getRecords());
        for (ClassResponse vo : voList) {
            int studentCount = studentService.getStudentListByClassId(vo.getId()).size();
            long lessonCount = 0;
            try {
                lessonCount = lessonMapper.selectCount(
                        new LambdaQueryWrapper<Lesson>().eq(Lesson::getClassId, vo.getId()));
            } catch (Exception ignored) {}
            vo.setStudentCount(studentCount);
            vo.setLessonCount((int) lessonCount);

            List<ClassTeacher> classTeachers = classTeacherMapper.selectList(
                    new LambdaQueryWrapper<ClassTeacher>().eq(ClassTeacher::getClassId, vo.getId()));
            List<ClassTeacherResponse> teacherList = buildClassTeacherResponseList(classTeachers);
            vo.setTeachers(teacherList);
        }
        return Result.success(PageResult.of(voList, page.getTotal(), page.getCurrent(), page.getSize()));
    }

    /**
     * 构建班级教师响应列表
     */
    private List<ClassTeacherResponse> buildClassTeacherResponseList(List<ClassTeacher> classTeachers) {
        List<ClassTeacherResponse> teacherList = new ArrayList<>();
        for (ClassTeacher ct : classTeachers) {
            Teacher t = teacherService.findTeacherById(ct.getTeacherId());
            teacherList.add(ClassTeacherResponse.builder()
                    .id(ct.getId())
                    .classId(ct.getClassId())
                    .teacherId(ct.getTeacherId())
                    .role(ct.getRole())
                    .teacherName(t != null ? t.getName() : null)
                    .isPrimary(ClassTeacherRole.isPrimaryRole(ct.getRole()))
                    .createdAt(ct.getCreatedAt())
                    .build());
        }
        return teacherList;
    }

    @Operation(summary = "Delete class")
    @Log(module = LogModule.CLASS, type = LogOperationType.DELETE, description = "删除班级")
    @DeleteMapping("/{id}")
    public Result<Void> deleteClass(@PathVariable Long id) {
        Long tenantId = SecurityUtils.getCurrentTenantId();
        classService.deleteClassWithTenantCheck(id, tenantId);
        return Result.success();
    }

    @Operation(summary = "Add teacher to class")
    @Log(module = LogModule.CLASS, type = LogOperationType.CREATE, description = "添加教师到班级")
    @PostMapping("/{id}/teachers")
    public Result<Void> addClassTeacher(@PathVariable Long id, @Valid @RequestBody AddClassTeacherRequest request) {
        Long tenantId = SecurityUtils.getCurrentTenantId();
        classService.getClassByIdWithTenantCheck(id, tenantId);

        // 如果设置为新主班，先将原主班降级为配班
        if (ClassTeacherRole.isPrimaryRole(request.getRole())) {
            List<ClassTeacher> allTeachers = classTeacherMapper.selectList(
                    new LambdaQueryWrapper<ClassTeacher>().eq(ClassTeacher::getClassId, id));
            for (ClassTeacher ct : allTeachers) {
                if (ClassTeacherRole.isPrimaryRole(ct.getRole())) {
                    ct.setRole(ClassTeacherRole.ASSIST.getCode());
                    classTeacherMapper.updateById(ct);
                    log.info("班级 {} 的原主班教师 {} 已降级为配班", id, ct.getTeacherId());
                }
            }
        }

        // 查询是否已存在关联
        ClassTeacher existing = classTeacherMapper.selectOne(new LambdaQueryWrapper<ClassTeacher>()
                .eq(ClassTeacher::getClassId, id)
                .eq(ClassTeacher::getTeacherId, request.getTeacherId()));

        if (existing != null) {
            // 更新现有角色
            existing.setRole(request.getRole());
            classTeacherMapper.updateById(existing);
        } else {
            // 创建新关联
            ClassTeacher classTeacher = new ClassTeacher();
            classTeacher.setClassId(id);
            classTeacher.setTeacherId(request.getTeacherId());
            classTeacher.setRole(request.getRole());
            classTeacherMapper.insert(classTeacher);
        }

        return Result.success();
    }

    @Operation(summary = "Assign students to class")
    @Log(module = LogModule.CLASS, type = LogOperationType.UPDATE, description = "分配学生到班级")
    @PostMapping("/{id}/students")
    public Result<Void> assignStudents(@PathVariable Long id, @RequestBody List<Long> studentIds) {
        Long tenantId = SecurityUtils.getCurrentTenantId();
        classService.assignStudentsWithTenantCheck(id, tenantId, studentIds);
        return Result.success();
    }

    @Operation(summary = "Get students of class")
    @GetMapping("/{id}/students")
    public Result<PageResult<StudentResponse>> getClassStudents(
            @PathVariable Long id,
            @RequestParam(required = false, defaultValue = "1") Integer pageNum,
            @RequestParam(required = false, defaultValue = "10") Integer pageSize,
            @RequestParam(required = false) String keyword) {
        Long tenantId = SecurityUtils.getCurrentTenantId();
        classService.getClassByIdWithTenantCheck(id, tenantId);
        Page<Student> page = studentService.getStudentsByClassId(id, pageNum, pageSize, keyword);
        List<StudentResponse> voList = studentMapper.toVO(page.getRecords());
        for (StudentResponse vo : voList) {
            var parentRelation = parentStudentMapper.selectOne(
                    new LambdaQueryWrapper<ParentStudent>()
                            .eq(ParentStudent::getStudentId, vo.getId())
                            .eq(ParentStudent::getIsPrimary, 1)
                            .last("LIMIT 1"));
            if (parentRelation != null) {
                var parent = parentMapper.selectById(parentRelation.getParentId());
                if (parent != null) {
                    vo.setParentName(parent.getName());
                    vo.setParentPhone(parent.getPhone());
                }
            }
        }
        return Result.success(PageResult.of(voList, page.getTotal(), page.getCurrent(), page.getSize()));
    }

    @Operation(summary = "Get teachers of class")
    @GetMapping("/{id}/teachers")
    public Result<List<ClassTeacherResponse>> getClassTeachers(@PathVariable Long id) {
        Long tenantId = SecurityUtils.getCurrentTenantId();
        classService.getClassByIdWithTenantCheck(id, tenantId);
        List<ClassTeacher> classTeachers = classTeacherMapper.selectList(
                new LambdaQueryWrapper<ClassTeacher>().eq(ClassTeacher::getClassId, id));
        return Result.success(buildClassTeacherResponseList(classTeachers));
    }

    @Operation(summary = "Update class teacher role")
    @Log(module = LogModule.CLASS, type = LogOperationType.UPDATE, description = "更新班级教师角色")
    @PutMapping("/{id}/teachers/{teacherId}")
    public Result<Void> updateClassTeacher(
            @PathVariable Long id,
            @PathVariable Long teacherId,
            @Valid @RequestBody UpdateClassTeacherRequest request) {
        // 验证班级属于当前租户
        Long tenantId = SecurityUtils.getCurrentTenantId();
        classService.getClassByIdWithTenantCheck(id, tenantId);

        // 调用 Service 方法更新
        classService.updateClassTeacherRole(id, teacherId, request.getRole(), null);
        return Result.success();
    }

    @Operation(summary = "Remove teacher from class")
    @Log(module = LogModule.CLASS, type = LogOperationType.DELETE, description = "从班级移除教师")
    @DeleteMapping("/{id}/teachers/{teacherId}")
    public Result<Void> removeClassTeacher(
            @PathVariable Long id,
            @PathVariable Long teacherId) {
        // 验证班级属于当前租户
        Long tenantId = SecurityUtils.getCurrentTenantId();
        classService.getClassByIdWithTenantCheck(id, tenantId);

        // 删除班级教师关联记录
        classTeacherMapper.delete(new LambdaQueryWrapper<ClassTeacher>()
                .eq(ClassTeacher::getClassId, id)
                .eq(ClassTeacher::getTeacherId, teacherId));

        return Result.success();
    }

}
