package com.qmth.teachcloud.common.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.qmth.boot.api.exception.ApiException;
import com.qmth.teachcloud.common.base.BaseEntity;
import com.qmth.teachcloud.common.bean.dto.BasicStudentExportDto;
import com.qmth.teachcloud.common.bean.dto.DataPermissionRule;
import com.qmth.teachcloud.common.bean.dto.TaskPrintClassDto;
import com.qmth.teachcloud.common.bean.dto.excel.BasicStudentImportDto;
import com.qmth.teachcloud.common.bean.dto.excel.DescribeImportDto;
import com.qmth.teachcloud.common.bean.dto.excel.export.BasicStudentErrorExportDto;
import com.qmth.teachcloud.common.bean.params.BasicClazzParams;
import com.qmth.teachcloud.common.bean.params.BasicMajorParams;
import com.qmth.teachcloud.common.bean.params.BasicStudentExtrasParam;
import com.qmth.teachcloud.common.bean.params.BasicStudentParams;
import com.qmth.teachcloud.common.bean.result.BasicExamStudentResult;
import com.qmth.teachcloud.common.bean.vo.FilePathVo;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.*;
import com.qmth.teachcloud.common.enums.*;
import com.qmth.teachcloud.common.mapper.BasicStudentMapper;
import com.qmth.teachcloud.common.service.*;
import com.qmth.teachcloud.common.util.ExcelUtil;
import com.qmth.teachcloud.common.util.JdbcErrorUtil;
import com.qmth.teachcloud.common.util.ResultUtil;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 学校id 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2021-08-02
 */
@Service
public class BasicStudentServiceImpl extends ServiceImpl<BasicStudentMapper, BasicStudent> implements BasicStudentService {
    @Resource
    private BasicStudentMapper basicStudentMapper;
    @Resource
    private BasicClazzService basicClazzService;
    @Resource
    private BasicMajorService basicMajorService;
    @Resource
    private SysOrgService sysOrgService;
    @Resource
    private BasicRoleDataPermissionService basicRoleDataPermissionService;
    @Resource
    private FileUploadService fileUploadService;
    @Resource
    private TBTaskService tbTaskService;


    @Override
    public IPage<BasicExamStudentResult> basicStudentPage(String queryParams, Long collegeId, Long majorId, Long clazzId, int pageNumber, int pageSize) {
        Long schoolId = SystemConstant.convertIdToLong(ServletUtil.getRequestHeaderSchoolId().toString());
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        DataPermissionRule dpr = basicRoleDataPermissionService.findDataPermission(schoolId, requestUser.getId(), ServletUtil.getRequest().getServletPath());
        queryParams = SystemConstant.translateSpecificSign(queryParams);
        return basicStudentMapper.findBasicStudentPage(new Page<>(pageNumber, pageSize), queryParams, schoolId, collegeId, majorId, clazzId, dpr);
    }

    @Override
    public BasicExamStudentResult findById(Long id) {
        BasicExamStudentResult basicStudentResult = null;
        if (SystemConstant.longNotNull(id)) {
            basicStudentResult = this.baseMapper.findById(id);
        }
        return basicStudentResult;
    }

    @Override
    public List<BasicExamStudentResult> basicStudentList(Long schoolId, Long examId, String courseCode, String teacher, String className, List<String> studentCodeList) {
        return this.baseMapper.findBasicStudentList(schoolId, examId, courseCode, teacher, className, studentCodeList);
    }

    @Override
    public IPage<BasicStudent> listPage(Page<BasicStudent> page, String classId) {
        List<String> classIds = Arrays.asList(classId.split(","));
        QueryWrapper<BasicStudent> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(BasicStudent::getClazzId, classIds)
                .orderByAsc(BasicStudent::getClazzId)
                .orderByAsc(BasicStudent::getStudentCode);
        return this.baseMapper.selectPage(page, queryWrapper);
    }

