package com.pangu.school.service.impl;

import com.pangu.base.mapper.RegionMapper;
import com.pangu.common.core.domain.BaseEntity;
import com.pangu.common.core.exception.ServiceException;
import com.pangu.common.utils.DateUtils;
import com.pangu.school.domain.dto.SchoolCreateDTO;
import com.pangu.school.domain.dto.SchoolQueryDTO;
import com.pangu.school.domain.entity.School;
import com.pangu.school.domain.entity.SchoolClass;
import com.pangu.school.domain.entity.SchoolGrade;
import com.pangu.school.domain.vo.SchoolTreeVO;
import com.pangu.school.domain.vo.SchoolVO;
import com.pangu.school.mapper.SchoolClassMapper;
import com.pangu.school.mapper.SchoolGradeMapper;
import com.pangu.school.mapper.SchoolMapper;
import com.pangu.school.service.ISchoolService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 学校服务实现
 * @author pangu
 */
@Service
public class SchoolServiceImpl implements ISchoolService {

    @Autowired
    private SchoolMapper schoolMapper;

    @Autowired
    private SchoolGradeMapper schoolGradeMapper;

    @Autowired
    private SchoolClassMapper schoolClassMapper;

    @Autowired
    private RegionMapper regionMapper;

    @Override
    public List<SchoolTreeVO> selectSchoolTree(Long regionId) {
        // 1. 查询学校列表
        List<School> schools = schoolMapper.selectSchoolsByRegionId(regionId);
        if (schools.isEmpty()) {
            return new ArrayList<>();
        }

        // 2. 查询学校下的年级
        List<Long> schoolIds = schools.stream()
                .map(School::getSchoolId)
                .collect(Collectors.toList());
        List<SchoolGrade> grades = schoolGradeMapper.selectBySchoolIds(schoolIds);

        // 3. 查询年级下的班级
        List<Long> schoolGradeIds = grades.stream()
                .map(SchoolGrade::getId)
                .collect(Collectors.toList());
        List<SchoolClass> classes = schoolGradeIds.isEmpty() ? 
                new ArrayList<>() : schoolClassMapper.selectBySchoolGradeIds(schoolGradeIds);

        // 4. 组装树形结构
        return buildSchoolTree(schools, grades, classes);
    }

    @Override
    public List<SchoolVO> selectSchoolList(SchoolQueryDTO query) {
        return schoolMapper.selectSchoolList(query);
    }

