package com.xjrsoft.module.student.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.xjrsoft.common.enums.YesOrNoEnum;
import com.xjrsoft.common.utils.VoToColumnUtil;
import com.xjrsoft.module.banding.vo.IdManyCountVo;
import com.xjrsoft.module.base.entity.BaseMajorSet;
import com.xjrsoft.module.base.service.IBaseMajorSetService;
import com.xjrsoft.module.outint.vo.IdCountVo;
import com.xjrsoft.module.student.dto.BaseNewStudentPageDto;
import com.xjrsoft.module.student.entity.BaseNewStudent;
import com.xjrsoft.module.student.mapper.BaseNewStudentMapper;
import com.xjrsoft.module.student.service.IBaseNewStudentService;
import com.xjrsoft.module.student.vo.BaseNewStudentPageVo;
import com.xjrsoft.module.student.vo.BaseNewStudentScoreExcelVo;
import com.xjrsoft.module.student.vo.EnrollmentPlanGradeVo;
import com.xjrsoft.module.student.vo.EnrollmentPlanTreeVo;
import com.xjrsoft.module.system.entity.DictionaryDetail;
import com.xjrsoft.module.system.entity.DictionaryItem;
import com.xjrsoft.module.system.mapper.DictionarydetailMapper;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @title: 新生维护信息
* @Author dzx
* @Date: 2024-06-27
* @Version 1.0
*/
@Service
@AllArgsConstructor
public class BaseNewStudentServiceImpl extends MPJBaseServiceImpl<BaseNewStudentMapper, BaseNewStudent> implements IBaseNewStudentService {

    private final DictionarydetailMapper dictionarydetailMapper;
    private final IBaseMajorSetService majorSetService;
    @Override
    public Page<BaseNewStudentPageVo> getPage(Page<BaseNewStudentPageVo> page, BaseNewStudentPageDto dto) {
        return this.baseMapper.getPage(page, dto);
    }

    @Override
    public List<EnrollmentPlanTreeVo> getEnrollmentPlanList() {
        return this.baseMapper.getEnrollmentPlanList();
    }

    @Override
    public List<EnrollmentPlanGradeVo> getGradeList() {
        return this.baseMapper.getGradeList();
    }

