package com.lesingle.edu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lesingle.edu.common.enums.ErrorCode;
import com.lesingle.edu.common.enums.GenericStatus;
import com.lesingle.edu.common.enums.StudentClassStatus;
import com.lesingle.edu.common.exception.BusinessException;
import com.lesingle.edu.dto.request.StudentCreateRequest;
import com.lesingle.edu.dto.request.StudentUpdateRequest;
import com.lesingle.edu.entity.Parent;
import com.lesingle.edu.entity.ParentStudent;
import com.lesingle.edu.entity.Student;
import com.lesingle.edu.entity.StudentClassHistory;
import com.lesingle.edu.mapper.ParentMapper;
import com.lesingle.edu.mapper.ParentStudentMapper;
import com.lesingle.edu.mapper.StudentClassHistoryMapper;
import com.lesingle.edu.mapper.StudentMapper;
import com.lesingle.edu.service.ClassService;
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.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 学生服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StudentServiceImpl extends com.baomidou.mybatisplus.extension.service.impl.ServiceImpl<StudentMapper, Student>
    implements StudentService {

    private final StudentMapper studentMapper;
    private final ParentStudentMapper parentStudentMapper;
    private final ParentMapper parentMapper;
    private final StudentClassHistoryMapper studentClassHistoryMapper;
    private final ClassService classService;

    @Override
    @Transactional
    public Student createStudent(Long tenantId, StudentCreateRequest request) {
        log.info("开始创建学生，姓名：{}", request.getName());

        Student student = new Student();
        student.setTenantId(tenantId);
        student.setName(request.getName());
        student.setGender(request.getGender());
        student.setBirthDate(request.getBirthDate());
        student.setGrade(request.getGrade());
        student.setStudentNo(request.getStudentNo());
        student.setReadingLevel(request.getReadingLevel());
        student.setInterests(request.getInterests());
        student.setNotes(request.getNotes());
        student.setStatus(GenericStatus.ACTIVE.getCode());

        studentMapper.insert(student);

        if (request.getClassId() != null) {
            classService.assignStudentToClass(student.getId(), request.getClassId(), tenantId);
        }

        // 处理家长信息：如果提供了家长姓名和电话，创建家长账号并关联
        if (StringUtils.hasText(request.getParentName()) && StringUtils.hasText(request.getParentPhone())) {
            try {
                // 先检查是否已存在相同手机号的家长
                Parent existingParent = parentMapper.selectOne(
                    new LambdaQueryWrapper<Parent>()
                        .eq(Parent::getPhone, request.getParentPhone())
                        .eq(Parent::getTenantId, tenantId)
                );

                Parent parent;
                if (existingParent != null) {
                    // 家长已存在，直接使用
                    parent = existingParent;
                    log.info("家长已存在，手机号：{}, ID: {}", request.getParentPhone(), existingParent.getId());
                } else {
                    // 创建新家长账号
                    parent = new Parent();
                    parent.setTenantId(tenantId);
                    parent.setName(request.getParentName());
                    parent.setPhone(request.getParentPhone());
                    // 使用手机号作为登录账号，默认密码 123456
                    parent.setUsername(request.getParentPhone());
                    // 密码需要加密，这里先使用明文（实际应该使用 BCrypt 等加密）
                    parent.setPassword("123456");
                    parent.setStatus(GenericStatus.ACTIVE.getCode());
                    parentMapper.insert(parent);
                    log.info("家长账号创建成功，ID: {}", parent.getId());
                }

                // 检查是否已存在关联
                Long finalParentId = parent.getId();
                Long existingRelationId = Optional.ofNullable(
                    parentStudentMapper.selectOne(
                        new LambdaQueryWrapper<ParentStudent>()
                            .eq(ParentStudent::getParentId, finalParentId)
                            .eq(ParentStudent::getStudentId, student.getId())
                    )
                ).map(ParentStudent::getId).orElse(null);

                if (existingRelationId == null) {
                    // 创建家长 - 学生关联
                    ParentStudent relation = new ParentStudent();
                    relation.setParentId(parent.getId());
                    relation.setStudentId(student.getId());
                    relation.setRelationship("父子/母子"); // 默认关系，后续可扩展
                    relation.setIsPrimary(1); // 默认为主要监护人
                    parentStudentMapper.insert(relation);
                    log.info("家长 - 学生关联创建成功，ParentId: {}, StudentId: {}", parent.getId(), student.getId());
                }
            } catch (Exception e) {
                log.error("处理家长信息失败：{}", e.getMessage(), e);
                // 不抛出异常，避免影响学生创建
            }
        }

        log.info("学生创建成功，ID: {}", student.getId());
        return student;
    }

    @Override
    @Transactional
    public Student updateStudent(Long id, StudentUpdateRequest request) {
        log.info("开始更新学生，ID: {}", id);

        Student student = getStudentById(id);

        if (StringUtils.hasText(request.getName())) {
            student.setName(request.getName());
        }
        if (request.getGender() != null) {
            student.setGender(request.getGender());
        }
        if (request.getBirthDate() != null) {
            student.setBirthDate(request.getBirthDate());
        }
        if (request.getAvatarUrl() != null) {
            student.setAvatarUrl(request.getAvatarUrl());
        }
        if (request.getGrade() != null) {
            student.setGrade(request.getGrade());
        }
        if (request.getStudentNo() != null) {
            student.setStudentNo(request.getStudentNo());
        }
        if (request.getReadingLevel() != null) {
            student.setReadingLevel(request.getReadingLevel());
        }
        if (request.getInterests() != null) {
            student.setInterests(request.getInterests());
        }
        if (request.getNotes() != null) {
            student.setNotes(request.getNotes());
        }
        if (StringUtils.hasText(request.getStatus())) {
            student.setStatus(request.getStatus());
        }

        studentMapper.updateById(student);

        if (request.getClassId() != null) {
            classService.assignStudentToClass(id, request.getClassId(), student.getTenantId());
        }

        // 处理家长信息更新
        if (StringUtils.hasText(request.getParentName()) && StringUtils.hasText(request.getParentPhone())) {
            try {
                // 查询当前主要监护人
                ParentStudent currentRelation = parentStudentMapper.selectOne(
                    new LambdaQueryWrapper<ParentStudent>()
                        .eq(ParentStudent::getStudentId, id)
                        .eq(ParentStudent::getIsPrimary, 1)
                );

                // 检查是否已存在相同手机号的家长
                Parent existingParent = parentMapper.selectOne(
                    new LambdaQueryWrapper<Parent>()
                        .eq(Parent::getPhone, request.getParentPhone())
                        .eq(Parent::getTenantId, student.getTenantId())
                );

                if (existingParent != null) {
                    // 家长已存在
                    if (currentRelation != null && currentRelation.getParentId().equals(existingParent.getId())) {
                        // 同一个家长，只需更新姓名
                        if (!existingParent.getName().equals(request.getParentName())) {
                            existingParent.setName(request.getParentName());
                            parentMapper.updateById(existingParent);
                        }
                    } else {
                        // 更换监护人：先删除旧关联，再创建新关联
                        if (currentRelation != null) {
                            parentStudentMapper.deleteById(currentRelation.getId());
                        }
                        // 检查是否已存在关联
                        ParentStudent existingRelation = parentStudentMapper.selectOne(
                            new LambdaQueryWrapper<ParentStudent>()
                                .eq(ParentStudent::getParentId, existingParent.getId())
                                .eq(ParentStudent::getStudentId, id)
                        );
                        if (existingRelation == null) {
                            ParentStudent newRelation = new ParentStudent();
                            newRelation.setParentId(existingParent.getId());
                            newRelation.setStudentId(id);
                            newRelation.setRelationship("父子/母子");
                            newRelation.setIsPrimary(1);
                            parentStudentMapper.insert(newRelation);
                        }
                    }
                } else {
                    // 家长不存在，创建新家长账号
                    Parent parent = new Parent();
                    parent.setTenantId(student.getTenantId());
                    parent.setName(request.getParentName());
                    parent.setPhone(request.getParentPhone());
                    parent.setUsername(request.getParentPhone());
                    parent.setPassword("123456");
                    parent.setStatus(GenericStatus.ACTIVE.getCode());
                    parentMapper.insert(parent);

                    // 如果已有监护人，删除旧关联
                    if (currentRelation != null) {
                        parentStudentMapper.deleteById(currentRelation.getId());
                    }

                    // 创建新关联
                    ParentStudent newRelation = new ParentStudent();
                    newRelation.setParentId(parent.getId());
                    newRelation.setStudentId(id);
                    newRelation.setRelationship("父子/母子");
                    newRelation.setIsPrimary(1);
                    parentStudentMapper.insert(newRelation);
                }

                log.info("家长信息更新成功");
            } catch (Exception e) {
                log.error("处理家长信息失败：{}", e.getMessage(), e);
                // 不抛出异常，避免影响学生更新
            }
        }

        log.info("学生更新成功，ID: {}", id);
        return student;
    }

    @Override
    public Student getStudentById(Long id) {
        log.debug("查询学生，ID: {}", id);

        Student student = studentMapper.selectById(id);
        if (student == null) {
            log.warn("学生不存在，ID: {}", id);
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND, "学生不存在");
        }
        return student;
    }

    @Override
    public Student getStudentByIdWithTenantCheck(Long id, Long tenantId) {
        log.debug("查询学生（带租户验证），ID: {}, tenantId: {}", id, tenantId);
        Student student = getStudentById(id);
        if (!student.getTenantId().equals(tenantId)) {
            log.warn("租户无权访问学生，学生ID: {}, 租户ID: {}", id, tenantId);
            throw new BusinessException(ErrorCode.FORBIDDEN, "无权访问该学生");
        }
        return student;
    }

    @Override
    @Transactional
    public Student updateStudentWithTenantCheck(Long id, Long tenantId, StudentUpdateRequest request) {
        log.info("开始更新学生（带租户验证），ID: {}, tenantId: {}", id, tenantId);
        getStudentByIdWithTenantCheck(id, tenantId);
        return updateStudent(id, request);
    }

    @Override
    public Page<Student> getStudentPage(Long tenantId, Integer pageNum, Integer pageSize, String keyword, String grade, String status, Long classId) {
        if (classId != null) {
            return getStudentsByClassId(classId, pageNum, pageSize, keyword);
        }
        log.debug("分页查询学生，页码：{}，每页数量：{}", pageNum, pageSize);

        Page<Student> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();

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

        if (StringUtils.hasText(keyword)) {
            wrapper.and(w -> w
                    .like(Student::getName, keyword)
                    .or()
                    .like(Student::getStudentNo, keyword)
            );
        }
        if (StringUtils.hasText(grade)) {
            wrapper.eq(Student::getGrade, grade);
        }
        if (StringUtils.hasText(status)) {
            wrapper.eq(Student::getStatus, status);
        }
        wrapper.orderByDesc(Student::getCreatedAt);

        return studentMapper.selectPage(page, wrapper);
    }

    @Override
    public Page<Student> getStudentsByClassId(Long classId, Integer pageNum, Integer pageSize) {
        return getStudentsByClassId(classId, pageNum, pageSize, null);
    }

    @Override
    public Page<Student> getStudentsByClassId(Long classId, Integer pageNum, Integer pageSize, String keyword) {
        log.debug("根据班级查询学生，班级 ID: {}，页码：{}", classId, pageNum);

        Page<Student> page = new Page<>(pageNum, pageSize);

        // 获取班级中活跃的学生 ID
        // 条件：status 为 active/ACTIVE，且 (end_date 为空 或 end_date >= 今天)
        List<StudentClassHistory> histories = studentClassHistoryMapper.selectList(
                new LambdaQueryWrapper<StudentClassHistory>()
                        .eq(StudentClassHistory::getClassId, classId)
                        .in(StudentClassHistory::getStatus, StudentClassStatus.ACTIVE.getCode())
                        .and(w -> w.isNull(StudentClassHistory::getEndDate)
                                .or()
                                .ge(StudentClassHistory::getEndDate, LocalDate.now()))
        );

        if (histories.isEmpty()) {
            return page;
        }

        List<Long> studentIds = histories.stream()
                .map(StudentClassHistory::getStudentId)
                .distinct()
                .toList();

        if (studentIds.isEmpty()) {
            return page;
        }

        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Student::getId, studentIds)
                .eq(Student::getStatus, StudentClassStatus.ACTIVE.getCode());

        if (StringUtils.hasText(keyword)) {
            wrapper.and(w -> w
                    .like(Student::getName, keyword)
                    .or()
                    .like(Student::getStudentNo, keyword)
            );
        }
        wrapper.orderByAsc(Student::getName);

        return studentMapper.selectPage(page, wrapper);
    }

    @Override
    public List<Student> getStudentListByClassId(Long classId) {
        log.debug("根据班级查询学生列表，班级 ID: {}", classId);

        List<StudentClassHistory> histories = studentClassHistoryMapper.selectList(
                new LambdaQueryWrapper<StudentClassHistory>()
                        .eq(StudentClassHistory::getClassId, classId)
                        .in(StudentClassHistory::getStatus, StudentClassStatus.ACTIVE.getCode())
                        .and(w -> w.isNull(StudentClassHistory::getEndDate)
                                .or()
                                .ge(StudentClassHistory::getEndDate, LocalDate.now()))
        );

        if (histories.isEmpty()) {
            return List.of();
        }

        List<Long> studentIds = histories.stream()
                .map(StudentClassHistory::getStudentId)
                .distinct()
                .toList();

        return studentMapper.selectList(
                new LambdaQueryWrapper<Student>()
                        .in(Student::getId, studentIds)
                        .eq(Student::getStatus, StudentClassStatus.ACTIVE.getCode())
                        .orderByAsc(Student::getName)
        );
    }

    @Override
    @Transactional
    public void deleteStudent(Long id) {
        log.info("开始删除学生，ID: {}", id);

        getStudentById(id);
        studentMapper.deleteById(id);

        log.info("学生删除成功，ID: {}", id);
    }

    @Override
    @Transactional
    public void deleteStudentWithTenantCheck(Long id, Long tenantId) {
        log.info("开始删除学生（带租户验证），ID: {}, tenantId: {}", id, tenantId);
        getStudentByIdWithTenantCheck(id, tenantId);
        deleteStudent(id);
    }

    @Override
    public List<Student> getStudentsByParentId(Long parentId) {
        log.debug("根据家长 ID 查询学生，家长 ID: {}", parentId);

        List<ParentStudent> parentStudents = parentStudentMapper.selectList(
                new LambdaQueryWrapper<ParentStudent>()
                        .eq(ParentStudent::getParentId, parentId)
        );

        if (parentStudents.isEmpty()) {
            return new ArrayList<>();
        }

        List<Long> studentIds = parentStudents.stream()
                .map(ParentStudent::getStudentId)
                .toList();

        return studentMapper.selectList(
                new LambdaQueryWrapper<Student>()
                        .in(Student::getId, studentIds)
                        .eq(Student::getStatus, "active")
        );
    }

    @Override
    public List<Student> getStudentsByClassIds(List<Long> classIds, String keyword, Page<Student> page) {
        log.debug("根据班级 ID 列表查询学生，班级 ID 列表：{}", classIds);

        // 获取班级中活跃的学生 ID
        List<StudentClassHistory> histories = studentClassHistoryMapper.selectList(
                new LambdaQueryWrapper<StudentClassHistory>()
                        .in(StudentClassHistory::getClassId, classIds)
                        .in(StudentClassHistory::getStatus, StudentClassStatus.ACTIVE.getCode())
                        .and(w -> w.isNull(StudentClassHistory::getEndDate)
                                .or()
                                .ge(StudentClassHistory::getEndDate, LocalDate.now()))
        );

        if (histories.isEmpty()) {
            return List.of();
        }

        List<Long> studentIds = histories.stream()
                .map(StudentClassHistory::getStudentId)
                .distinct()
                .toList();

        if (studentIds.isEmpty()) {
            return List.of();
        }

        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Student::getId, studentIds)
                .eq(Student::getStatus, StudentClassStatus.ACTIVE.getCode());

        if (StringUtils.hasText(keyword)) {
            wrapper.and(w -> w
                    .like(Student::getName, keyword)
                    .or()
                    .like(Student::getStudentNo, keyword)
            );
        }
        wrapper.orderByAsc(Student::getName);

        return studentMapper.selectPage(page, wrapper).getRecords();
    }

}