    @Override
    public SchoolVO selectSchoolById(Long schoolId) {
        return schoolMapper.selectSchoolById(schoolId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertSchool(SchoolCreateDTO dto) {
        School school = new School();
        BeanUtils.copyProperties(dto, school);

        // 生成学校编码：SCH + 年份 + 4位序号
        String schoolCode = generateSchoolCode();
        school.setSchoolCode(schoolCode);

        // 设置区域路径
        String regionPath = getRegionPath(dto.getRegionId());
        school.setRegionPath(regionPath);

        school.setCreateTime(DateUtils.getNowDate());
        return schoolMapper.insertSchool(school);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateSchool(School school) {
        // 如果修改了regionId，需要更新regionPath
        if (school.getRegionId() != null) {
            String regionPath = getRegionPath(school.getRegionId());
            school.setRegionPath(regionPath);
        }

        school.setUpdateTime(DateUtils.getNowDate());
        return schoolMapper.updateSchool(school);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteSchool(Long schoolId) {
        // 1. 检查是否有年级/班级
        int gradeCount = schoolGradeMapper.countBySchoolId(schoolId);
        if (gradeCount > 0) {
            throw new ServiceException("该学校下存在年级数据，请先删除年级");
        }

        // 2. 检查是否被学生引用
        // TODO: 等学生模块开发完成后补充
        // int studentCount = studentMapper.countBySchoolId(schoolId);
        // if (studentCount > 0) {
        //     throw new ServiceException("该学校已被学生信息引用，无法删除");
        // }

        // 3. 软删除
        return schoolMapper.deleteSchoolById(schoolId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int bindGrades(Long schoolId, List<Long> gradeIds) {
        if (gradeIds == null || gradeIds.isEmpty()) {
            throw new ServiceException("请至少选择一个年级");
        }

        List<SchoolGrade> schoolGrades = new ArrayList<>();
        int orderNum = 1;
        for (Long gradeId : gradeIds) {
            // 检查是否已存在
            if (schoolGradeMapper.exists(schoolId, gradeId)) {
                continue;
            }

            SchoolGrade sg = new SchoolGrade();
            sg.setSchoolId(schoolId);
            sg.setGradeId(gradeId);
            sg.setOrderNum(orderNum++);
            sg.setStatus("0");
            sg.setCreateTime(DateUtils.getNowDate());
            schoolGrades.add(sg);
        }

        if (schoolGrades.isEmpty()) {
            return 0;
        }

        return schoolGradeMapper.batchInsert(schoolGrades);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int bindClasses(Long schoolGradeId, List<Long> classIds) {
        if (classIds == null || classIds.isEmpty()) {
            throw new ServiceException("请至少选择一个班级");
        }

        List<SchoolClass> schoolClasses = new ArrayList<>();
        int orderNum = 1;
        for (Long classId : classIds) {
            // 检查是否已存在
            if (schoolClassMapper.exists(schoolGradeId, classId)) {
                continue;
            }

            SchoolClass sc = new SchoolClass();
            sc.setSchoolGradeId(schoolGradeId);
            sc.setClassId(classId);
            sc.setOrderNum(orderNum++);
            sc.setStatus("0");
            sc.setCreateTime(DateUtils.getNowDate());
            schoolClasses.add(sc);
        }

        if (schoolClasses.isEmpty()) {
            return 0;
        }

        return schoolClassMapper.batchInsert(schoolClasses);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteSchoolGrade(Long schoolGradeId) {
        // 1. 检查是否有班级
        int classCount = schoolClassMapper.countBySchoolGradeId(schoolGradeId);
        if (classCount > 0) {
            throw new ServiceException("该年级下存在班级数据，请先删除班级");
        }

        // 2. 检查是否被学生引用
        // TODO: 等学生模块开发完成后补充
        // int studentCount = studentMapper.countBySchoolGradeId(schoolGradeId);
        // if (studentCount > 0) {
        //     throw new ServiceException("该年级已被学生信息引用，无法删除");
        // }

        // 3. 软删除
        return schoolGradeMapper.deleteById(schoolGradeId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteSchoolClass(Long schoolClassId) {
        // 1. 检查是否被学生引用
        // TODO: 等学生模块开发完成后补充
        // int studentCount = studentMapper.countBySchoolClassId(schoolClassId);
        // if (studentCount > 0) {
        //     throw new ServiceException("该班级已被学生信息引用，无法删除");
        // }

        // 2. 软删除
        return schoolClassMapper.deleteById(schoolClassId);
    }

    /**
     * 生成学校编码
     * 格式：SCH + 年份(4位) + 序号(4位)
     * 示例：SCH20260001
     */
    private String generateSchoolCode() {
        String year = String.valueOf(LocalDate.now().getYear());
        String prefix = "SCH" + year;

        // 查询当前年份最大编号
        String maxCode = schoolMapper.selectMaxCode(prefix);

        int seq = 1;
        if (maxCode != null && maxCode.length() >= 11) {
            try {
                seq = Integer.parseInt(maxCode.substring(7)) + 1;
            } catch (NumberFormatException e) {
                seq = 1;
            }
        }

        return prefix + String.format("%04d", seq);
    }

    /**
     * 获取区域路径
     * @param regionId 区域ID
     * @return 区域路径（如：湖北省-武汉市-武昌区）
     */
    private String getRegionPath(Long regionId) {
        if (regionId == null) {
            return "";
        }
        String path = regionMapper.selectRegionPath(regionId);
        return path != null ? path : "";
    }

    /**
     * 构建学校树形结构
     */
    private List<SchoolTreeVO> buildSchoolTree(List<School> schools,
                                               List<SchoolGrade> grades,
                                               List<SchoolClass> classes) {
        // 按学校ID分组年级
        Map<Long, List<SchoolGrade>> gradeMap = grades.stream()
                .collect(Collectors.groupingBy(SchoolGrade::getSchoolId));

        // 按学校年级ID分组班级
        Map<Long, List<SchoolClass>> classMap = classes.stream()
                .collect(Collectors.groupingBy(SchoolClass::getSchoolGradeId));

        return schools.stream().map(school -> {
            SchoolTreeVO vo = new SchoolTreeVO();
            vo.setId(school.getSchoolId());
            vo.setType("school");
            vo.setName(school.getSchoolName());
            vo.setCode(school.getSchoolCode());
            vo.setStatus(school.getStatus());
            vo.setRegionPath(school.getRegionPath());

            // 组装年级
            List<SchoolGrade> schoolGrades = gradeMap.getOrDefault(school.getSchoolId(), Collections.emptyList());
            vo.setChildren(schoolGrades.stream().map(sg -> {
                SchoolTreeVO gradeVO = new SchoolTreeVO();
                gradeVO.setId(sg.getId());
                gradeVO.setType("grade");
                gradeVO.setName(sg.getGradeName() != null ? sg.getGradeName() : "未知年级");
                gradeVO.setSchoolGradeId(sg.getId());
                gradeVO.setGradeId(sg.getGradeId());

                // 组装班级
                List<SchoolClass> gradeClasses = classMap.getOrDefault(sg.getId(), Collections.emptyList());
                gradeVO.setChildren(gradeClasses.stream().map(sc -> {
                    SchoolTreeVO classVO = new SchoolTreeVO();
                    classVO.setId(sc.getId());
                    classVO.setType("class");
                    classVO.setName(sc.getClassName() != null ? sc.getClassName() : "未知班级");
                    classVO.setSchoolClassId(sc.getId());
                    classVO.setClassId(sc.getClassId());
                    return classVO;
                }).collect(Collectors.toList()));

                return gradeVO;
            }).collect(Collectors.toList()));

            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public Long getSchoolIdByName(String schoolName, Long regionId) {
        SchoolQueryDTO query = new SchoolQueryDTO();
        query.setSchoolName(schoolName);
        query.setRegionId(regionId);
        List<SchoolVO> schools = schoolMapper.selectSchoolList(query);
        return schools.isEmpty() ? null : schools.get(0).getSchoolId();
    }

    @Override
    public Long getSchoolGradeId(Long schoolId, String gradeName) {
        List<SchoolGrade> grades = schoolGradeMapper.selectBySchoolIds(Collections.singletonList(schoolId));
        for (SchoolGrade grade : grades) {
            if (gradeName.equals(grade.getGradeName())) {
                return grade.getId();
            }
        }
        return null;
    }

    @Override
    public Long getSchoolClassId(Long schoolGradeId, String className) {
        List<SchoolClass> classes = schoolClassMapper.selectBySchoolGradeIds(Collections.singletonList(schoolGradeId));
        for (SchoolClass clazz : classes) {
            if (className.equals(clazz.getClassName())) {
                return clazz.getId();
            }
        }
        return null;
    }
}