    /**
     * 导入数据
     * @param file 上传的文件
     * @return 未成功导入的数据
     */
    @Override
    public List<Map<Integer, Object>> importData(Long treeId, MultipartFile file) throws IOException {
        List<Map<Integer, Object>> excelDataList = EasyExcel.read(file.getInputStream()).sheet().headRowNumber(3).doReadSync();

        //查询字典数据
        List<String> codeList = new ArrayList<>();
        codeList.add("gender");
        codeList.add("student_type");
        codeList.add("stduy_status");

        List<DictionaryDetail> detailList = dictionarydetailMapper.selectJoinList(DictionaryDetail.class,
                new MPJLambdaWrapper<DictionaryDetail>()
                        .select(DictionaryDetail.class, x -> VoToColumnUtil.fieldsToColumns(DictionaryDetail.class).contains(x.getProperty()))
                        .leftJoin(DictionaryItem.class, DictionaryItem::getId, DictionaryDetail::getItemId)
                        .in(DictionaryItem::getCode, codeList)
        );
        Map<String, String> dictMap = new HashMap<>();
        for (DictionaryDetail detail : detailList) {
            dictMap.put(detail.getName(), detail.getCode());
        }

        //查询专业数据
        Map<String, Long> majorSetMap = majorSetService.list(new QueryWrapper<BaseMajorSet>().lambda().eq(BaseMajorSet::getDeleteMark, 0))
                .stream().collect(Collectors.toMap(BaseMajorSet::getName, BaseMajorSet::getId));
        
        //查询已有的学生数据
        List<BaseNewStudent> baseNewStudents = this.baseMapper.selectList(
                new QueryWrapper<BaseNewStudent>().lambda()
                        .eq(BaseNewStudent::getEnrollmentPlanId, treeId)
        );
        Map<String, BaseNewStudent> exeistStudent = baseNewStudents.stream().collect(Collectors.toMap(BaseNewStudent::getCredentialNumber, x -> x));

        List<BaseNewStudent> dataList = new ArrayList<>();
        List<BaseNewStudent> updateList = new ArrayList<>();
        List<Map<Integer, Object>> errorList = new ArrayList<>();
        Date createDate = new Date();
        for (Map<Integer, Object> objectMap : excelDataList) {

            //1、验证数据
            if(checkData(objectMap, dictMap, majorSetMap) != null){
                errorList.add(objectMap);
                continue;
            }
            BaseNewStudent student = exeistStudent.get(objectMap.get(3).toString());
            if(student != null && student.getStatus() == 1){
                objectMap.put(15, "该学生已分班并已经同步到学生基本信息,无法导入");
                errorList.add(objectMap);
                continue;
            }
            if(majorSetMap.get(objectMap.get(10).toString()) == null){
                objectMap.put(15, "第一志愿未匹配,无法导入");
                errorList.add(objectMap);
                continue;
            }
            if(majorSetMap.get(objectMap.get(11).toString()) == null){
                objectMap.put(15, "第二志愿未匹配,无法导入");
                errorList.add(objectMap);
                continue;
            }
            if(student != null && student.getStatus() == 0){
                student.setGraduateSchool(objectMap.get(0).toString());
                student.setName(objectMap.get(1).toString());
                student.setGender(dictMap.get(objectMap.get(2).toString()));
                student.setCredentialNumber(objectMap.get(3).toString());
                student.setHeight(BigDecimal.valueOf(Double.parseDouble(objectMap.get(4).toString())));
                student.setWeight(BigDecimal.valueOf(Double.parseDouble(objectMap.get(5).toString())));
                if(objectMap.get(6) != null){
                    student.setGraduateClass(objectMap.get(6).toString());
                }

                student.setSource(dictMap.get(objectMap.get(7).toString()));
                student.setStduyStatus(dictMap.get(objectMap.get(8).toString()));
                student.setMobile(objectMap.get(9).toString());
                student.setFirstAmbition(majorSetMap.get(objectMap.get(10).toString()));
                student.setFirstAmbitionId(majorSetMap.get(objectMap.get(10).toString()));
                student.setSecondAmbition(majorSetMap.get(objectMap.get(11).toString()));
                student.setSecondAmbitionId(majorSetMap.get(objectMap.get(11).toString()));
                student.setIsAdjust(YesOrNoEnum.getCode(objectMap.get(12).toString()));
                if(objectMap.get(13) != null){
                    student.setFamilyMobile(objectMap.get(13).toString());
                }
                if(objectMap.get(14) != null){
                    student.setFamilyAddress(objectMap.get(14).toString());
                }
                updateList.add(student);
                continue;
            }

            dataList.add(
                new BaseNewStudent(){{
                    setCreateDate(createDate);
                    setCreateUserId(StpUtil.getLoginIdAsLong());
                    setGraduateSchool(objectMap.get(0).toString());
                    setName(objectMap.get(1).toString());
                    setGender(dictMap.get(objectMap.get(2).toString()));
                    setCredentialNumber(objectMap.get(3).toString());
                    setHeight(BigDecimal.valueOf(Double.parseDouble(objectMap.get(4).toString())));
                    setWeight(BigDecimal.valueOf(Double.parseDouble(objectMap.get(5).toString())));
                    if(objectMap.get(6) != null){
                        setGraduateClass(objectMap.get(6).toString());
                    }

                    setSource(dictMap.get(objectMap.get(7).toString()));
                    setStduyStatus(dictMap.get(objectMap.get(8).toString()));
                    setMobile(objectMap.get(9).toString());
                    setFirstAmbition(majorSetMap.get(objectMap.get(10).toString()));
                    setFirstAmbitionId(majorSetMap.get(objectMap.get(10).toString()));
                    setSecondAmbition(majorSetMap.get(objectMap.get(11).toString()));
                    setSecondAmbitionId(majorSetMap.get(objectMap.get(11).toString()));
                    setIsAdjust(YesOrNoEnum.getCode(objectMap.get(12).toString()));
                    if(objectMap.get(13) != null){
                        setFamilyMobile(objectMap.get(13).toString());
                    }
                    if(objectMap.get(14) != null){
                        setFamilyAddress(objectMap.get(14).toString());
                    }
                    setEnrollmentPlanId(treeId);
                    setStatus(0);
                }}
            );
        }
        if(!dataList.isEmpty()){
            this.saveBatch(dataList);
        }

        if(!updateList.isEmpty()){
            this.updateBatchById(updateList);
        }

        return errorList;
    }

    @Override
    public List<BaseNewStudentScoreExcelVo> scoreImport(MultipartFile file) throws IOException {
        List<DictionaryDetail> detailList = dictionarydetailMapper.selectJoinList(DictionaryDetail.class,
                new MPJLambdaWrapper<DictionaryDetail>()
                        .select(DictionaryDetail.class, x -> VoToColumnUtil.fieldsToColumns(DictionaryDetail.class).contains(x.getProperty()))
                        .leftJoin(DictionaryItem.class, DictionaryItem::getId, DictionaryDetail::getItemId)
                        .eq(DictionaryItem::getCode, "gender")
        );
        Map<String, String> genderMap = detailList.stream().collect(Collectors.toMap(DictionaryDetail::getName, DictionaryDetail::getCode));

        List<BaseNewStudentScoreExcelVo> excelDataList = EasyExcel.read(file.getInputStream()).headRowNumber(2).head(BaseNewStudentScoreExcelVo.class).sheet().doReadSync();
        List<BaseNewStudentScoreExcelVo> errorList = new ArrayList<>();
        List<BaseNewStudent> updateList = new ArrayList<>();
        for (BaseNewStudentScoreExcelVo el : excelDataList) {
            List<BaseNewStudent> studentList = this.baseMapper.selectList(
                    new QueryWrapper<BaseNewStudent>().lambda()
                            .eq(BaseNewStudent::getGender, genderMap.get(el.getGender()))
                            .eq(BaseNewStudent::getGraduateSchool, el.getGraduateSchool())
                            .eq(BaseNewStudent::getGraduateClass, el.getGraduateClass())
                            .eq(BaseNewStudent::getName, el.getName())
            );
            if(studentList.size() != 1){
                errorList.add(el);
                continue;
            }
            BaseNewStudent student = studentList.get(0);
            student.setScore(el.getScore());
            updateList.add(student);
        }
        if(!updateList.isEmpty()){
            this.updateBatchById(updateList);
        }

        return errorList;
    }