    @Override
    public List<TaskPrintClassDto> listByClass(Long schoolId, Set<String> stringList) {
        return this.baseMapper.listByClass(schoolId, stringList).stream()
                .peek(e -> e.setTeachBasicEnum(TeachBasicEnum.BASIC_CLAZZ))
                .collect(Collectors.toList());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long saveBasicStudent(BasicStudentParams basicStudentParams) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        BasicStudent basicStudent = this.editEntityHelp(basicStudentParams, sysUser);
        this.saveOrUpdate(basicStudent);
        return basicStudent.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveBasicStudentWithExtrasList(List<BasicStudentExtrasParam> basicStudentExtrasParamList, SysUser requestUser, boolean saveBasicStudent, Map<String, Object> map) {
        Long schoolId = requestUser.getSchoolId();
        List<BasicStudentErrorExportDto> errorDataList = new ArrayList<>();
        boolean throwException = true;
        if (Objects.nonNull(map)) {
            throwException = false;
        }

        // 查询所有学院map
        List<SysOrg> sysOrgList = sysOrgService.findCollegeLevelOrgList(schoolId);
        Map<String, Long> collegeMap = CollectionUtils.isEmpty(sysOrgList) ? new HashMap<>() : sysOrgList.stream().collect(Collectors.toMap(SysOrg::getName, SysOrg::getId));
        // 查询所有专业map
        List<BasicMajor> basicMajorList = basicMajorService.list(new QueryWrapper<BasicMajor>().lambda().eq(BasicMajor::getSchoolId, schoolId));
        Map<String, Long> majorMap = CollectionUtils.isEmpty(basicMajorList) ? new HashMap<>() : basicMajorList.stream().collect(Collectors.toMap(k -> k.getBelongOrgId() + SystemConstant.HYPHEN + k.getName(), BaseEntity::getId));
        // 查询所有班级map
        List<BasicClazz> basicClazzList = basicClazzService.list(new QueryWrapper<BasicClazz>().lambda().eq(BasicClazz::getSchoolId, schoolId));
        Map<String, Long> clazzMap = CollectionUtils.isEmpty(basicClazzList) ? new HashMap<>() : basicClazzList.stream().collect(Collectors.toMap(k -> k.getMajorId() + SystemConstant.HYPHEN + k.getClazzName(), BaseEntity::getId));

        List<BasicStudent> editEntityList = new ArrayList<>();
        for (BasicStudentExtrasParam basicStudentExtrasParam : basicStudentExtrasParamList) {
            // 取值
            String studentName = basicStudentExtrasParam.getStudentName();
            String studentCode = basicStudentExtrasParam.getStudentCode();
            String phoneNumber = basicStudentExtrasParam.getPhoneNumber();
            String collegeName = basicStudentExtrasParam.getCollegeName();
            String majorName = basicStudentExtrasParam.getMajorName();
            String clazzName = basicStudentExtrasParam.getClazzName();

            BasicStudentErrorExportDto basicStudentErrorExportDto = new BasicStudentErrorExportDto();
            BeanUtils.copyProperties(basicStudentExtrasParam, basicStudentErrorExportDto);
            // 学院
            if (StringUtils.isBlank(collegeName)) {
                basicStudentErrorExportDto.setErrorMsg("学号[" + studentCode + "]的数据，学院必填");
                errorDataList.add(basicStudentErrorExportDto);
                continue;
            }
            if (!collegeMap.containsKey(collegeName)) {
                try {
                    SysOrg sysOrg = new SysOrg();
                    sysOrg.setSchoolId(schoolId);
                    sysOrg.setName(collegeName);
                    sysOrg.setParentId(sysOrgService.findRootOrg(schoolId).getId());
                    sysOrgService.saveOrg(sysOrg, requestUser);
                    collegeMap.put(collegeName, sysOrg.getId());
                } catch (Exception e) {
                    basicStudentErrorExportDto.setErrorMsg(e.getMessage());
                    errorDataList.add(basicStudentErrorExportDto);
                    continue;
                }
            }
            Long collegeId = collegeMap.get(collegeName);
            if (collegeId == null) {
                basicStudentErrorExportDto.setErrorMsg("学号[" + studentCode + "]的数据，学院查询失败");
                errorDataList.add(basicStudentErrorExportDto);
                continue;
            }

            // 专业
            if (StringUtils.isBlank(majorName)) {
                basicStudentErrorExportDto.setErrorMsg("学号[" + studentCode + "]的数据，专业必填");
                errorDataList.add(basicStudentErrorExportDto);
                continue;
            }
            String majorKey = collegeId + SystemConstant.HYPHEN + majorName;
            if (!majorMap.containsKey(majorKey)) {
                // 新增一个major
                try {
                    BasicMajorParams basicMajorParams = new BasicMajorParams();
                    basicMajorParams.setMajorName(majorName);
                    basicMajorParams.setCollegeId(collegeId);
                    Long majorId = basicMajorService.saveBasicMajor(basicMajorParams, requestUser);
                    majorMap.put(majorKey, majorId);
                } catch (Exception e) {
                    basicStudentErrorExportDto.setErrorMsg(e.getMessage());
                    errorDataList.add(basicStudentErrorExportDto);
                    continue;
                }

            }
            Long majorId = majorMap.get(majorKey);
            if (majorId == null) {
                basicStudentErrorExportDto.setErrorMsg("学号[" + studentCode + "]的数据，专业查询失败");
                errorDataList.add(basicStudentErrorExportDto);
                continue;
            }

            // 班级
            if (StringUtils.isBlank(clazzName)) {
                basicStudentErrorExportDto.setErrorMsg("学号[" + studentCode + "]的数据，班级必填");
                errorDataList.add(basicStudentErrorExportDto);
                continue;
            }
            String clazzKey = majorId + SystemConstant.HYPHEN + clazzName;
            if (!clazzMap.containsKey(clazzKey)) {
                // 新增一个clazz
                try {
                    BasicClazzParams basicClazzParams = new BasicClazzParams();
                    basicClazzParams.setMajorId(majorId);
                    basicClazzParams.setClazzName(clazzName);
                    Long clazzId = basicClazzService.saveBasicClazz(basicClazzParams, requestUser);
                    clazzMap.put(clazzKey, clazzId);
                } catch (Exception e) {
                    basicStudentErrorExportDto.setErrorMsg(e.getMessage());
                    errorDataList.add(basicStudentErrorExportDto);
                    continue;
                }

            }
            Long clazzId = clazzMap.get(clazzKey);
            if (clazzId == null) {
                basicStudentErrorExportDto.setErrorMsg("学号[" + studentCode + "]的数据，班级查询失败");
                errorDataList.add(basicStudentErrorExportDto);
                continue;
            }

            if (saveBasicStudent) {
                // 学生信息组装
                BasicStudentParams basicStudentParams = new BasicStudentParams();
                basicStudentParams.setStudentName(studentName);
                basicStudentParams.setStudentCode(studentCode);
                basicStudentParams.setPhoneNumber(phoneNumber);
                basicStudentParams.setCollegeId(collegeId);
                basicStudentParams.setMajorId(majorId);
                basicStudentParams.setClazzId(clazzId);
                try {
                    BasicStudent basicStudent = this.editEntityHelp(basicStudentParams, requestUser);
                    editEntityList.add(basicStudent);
                } catch (Exception e) {
                    basicStudentErrorExportDto.setErrorMsg(e.getMessage());
                    errorDataList.add(basicStudentErrorExportDto);
                }
            }
        }
        // 抛出或者记录异常
        if (throwException) {
            String errorMsg = errorDataList.stream().map(BasicStudentErrorExportDto::getErrorMsg).collect(Collectors.joining("\n"));
            throw ExceptionResultEnum.ERROR.exception(errorMsg);
        } else {
            if (map.containsKey(SystemConstant.ERROR_DATA_LIST)) {
                errorDataList = JSON.parseArray(JSON.toJSONString(map.get(SystemConstant.ERROR_DATA_LIST)), BasicStudentErrorExportDto.class);
                map.put(SystemConstant.ERROR_DATA_LIST, errorDataList);
            }

            int dataCount = (int) map.get(SystemConstant.DATA_COUNT);
            map.put(SystemConstant.SUCCESS_DATA_COUNT, dataCount - errorDataList.size());
            map.put(SystemConstant.ERROR_DATA_COUNT, errorDataList.size());
        }


        try {
            this.saveOrUpdateBatch(editEntityList);
        } catch (Exception e) {
            if (e instanceof DataIntegrityViolationException || e instanceof BadSqlGrammarException) {
                String content = JdbcErrorUtil.parseErrorMsg(e.getMessage().toString());
                throw ExceptionResultEnum.SQL_ERROR.exception(content);
            } else if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, ((ApiException) e).getCode(), e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean removeBasicStudentBatch(List<Long> idList) {

        if (idList.size() == 0) {
            throw ExceptionResultEnum.ERROR.exception("请选择要删除的目标");
        }
        // 删除基础学生
        this.remove(new QueryWrapper<BasicStudent>().lambda().in(BasicStudent::getId, idList));
        // 同步删除教学学生
        this.baseMapper.deleteTeachStudentByBasicStudentIdSet(new HashSet<>(idList));
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean removeBasicStudentByCondition(String queryParams, Long collegeId, Long majorId, Set<Long> clazzIdList) {
        LambdaQueryWrapper<BasicStudent> basicStudentQueryWrapper = new QueryWrapper<BasicStudent>().lambda();
        if (SystemConstant.strNotNull(queryParams)) {
            basicStudentQueryWrapper.and(e -> e.like(BasicStudent::getStudentName, queryParams).or().like(BasicStudent::getStudentCode, queryParams));
        }
        if (SystemConstant.longNotNull(collegeId)) {
            basicStudentQueryWrapper.eq(BasicStudent::getBelongOrgId, collegeId);
        }
        if (SystemConstant.longNotNull(majorId)) {
            basicStudentQueryWrapper.eq(BasicStudent::getMajorId, majorId);
        }
        if (clazzIdList != null && clazzIdList.size() > 0) {
            basicStudentQueryWrapper.in(BasicStudent::getClazzId, clazzIdList);
        }
        List<BasicStudent> willDeleteStudent = this.list(basicStudentQueryWrapper);

        // 删除基础学生
        if (willDeleteStudent.size() > 0) {
            Set<Long> idSet = willDeleteStudent.stream().map(BaseEntity::getId).collect(Collectors.toSet());
            this.removeByIds(idSet);
            // 同步删除教学学生
            this.baseMapper.deleteTeachStudentByBasicStudentIdSet(idSet);
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, Object> executeBasicStudentImportLogic(List<LinkedMultiValueMap<Integer, Object>> finalList, Map<String, Object> map) {
        SysUser sysUser = (SysUser) map.get(SystemConstant.SYS_USER);
        for (int i = 0; i < finalList.size(); i++) {
            LinkedMultiValueMap<Integer, Object> excelMap = finalList.get(i);
            List<Object> basicStudentImportDtoList = excelMap.get(i);
            if (CollectionUtils.isEmpty(basicStudentImportDtoList)) {
                continue;
            }
            List<BasicStudentImportDto> datasource = basicStudentImportDtoList.stream().map(e -> {
                BasicStudentImportDto basicStudentImportDto = new BasicStudentImportDto();
                BeanUtils.copyProperties(e, basicStudentImportDto);
                return basicStudentImportDto;
            }).collect(Collectors.toList());

            List<BasicStudentExtrasParam> basicStudentExtrasParamList = datasource.stream().flatMap(e -> {
                BasicStudentExtrasParam basicStudentExtrasParam = new BasicStudentExtrasParam();
                basicStudentExtrasParam.setStudentName(StringUtils.isNotBlank(e.getStudentName()) ? e.getStudentName().trim() : null);
                basicStudentExtrasParam.setStudentCode(StringUtils.isNotBlank(e.getStudentCode()) ? e.getStudentCode().trim() : null);
                basicStudentExtrasParam.setPhoneNumber(null);
                basicStudentExtrasParam.setCollegeName(StringUtils.isNotBlank(e.getCollegeName()) ? e.getCollegeName().trim() : null);
                basicStudentExtrasParam.setMajorName(StringUtils.isNotBlank(e.getMajorName()) ? e.getMajorName().trim() : null);
                basicStudentExtrasParam.setClazzName(StringUtils.isNotBlank(e.getClazzName()) ? e.getClazzName().trim() : null);
                basicStudentExtrasParam.setRowIndex(e.getRowIndex());
                return Stream.of(basicStudentExtrasParam);
            }).collect(Collectors.toList());
            this.saveBasicStudentWithExtrasList(basicStudentExtrasParamList, sysUser, true, map);
        }
        return map;
    }

    @Override
    public void exportData(HttpServletResponse response, String queryParams, Long collegeId, Long majorId, Set<Long> clazzIdList) throws Exception {
        Long schoolId = SystemConstant.convertIdToLong(ServletUtil.getRequestHeaderSchoolId().toString());
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        DataPermissionRule dpr = basicRoleDataPermissionService.findDataPermission(schoolId, requestUser.getId(), ServletUtil.getRequest().getServletPath());
        queryParams = SystemConstant.translateSpecificSign(queryParams);
        List<BasicStudentExportDto> studentExportDtos = basicStudentMapper.listExportData(queryParams, schoolId, collegeId, majorId, clazzIdList, dpr);
        if (studentExportDtos.isEmpty()) {
            throw ExceptionResultEnum.ERROR.exception("没有可导出数据");
        }
        ExcelUtil.excelExport("学生数据", BasicStudentExportDto.class, studentExportDtos, response);
    }

    @Override
    public boolean importBasicStudent(Map<String, Object> map, MultipartFile file) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();

        TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
        List<BasicStudent> basicStudentList = new ArrayList<>();
        List<BasicStudentErrorExportDto> errorDataList = new ArrayList<>();
        AtomicInteger totalInteger = new AtomicInteger(0);
        try {
            tbTask.setStatus(TaskStatusEnum.RUNNING);
            tbTaskService.updateById(tbTask);
            checkImportBasicStudent(file, basicStudentList, errorDataList, totalInteger, sysUser);

            if (CollectionUtils.isNotEmpty(basicStudentList)) {
                this.saveBatch(basicStudentList);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (CollectionUtils.isNotEmpty(errorDataList)) {
                tbTask.setResult(TaskResultEnum.ERROR);
                try {
                    File excelFileTemp = SystemConstant.getFileTempVar(SystemConstant.EXCEL_PREFIX);
                    ExcelUtil.excelExportLocal(excelFileTemp, BasicStudentErrorExportDto.class, errorDataList);
                    String fileName = SystemConstant.getNanoId() + SystemConstant.EXCEL_PREFIX;
                    FilePathVo filePathVo = fileUploadService.uploadFile(excelFileTemp, UploadFileEnum.FILE, fileName);
                    tbTask.setErrorFilePath(JSON.toJSONString(filePathVo));
                } catch (Exception e) {
                    log.error("创建学生导入错误数据文件失败");
                } finally {
                    tbTask.setSummary(JSON.toJSONString(errorDataList));
                }
            } else {
                tbTask.setResult(TaskResultEnum.SUCCESS);
            }
            tbTask.setStatus(TaskStatusEnum.FINISH);
            tbTaskService.updateById(tbTask);
        }
        return true;
    }

    private void checkImportBasicStudent(MultipartFile file, List<BasicStudent> basicStudentList, List<BasicStudentErrorExportDto> errorDataList, AtomicInteger totalInteger, SysUser sysUser) throws IOException, NoSuchFieldException {
        // 查询所有学院map
        List<SysOrg> sysOrgList = sysOrgService.findCollegeLevelOrgList(sysUser.getSchoolId());
        Map<String, Long> collegeMap = CollectionUtils.isEmpty(sysOrgList) ? new HashMap<>() : sysOrgList.stream().collect(Collectors.toMap(SysOrg::getName, SysOrg::getId));
        // 查询所有专业map
        List<BasicMajor> basicMajorList = basicMajorService.list(new QueryWrapper<BasicMajor>().lambda().eq(BasicMajor::getSchoolId, sysUser.getSchoolId()));
        Map<String, Long> majorMap = CollectionUtils.isEmpty(basicMajorList) ? new HashMap<>() : basicMajorList.stream().collect(Collectors.toMap(k -> k.getBelongOrgId() + SystemConstant.HYPHEN + k.getName(), BaseEntity::getId));
        // 查询所有班级map
        List<BasicClazz> basicClazzList = basicClazzService.list(new QueryWrapper<BasicClazz>().lambda().eq(BasicClazz::getSchoolId, sysUser.getSchoolId()));
        Map<String, Long> clazzMap = CollectionUtils.isEmpty(basicClazzList) ? new HashMap<>() : basicClazzList.stream().collect(Collectors.toMap(k -> k.getMajorId() + SystemConstant.HYPHEN + k.getClazzName(), BaseEntity::getId));

        // 顶级机构（学校级）
        Long rootSchoolOrgId = sysOrgService.findRootOrg(sysUser.getSchoolId()).getId();

        ExcelUtil.excelReader(file.getInputStream(), Lists.newArrayList(BasicStudentImportDto.class, DescribeImportDto.class), (finalExcelList, finalColumnNameList, finalExcelErrorList) -> {
            Map<String, Integer> checkCodeMap = new HashMap<>();
            for (int i = 0; i < finalExcelList.size(); i++) {
                LinkedMultiValueMap<Integer, Object> excelMap = finalExcelList.get(i);
                List<Object> basicStudentImportDtoList = excelMap.get(i);
                // 无数据，跳过
                if (CollectionUtils.isEmpty(basicStudentImportDtoList)) {
                    continue;
                }
                for (int y = 0; y < basicStudentImportDtoList.size(); y++) {
                    // 计算总数量
                    totalInteger.getAndIncrement();

                    // 行索引
                    Integer rowIndex = y + 1;
                    BasicStudentImportDto basicStudentImportDto = (BasicStudentImportDto) basicStudentImportDtoList.get(y);
                    String studentName = StringUtils.trimToNull(basicStudentImportDto.getStudentName());
                    String studentCode = StringUtils.trimToNull(basicStudentImportDto.getStudentCode());
                    String collegeName = StringUtils.trimToNull(basicStudentImportDto.getCollegeName());
                    String majorName = StringUtils.trimToNull(basicStudentImportDto.getMajorName());
                    String clazzName = StringUtils.trimToNull(basicStudentImportDto.getClazzName());

                    // 本行全部列为空，跳过
                    if (StringUtils.isAllBlank(studentName, studentCode, collegeName, majorName, clazzName)) {
                        continue;
                    }

                    basicStudentImportDto.setRowIndex(rowIndex);
                    BasicStudentErrorExportDto basicStudentErrorExportDto = new BasicStudentErrorExportDto();
                    BeanUtils.copyProperties(basicStudentImportDto, basicStudentErrorExportDto);

                    // excel内校验
                    List<String> errorMsgList = new ArrayList<>();
                    // 必填字段校验
                    String errorStringEmpty = ExcelUtil.checkExcelField(basicStudentImportDto);
                    if (errorStringEmpty.length() > 0) {
                        errorMsgList.add(errorStringEmpty);
                    }

                    if (!studentCode.matches(SystemConstant.REGULAR_EXPRESSION_OF_CODE1)) {
                        errorMsgList.add("学号[" + studentCode + "]只能是字母或数字");
                    }

                    // 检验学号
                    if (checkCodeMap.containsKey(studentCode)) {
                        Integer studentCodeCount = checkCodeMap.get(studentCode);
                        errorMsgList.add(String.format("学号[%s]有[%d]行数据", studentCode, studentCodeCount));
                        checkCodeMap.put(studentCode, studentCodeCount + 1);
                    } else {
                        checkCodeMap.put(studentCode, 1);
                    }

                    if (CollectionUtils.isNotEmpty(errorMsgList)) {
                        continue;
                    }

                    // 院专班数据校验
                    // 1.学院
                    if (!collegeMap.containsKey(collegeName)) {
                        try {
                            SysOrg sysOrg = new SysOrg(sysUser.getSchoolId(), collegeName, rootSchoolOrgId);
                            sysOrgService.saveOrg(sysOrg, sysUser);
                            collegeMap.put(collegeName, sysOrg.getId());
                        } catch (Exception e) {
                            errorMsgList.add("创建学院[" + collegeName + "]失败");
                            continue;
                        }
                    }
                    Long collegeId = collegeMap.get(collegeName);
                    if (collegeId == null) {
                        errorMsgList.add("学号[" + studentCode + "]的考生，学院查询失败");
                        errorDataList.add(basicStudentErrorExportDto);
                        continue;
                    }

                    // 2.专业
                    String majorKey = collegeId + SystemConstant.HYPHEN + majorName;
                    if (!majorMap.containsKey(majorKey)) {
                        // 新增一个major
                        try {
                            BasicMajorParams basicMajorParams = new BasicMajorParams();
                            basicMajorParams.setMajorName(majorName);
                            basicMajorParams.setCollegeId(collegeId);
                            Long majorId = basicMajorService.saveBasicMajor(basicMajorParams, sysUser);
                            majorMap.put(majorKey, majorId);
                        } catch (Exception e) {
                            errorMsgList.add("创建专业[" + majorName + "]失败");
                            continue;
                        }

                    }
                    Long majorId = majorMap.get(majorKey);
                    if (majorId == null) {
                        errorMsgList.add("学号[" + studentCode + "]的考生，专业查询失败");
                        errorDataList.add(basicStudentErrorExportDto);
                        continue;
                    }

                    // 3.班级
                    String clazzKey = majorId + SystemConstant.HYPHEN + clazzName;
                    if (!clazzMap.containsKey(clazzKey)) {
                        // 新增一个clazz
                        try {
                            BasicClazzParams basicClazzParams = new BasicClazzParams();
                            basicClazzParams.setMajorId(majorId);
                            basicClazzParams.setClazzName(clazzName);
                            Long clazzId = basicClazzService.saveBasicClazz(basicClazzParams, sysUser);
                            clazzMap.put(clazzKey, clazzId);
                        } catch (Exception e) {
                            errorMsgList.add("创建班级[" + clazzName + "]失败");
                            continue;
                        }

                    }
                    Long clazzId = clazzMap.get(clazzKey);
                    if (clazzId == null) {
                        errorMsgList.add("学号[" + studentCode + "]的考生，班级查询失败");
                        errorDataList.add(basicStudentErrorExportDto);
                        continue;
                    }

                    // 学生信息组装
                    BasicStudentParams basicStudentParams = new BasicStudentParams();
                    basicStudentParams.setStudentName(studentName);
                    basicStudentParams.setStudentCode(studentCode);
                    basicStudentParams.setCollegeId(collegeId);
                    basicStudentParams.setMajorId(majorId);
                    basicStudentParams.setClazzId(clazzId);
                    try {
                        BasicStudent basicStudent = this.editEntityHelp(basicStudentParams, sysUser);
                        basicStudentList.add(basicStudent);
                    } catch (Exception e) {
                        errorMsgList.add("学生保存失败");
                    }

                    // 错误
                    if (CollectionUtils.isNotEmpty(errorMsgList)) {
                        basicStudentErrorExportDto.setErrorMsg(JSON.toJSONString(errorMsgList));
                        errorDataList.add(basicStudentErrorExportDto);
                    }
                }
            }
            return finalExcelList;
        }, 2);
    }

    /**
     * 学生保存助手方法（应对学生保存和导入批量保存）
     *
     * @param basicStudentParams 学生参数
     * @param sysUser            操作人
     * @return 结果
     */
    private BasicStudent editEntityHelp(BasicStudentParams basicStudentParams, SysUser sysUser) {
        Long schoolId = sysUser.getSchoolId();
        // 普通参数
        String studentName = basicStudentParams.getStudentName();
        String studentCode = basicStudentParams.getStudentCode();
        String phoneNumber = basicStudentParams.getPhoneNumber();
        Long clazzId = basicStudentParams.getClazzId();
        Long majorId = basicStudentParams.getMajorId();
        Long collegeId = basicStudentParams.getCollegeId();

        // 检验有值的电话在学校的唯一性
        if (SystemConstant.strNotNull(phoneNumber)) {
            BasicStudent checkPhone = this.getOne(new QueryWrapper<BasicStudent>().lambda()
                    .eq(BasicStudent::getSchoolId, schoolId)
                    .eq(BasicStudent::getPhoneNumber, phoneNumber));
            if (Objects.nonNull(checkPhone)) {
                if ((basicStudentParams.getId() != null && !checkPhone.getId().equals(basicStudentParams.getId())) || basicStudentParams.getId() == null) {
                    throw ExceptionResultEnum.ERROR.exception("电话[" + phoneNumber + "]已使用");
                }
            }
        }

        // 组装基础参数
        BasicStudent basicStudent = new BasicStudent();
        basicStudent.setStudentCode(studentCode);
        basicStudent.setStudentName(studentName);
        basicStudent.setPhoneNumber(phoneNumber);
        basicStudent.setBelongOrgId(collegeId);
        basicStudent.setMajorId(majorId);
        basicStudent.setClazzId(clazzId);
        basicStudent.setSchoolId(schoolId);
        basicStudent.setOrgId(sysUser.getOrgId());

        if (basicStudentParams.getId() != null) {
            if (!studentCode.matches(SystemConstant.REGULAR_EXPRESSION_OF_CODE)) {
                throw ExceptionResultEnum.ERROR.exception("学号[" + studentCode + "]不符合规范");
            }
            BasicStudent basicStudentOld = this.getById(basicStudentParams.getId());
            if (!basicStudentOld.getStudentCode().equals(studentCode)) {
                List<BasicStudent> checkCodeList = this.list(new QueryWrapper<BasicStudent>().lambda()
                        .eq(BasicStudent::getSchoolId, schoolId)
                        .eq(BasicStudent::getStudentCode, studentCode)
                        .ne(BasicStudent::getId, basicStudentParams.getId()));
                if (!CollectionUtils.isEmpty(checkCodeList)) {
                    throw ExceptionResultEnum.ERROR.exception("学号[" + studentCode + "]已存在");
                }
            }

            basicStudent.setId(basicStudentParams.getId());
        } else {
            BasicStudent checkCode = this.getOne(new QueryWrapper<BasicStudent>().lambda()
                    .eq(BasicStudent::getSchoolId, schoolId)
                    .eq(BasicStudent::getStudentCode, studentCode));
            if (checkCode != null) {
                basicStudent.setId(checkCode.getId());
                // 禁用的学生，此时启用
                basicStudent.setEnable(true);
                basicStudent.updateInfo(sysUser.getId());
            } else {
                basicStudent.setId(SystemConstant.getDbUuid());
                basicStudent.insertInfo(sysUser.getId());
            }
        }

        return basicStudent;
    }
}
