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

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.qmth.teachcloud.common.base.BaseEntity;
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.params.BasicClazzParams;
import com.qmth.teachcloud.common.bean.params.BasicMajorParams;
import com.qmth.teachcloud.common.bean.params.BasicStudentParams;
import com.qmth.teachcloud.common.bean.result.BasicStudentResult;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.*;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.OrgTypeEnum;
import com.qmth.teachcloud.common.enums.TeachBasicEnum;
import com.qmth.teachcloud.common.mapper.BasicStudentMapper;
import com.qmth.teachcloud.common.service.*;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <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 BasicCampusService basicCampusService;

    @Override
    public IPage<BasicStudentResult> basicStudentPage(String queryParams, Long campusId,Long collegeId,Long majorId, Set<Long> clazzIdList, int pageNumber, int pageSize) {
        Long schoolId = SystemConstant.convertIdToLong(ServletUtil.getRequestHeaderSchoolId().toString());
//        Set<Long> orgIds = teachcloudCommonService.listSubOrgIds(null);
        Set<Long> orgIds = null;
        queryParams = SystemConstant.translateSpecificSign(queryParams);
        return basicStudentMapper.findBasicStudentPage(new Page<>(pageNumber, pageSize), queryParams, schoolId, campusId,collegeId,majorId, clazzIdList, orgIds);
    }

    @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, 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 requestUser) {
        List<BasicStudentParams> basicStudentParamsList = new ArrayList<>();
        basicStudentParamsList.add(basicStudentParams);
        BasicStudent basicStudent = this.editEntityHelp(basicStudentParamsList, requestUser).get(0);
        this.saveOrUpdate(basicStudent);
        return basicStudent.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveOrUpdateBasicStudentBatch(List<BasicStudentParams> basicStudentParamsList,SysUser requestUser) {
        this.saveOrUpdateBatch(this.editEntityHelp(basicStudentParamsList,requestUser));
    }

    @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 campusId, 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(campusId)){
            basicStudentQueryWrapper.eq(BasicStudent::getCampusId,campusId);
        }
        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) throws IllegalAccessException {
        SysUser sysUser = (SysUser) map.get(SystemConstant.SYS_USER);
        Long schoolId = sysUser.getSchoolId();
        final String link = "-";
        // key = campusName
        Map<String, BasicCampus> campusMap = new HashMap<>();
        // key = collegeName
        Map<String, SysOrg> collegeMap = new HashMap<>();
        // key = schoolId + "-" + majorName
        Map<String, Long> majorMap = new HashMap<>();
        // key = schoolId + "-" + clazzName
        Map<String, Long> clazzMap = new HashMap<>();

        List<BasicStudentParams> addBasicStudentParamsList = new ArrayList<>();
        for (int i = 0; i < finalList.size(); i++) {
            LinkedMultiValueMap<Integer, Object> excelMap = finalList.get(i);
            List<Object> basicStudentImportDtoList = excelMap.get(i);

            assert basicStudentImportDtoList != null;
            if (basicStudentImportDtoList.get(0) instanceof DescribeImportDto) {
                continue;
            }
            List<BasicStudentImportDto> datasource = basicStudentImportDtoList.stream().map(e -> {
                BasicStudentImportDto basicStudentImportDto = new BasicStudentImportDto();
                BeanUtils.copyProperties(e, basicStudentImportDto);
                return basicStudentImportDto;
            }).collect(Collectors.toList());
            map.put("dataCount", datasource.size());

            for (int y = 0; y < Objects.requireNonNull(basicStudentImportDtoList).size(); y++) {
                BasicStudentImportDto basicStudentImportDto = (BasicStudentImportDto) basicStudentImportDtoList.get(y);

                // 取值
                String studentName = basicStudentImportDto.getStudentName();
                String studentCode = basicStudentImportDto.getStudentCode();
                String phoneNumber = basicStudentImportDto.getPhoneNumber();
                String campusName = basicStudentImportDto.getCampusName();
                String collegeName = basicStudentImportDto.getCollegeName();
                String majorName = basicStudentImportDto.getMajorName();
                String clazzName = basicStudentImportDto.getClazzName();

                // 校区
                Long campusId = null;
                if (SystemConstant.strNotNull(campusName)) {
                    BasicCampus basicCampus;
                    if (campusMap.containsKey(campusName)) {
                        basicCampus = campusMap.get(campusName);
                    } else {
                        basicCampus = basicCampusService.getOne(new QueryWrapper<BasicCampus>().lambda()
                                .eq(BasicCampus::getSchoolId, schoolId)
                                .eq(BasicCampus::getCampusName, campusName));
                        if (Objects.isNull(basicCampus)) {
                            throw ExceptionResultEnum.ERROR.exception("系统中不存在【校区】：" + campusName);
                        }
                        campusMap.put(campusName, basicCampus);
                    }
                    campusId = basicCampus.getId();
                }

                // 学院
                Long collegeId = null;
                if (SystemConstant.strNotNull(collegeName)) {
                    SysOrg sysOrg;
                    if (collegeMap.containsKey(collegeName)) {
                        sysOrg = collegeMap.get(collegeName);
                    } else {
                        sysOrg = sysOrgService.getOne(new QueryWrapper<SysOrg>().lambda()
                                .eq(SysOrg::getSchoolId, schoolId)
                                .eq(SysOrg::getType, OrgTypeEnum.COLLEGE)
                                .eq(SysOrg::getName, collegeName));
                        if (Objects.isNull(sysOrg)) {
                            throw ExceptionResultEnum.ERROR.exception("系统中不存在【学院】：" + collegeName);
                        }
                        collegeMap.put(collegeName, sysOrg);
                    }
                    collegeId = sysOrg.getId();
                }

                // 专业
                Long majorId = null;
                if (SystemConstant.strNotNull(majorName)) {
                    if (!SystemConstant.longNotNull(collegeId)) {
                        throw ExceptionResultEnum.ERROR.exception("学生专业信息缺失学院信息异常");
                    }
                    String majorKey = schoolId + link + majorName;
                    if (majorMap.containsKey(majorKey)) {
                        majorId = majorMap.get(majorKey);
                    } else {
                        BasicMajor basicMajor = basicMajorService.getOne(new QueryWrapper<BasicMajor>().lambda()
                                .eq(BasicMajor::getSchoolId, schoolId)
                                .eq(BasicMajor::getName, majorName));
                        if (Objects.isNull(basicMajor)) {
                            // 新增一个major
                            BasicMajorParams basicMajorParams = new BasicMajorParams();
                            basicMajorParams.setMajorName(majorName);
                            basicMajorParams.setCollegeId(collegeId);
                            majorId = basicMajorService.saveBasicMajor(basicMajorParams, sysUser);
                        } else {
                            majorId = basicMajor.getId();
                        }
                        majorMap.put(majorKey, majorId);
                    }
                }

                // 班级
                Long clazzId = null;
                if (SystemConstant.strNotNull(clazzName)) {
                    if (!SystemConstant.longNotNull(campusId)) {
                        throw ExceptionResultEnum.ERROR.exception("学生班级信息缺失校区信息异常");
                    }
                    if (!SystemConstant.longNotNull(collegeId)) {
                        throw ExceptionResultEnum.ERROR.exception("学生班级信息缺失学院信息异常");
                    }
                    if (!SystemConstant.longNotNull(majorId)) {
                        throw ExceptionResultEnum.ERROR.exception("学生班级信息缺失专业信息异常");
                    }

                    String clazzKey = schoolId + link + clazzName;
                    if (clazzMap.containsKey(clazzKey)) {
                        clazzId = clazzMap.get(clazzKey);
                    } else {
                        // 2022-03-30 字典班级在全校唯一
                        BasicClazz basicClazz = basicClazzService.getOne(new QueryWrapper<BasicClazz>().lambda()
                                .eq(BasicClazz::getSchoolId, schoolId)
                                .eq(BasicClazz::getClazzName, clazzName));
                        if (Objects.isNull(basicClazz)) {
                            // 新增一个clazz
                            BasicClazzParams basicClazzParams = new BasicClazzParams();
                            basicClazzParams.setCampusId(campusId);
                            basicClazzParams.setMajorId(majorId);
                            basicClazzParams.setClazzName(clazzName);
                            clazzId = basicClazzService.saveBasicClazz(basicClazzParams, sysUser);
                        } else {
                            clazzId = basicClazz.getId();
                        }
                        clazzMap.put(clazzKey, clazzId);
                    }
                }
                // 学生信息组装
                BasicStudentParams basicStudentParams = new BasicStudentParams();
                basicStudentParams.setStudentName(studentName);
                basicStudentParams.setStudentCode(studentCode);
                basicStudentParams.setPhoneNumber(phoneNumber);
                if (SystemConstant.longNotNull(campusId)) {
                    basicStudentParams.setCampusId(campusId);
                }
                if (SystemConstant.longNotNull(collegeId)) {
                    basicStudentParams.setCollegeId(collegeId);
                }
                if (SystemConstant.longNotNull(majorId)) {
                    basicStudentParams.setMajorId(majorId);
                }
                if (SystemConstant.longNotNull(clazzId)) {
                    basicStudentParams.setClazzId(clazzId);
                }

                BasicStudent tmp = this.getOne(new QueryWrapper<BasicStudent>().lambda()
                        .eq(BasicStudent::getSchoolId, sysUser.getSchoolId())
                        .eq(BasicStudent::getEnable, true)
                        .eq(BasicStudent::getStudentCode, studentCode));
                if (Objects.nonNull(tmp)) {
                    basicStudentParams.setId(tmp.getId());
                }
                addBasicStudentParamsList.add(basicStudentParams);
            }

            List<BasicStudent> basicStudentList = this.editEntityHelp(addBasicStudentParamsList, sysUser);
            this.saveOrUpdateBatch(basicStudentList);
        }
        return map;
    }

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

            // 班级验证
            if (SystemConstant.longNotNull(clazzId)) {
                // 如果有班级id 再验证
                BasicClazz basicClazz = basicClazzService.getById(clazzId);
                if (Objects.isNull(basicClazz)) {
                    throw ExceptionResultEnum.ERROR.exception("所选班级不存在");
                }
                if (SystemConstant.longNotNull(campusId)) {
                    if (!campusId.equals(basicClazz.getCampusId())) {
                        String exception = "学生信息【" + studentName + "(" + studentCode + ")" + "-" + basicCampusService.getById(campusId).getCampusName() + "】中的校区和学生所属班级信息【" + basicClazz.getClazzName() + "-" + basicCampusService.getById(basicClazz.getCampusId()).getCampusName() + "】中的校区不对应";
                        throw ExceptionResultEnum.ERROR.exception(exception);
                    }
                }
                if (SystemConstant.longNotNull(majorId)) {
                    if (!majorId.equals(basicClazz.getMajorId())) {
                        String exception = "学生信息【" + studentName + "(" + studentCode + ")" + "-" + basicMajorService.getById(majorId).getName() + "】中的专业和学生所属班级信息【" + basicClazz.getClazzName() + "-" + basicMajorService.getById(basicClazz.getMajorId()).getName() + "】中的专业不对应";
                        throw ExceptionResultEnum.ERROR.exception(exception);
                    }
                }
            }


            // 专业验证
            if (SystemConstant.longNotNull(majorId)) {
                BasicMajor basicMajor = basicMajorService.getById(majorId);
                if (Objects.isNull(basicMajor)) {
                    throw ExceptionResultEnum.ERROR.exception("所选专业不存在");
                }
                if (SystemConstant.longNotNull(collegeId)) {
                    if (!collegeId.equals(basicMajor.getBelongOrgId())) {
                        String exception = "学生信息【" + studentName + "(" + studentCode + ")" + "-" + sysOrgService.getById(collegeId).getName() + "】中的学院和学生所属专业信息【" + basicMajor.getName() + "-" + sysOrgService.getById(basicMajor.getBelongOrgId()).getName() + "】中的学院不对应";
                        throw ExceptionResultEnum.ERROR.exception(exception);
                    }
                }
            }

            Long id = basicStudentParams.getId();
            // 检验学号在学校的唯一性
            BasicStudent checkCode = this.getOne(new QueryWrapper<BasicStudent>().lambda()
                    .eq(BasicStudent::getSchoolId, schoolId)
                    .eq(BasicStudent::getStudentCode, studentCode)
                    .eq(BasicStudent::getEnable, true));
            if (Objects.nonNull(checkCode)) {
                if (!checkCode.getId().equals(id)) {
                    throw ExceptionResultEnum.ERROR.exception("学生编号【" + studentCode + "】重复");
                }
            }

            // 检验有值的电话在学校的唯一性
            if (SystemConstant.strNotNull(phoneNumber)) {
                BasicStudent checkPhone = this.getOne(new QueryWrapper<BasicStudent>().lambda()
                        .eq(BasicStudent::getSchoolId, schoolId)
                        .eq(BasicStudent::getPhoneNumber, phoneNumber)
                        .eq(BasicStudent::getEnable, true));
                if (Objects.nonNull(checkPhone)) {
                    if (!checkPhone.getId().equals(id)) {
                        throw ExceptionResultEnum.ERROR.exception("学生电话【" + phoneNumber + "】重复");
                    }
                }
            }

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

            // 保存
            if (!SystemConstant.longNotNull(id)) {
                // id为空 -> 新增
                // 获取分布式id
                orgId = sysUser.getOrgId();
                id = SystemConstant.getDbUuid();
                basicStudent.setId(id);

                basicStudent.setCreateId(sysUser.getId());
            } else {
                // id不为空 -> 更新
                BasicStudent old = this.getById(id);
                if (Objects.isNull(old) || old.getEnable().equals(false)) {
                    throw ExceptionResultEnum.ERROR.exception("学生主键不存在或被禁用");
                }
                orgId = old.getOrgId();
                basicStudent.setId(id);
                basicStudent.setUpdateId(sysUser.getId());
            }
            basicStudent.setOrgId(orgId);
            editEntityList.add(basicStudent);
        }
        return editEntityList;
    }
}