    @Override
    public List<IdCountVo> getMajorStudent(Long gradeId, String enrollType, Integer index) {
        if(index == 1){
            return this.baseMapper.getFirstAmbitionStudentCount(gradeId, enrollType);
        }else if(index == 2){
            return this.baseMapper.getSecondAmbitionStudentCount(gradeId, enrollType);
        }
        return new ArrayList<>();
    }

    @Override
    public List<IdManyCountVo> getMajorStudentCount(Long bandingTaskId) {
        return this.baseMapper.getMajorStudentCount(bandingTaskId);
    }

    /**
     * 检查必填字段是否为空
     */
    Map<Integer, Object> checkData(Map<Integer, Object> objectMap, Map<String, String> dictMap, Map<String, Long> majorSetMap){
        //验证哪些列是空
        List<Integer> emptyColumn = new ArrayList<>();
        List<String> errorMsg = new ArrayList<>();
        if(objectMap.get(0) == null || "".equals(objectMap.get(0).toString())){
            emptyColumn.add(0);
        }
        if(objectMap.get(1) == null || "".equals(objectMap.get(1).toString())){
            emptyColumn.add(1);
        }
        if(objectMap.get(2) == null || "".equals(objectMap.get(2).toString())){
            emptyColumn.add(2);
        }else{
            if(dictMap.get(objectMap.get(2).toString()) == null){
                errorMsg.add("性别不正确");
            }
        }
        if(objectMap.get(3) == null || "".equals(objectMap.get(3).toString())){
            emptyColumn.add(3);
        }
        if(objectMap.get(4) == null || "".equals(objectMap.get(4).toString())){
            emptyColumn.add(4);
        }else{
            if(objectMap.get(4) instanceof Integer){
                errorMsg.add("身高请只填写数字");
            }
        }
        if(objectMap.get(5) == null || "".equals(objectMap.get(5).toString())){
            emptyColumn.add(5);
        }else{
            if(objectMap.get(5) instanceof Integer){
                errorMsg.add("体重请只填写数字");
            }
        }

        if(objectMap.get(7) == null || "".equals(objectMap.get(7).toString())){
            emptyColumn.add(7);
        }else{
            if(dictMap.get(objectMap.get(8).toString()) == null){
                errorMsg.add("学生来源填写不正确");
            }
        }
        if(objectMap.get(8) == null || "".equals(objectMap.get(8).toString())){
            emptyColumn.add(8);
        }else{
            if(dictMap.get(objectMap.get(8).toString()) == null){
                errorMsg.add("住宿类型填写不正确");
            }
        }
        if(objectMap.get(9) == null || "".equals(objectMap.get(9).toString())){
            emptyColumn.add(9);
        }
        if(objectMap.get(10) == null || "".equals(objectMap.get(10).toString())){
            emptyColumn.add(10);
        }else{
            if(majorSetMap.get(objectMap.get(10).toString()) == null){
                errorMsg.add("第一志愿填写不正确");
            }
        }
        if(objectMap.get(11) == null || "".equals(objectMap.get(11).toString())){
            emptyColumn.add(11);
        }else{
            if(majorSetMap.get(objectMap.get(11).toString()) == null){
                errorMsg.add("第二志愿填写不正确");
            }
        }
        if(objectMap.get(12) == null || "".equals(objectMap.get(12).toString())){
            emptyColumn.add(12);
        }else{
            if(!"是".equals(objectMap.get(12).toString()) && !"否".equals(objectMap.get(12).toString()) ){
                errorMsg.add("是否可调配请只填写“是”或“否”");
            }
        }
        String msg = "";
        if(!errorMsg.isEmpty()){
            msg += errorMsg.toString().replace("]", "").replace("[", "");
        }
        if(!emptyColumn.isEmpty()){
            msg += "以下列不能为空：" + emptyColumn.toString().replace("]", "").replace("[", "") + "；";
        }

        if(StrUtil.isNotEmpty(msg)){
            objectMap.put(15, msg);
            return objectMap;
        }

        return null;
    }
}
