package com.xinyilu.system.service.studentInfo.impl;

import com.xinyilu.common.constant.Constants;
import com.xinyilu.common.core.domain.AjaxResult;
import com.xinyilu.common.core.domain.entity.SysDictData;
import com.xinyilu.common.core.domain.entity.SysRole;
import com.xinyilu.common.core.page.TableDataInfo;
import com.xinyilu.common.exception.ServiceException;
import com.xinyilu.common.utils.DateUtils;
import com.xinyilu.common.utils.PageServiceUtil;
import com.xinyilu.common.utils.SecurityUtils;
import com.xinyilu.system.domain.classinfo.ClassInfo;
import com.xinyilu.system.domain.dto.ClassInfoDTO;
import com.xinyilu.system.domain.dto.StudentInfoDTO;
import com.xinyilu.system.domain.parentInfo.ParentInfo;
import com.xinyilu.system.domain.parentStudentInfo.ParentStudentInfo;
import com.xinyilu.system.domain.systemarea.SysArea;
import com.xinyilu.system.domain.sysuserclassrelation.SysUserClassRelation;
import com.xinyilu.system.domain.vo.ClassInfoVO;
import com.xinyilu.system.domain.vo.StudentInfoVO;
import com.xinyilu.system.domain.vo.StudentInforImportlVO;
import com.xinyilu.system.domain.vo.SysUserVO;
import com.xinyilu.system.mapper.SysDictDataMapper;
import com.xinyilu.system.mapper.SysUserMapper;
import com.xinyilu.system.mapper.classinfo.ClassInfoMapper;
import com.xinyilu.system.mapper.parentStudentInfo.ParentStudentInfoMapper;
import com.xinyilu.system.mapper.studentInfo.StudentInfoMapper;
import com.xinyilu.system.mapper.systemarea.SysAreaMapper;
import com.xinyilu.system.mapper.sysuserclassrelation.SysUserClassRelationMapper;
import com.xinyilu.system.service.studentInfo.IStudentInfoService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 学生信息Service业务层处理
 *
 * @author jihan
 * @date 2022-08-01
 */
@Service
public class StudentInfoServiceImpl implements IStudentInfoService {

    @Resource
    private StudentInfoMapper studentInfoMapper;
    @Resource
    private ParentStudentInfoMapper parentStudentInfoMapper;
    @Resource
    private PageServiceUtil pageServiceUtil;
    @Resource
    private ClassInfoMapper classInfoMapper;
    @Resource
    private SysDictDataMapper sysDictDataMapper;
    @Resource
    private SysUserMapper userMapper;
    @Resource
    private SysUserClassRelationMapper sysUserClassRelationMapper;
    @Resource
    private SysAreaMapper sysAreaMapper;

    /**
     * 查询学生信息
     *
     * @param id 学生信息主键
     * @return 学生信息
     */
    @Override
    public StudentInfoVO selectStudentInfoById(Long id) {
        //查询学生信息
        StudentInfoVO studentInfoVO = studentInfoMapper.selectStudentInfoById(id);
        if (Objects.isNull(studentInfoVO)) {
            return new StudentInfoVO();
        }
        //查询学生对应家长信息
        List<ParentInfo> parentInfoList = studentInfoMapper.getParentInfoList(studentInfoVO.getId());
        if (CollectionUtils.isNotEmpty(parentInfoList)) {
            studentInfoVO.setParentStudentInfoList(parentInfoList);
        }
        return studentInfoVO;
    }

    /**
     * 查询学生信息列表
     *
     * @param studentInfo 学生信息
     * @return 学生信息
     */
    @Override
    public TableDataInfo selectStudentInfoList(StudentInfoDTO studentInfo) {
        //判断当前用户角色，根据不同的角色查询不同的学生列表信息
        List<String> roleKeys = SecurityUtils.getLoginUser().getUser().getRoles()
                .stream().filter(Objects::nonNull)
                .filter(item -> StringUtils.isNotBlank(item.getRoleKey()))
                .map(SysRole::getRoleKey).collect(Collectors.toList());
        Long userId = SecurityUtils.getUserId();
        SysUserVO sysUserVO = userMapper.selectUserById(userId);
        if (roleKeys.contains(Constants.ADMIN_ROLE)) {
            //角色为管理员，查询所有的学生信息
            return getStudentInfoList(studentInfo);
        } else if (roleKeys.contains(Constants.CITY)) {
            //角色为市级角色，查询该该市级下所有幼儿园中的学生信息
            long areaId = Objects.isNull(SecurityUtils.getLoginUser().getUser().getAreaId()) ? 0 : SecurityUtils.getLoginUser().getUser().getAreaId();
            List<Long> kindergartenIdList = Lists.newArrayList();
            SysArea sysArea = new SysArea();
            sysArea.setParentId(areaId);
            List<Long> sysAreaIdList = sysAreaMapper.selectSysAreaList(sysArea).stream().filter(Objects::nonNull).filter(sysAreaId -> Objects.nonNull(sysAreaId.getId())).map(SysArea::getId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(sysAreaIdList)) {
                //获取该区域下的所有幼儿园信息
                kindergartenIdList = classInfoMapper.getKindergartenInfoByAreaId(sysAreaIdList, null);
            }
            if (CollectionUtils.isEmpty(kindergartenIdList)) {
                return null;
            }
            //找出当前市下所有幼儿园下的所有班级信息
            List<Long> classIdList = studentInfoMapper.getClassIdByKindergartenIdList(kindergartenIdList);
            studentInfo.setClassIdList(classIdList);
            return getStudentInfoList(studentInfo);
        } else if (roleKeys.contains(Constants.REGION_ROLE)) {
            //角色为区域角色，查询该区域下所有幼儿园中的学生信息
            long areaId = Objects.isNull(SecurityUtils.getLoginUser().getUser().getAreaId()) ? 0 : SecurityUtils.getLoginUser().getUser().getAreaId();
            List<Long> classIdList = Lists.newArrayList();
            if (areaId != 0) {
                //获取该区域下的所有幼儿园信息
                classIdList = studentInfoMapper.getClassIdByArea(areaId);
            }
            if (CollectionUtils.isEmpty(classIdList)) {
                return null;
            }
            studentInfo.setClassIdList(classIdList);
            return getStudentInfoList(studentInfo);
        } else if (roleKeys.contains(Constants.ENCHOU_ROLE)) {
            //角色为园长，查询其幼儿园中的所有学生的信息
            List<Long> classIdByPrincipalId = studentInfoMapper.getClassIdByPrincipalId(userId);
            if (CollectionUtils.isEmpty(classIdByPrincipalId)) {
                return null;
            }
            studentInfo.setClassIdList(classIdByPrincipalId);
            return getStudentInfoList(studentInfo);
        } else if (roleKeys.contains(Constants.HEALTHCARE_ROLE)) {
            //角色是：保健师，查找出其所属的幼儿园信息
            if (Objects.isNull(sysUserVO) || Objects.isNull(sysUserVO.getKindergartenId()) || sysUserVO.getKindergartenId() == 0L) {
                return null;
            }
            ClassInfoDTO classInfo = new ClassInfoDTO();
            classInfo.setKindergartenId(sysUserVO.getKindergartenId());
            List<Long> classIdByPrincipalIds = classInfoMapper.selectClassInfoList(classInfo).stream().filter(Objects::nonNull).filter(classId -> Objects.nonNull(classId.getId())).map(ClassInfoVO::getId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(classIdByPrincipalIds)) {
                return null;
            }
            studentInfo.setClassIdList(classIdByPrincipalIds);
            return getStudentInfoList(studentInfo);
        } else if (roleKeys.contains(Constants.TEACHER_ROLE) && roleKeys.size() == 1) {
            //角色为老师：查询班级下的所有学生信息
            List<Long> classIdByTeacherId = sysUserClassRelationMapper.getSysUserClassRelationList(userId).stream().filter(Objects::nonNull).filter(classId -> Objects.nonNull(classId.getClassId())).map(SysUserClassRelation::getClassId).distinct().collect(Collectors.toList());
            if (CollectionUtils.isEmpty(classIdByTeacherId)) {
                return null;
            }
            studentInfo.setClassIdList(classIdByTeacherId);
            return getStudentInfoList(studentInfo);
        } else if (roleKeys.contains(Constants.PARENT_ROLE) && roleKeys.size() == 1) {
            //角色为家长，查询其孩子的学生信息
            if (Objects.isNull(sysUserVO) || Objects.isNull(sysUserVO.getPhonenumber())) {
                return null;
            }
            List<Long> studentIdByParent = studentInfoMapper.getStudentIdByParent(sysUserVO.getPhonenumber());
            if (CollectionUtils.isEmpty(studentIdByParent)) {
                return null;
            }
            studentInfo.setIdList(studentIdByParent);
            return getStudentInfoList(studentInfo);
        } else if (roleKeys.contains(Constants.TEACHER_ROLE) && roleKeys.contains(Constants.PARENT_ROLE) && roleKeys.size() == 2) {
            //角色即是老师又是家长，查询自己孩子和班级中所有孩子的学生信息
            List<Long> classIdByTeacherId = sysUserClassRelationMapper.getSysUserClassRelationList(userId).stream().filter(Objects::nonNull).filter(classId -> Objects.nonNull(classId.getClassId())).map(SysUserClassRelation::getClassId).distinct().collect(Collectors.toList());
            List<Long> studentIdByParent = new ArrayList<>();
            if (Objects.nonNull(sysUserVO) && Objects.nonNull(sysUserVO.getPhonenumber())) {
                studentIdByParent = studentInfoMapper.getStudentIdByParent(sysUserVO.getPhonenumber());
            }
            if (CollectionUtils.isEmpty(classIdByTeacherId) && CollectionUtils.isEmpty(studentIdByParent)) {
                return null;
            }
            studentInfo.setClassList(classIdByTeacherId);
            studentInfo.setStudentList(studentIdByParent);
            return getStudentInfoList(studentInfo);
        }
        return null;
    }

    /**
     * 新增学生信息
     *
     * @param studentInfo 学生信息
     * @param createBy    创建人
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult insertStudentInfo(StudentInfoDTO studentInfo, String createBy) {
        //判断家长信息是否为空
        if (CollectionUtils.isEmpty(studentInfo.getParentIdList())) {
            return AjaxResult.error("家长信息不能位空");
        }
        if (StringUtils.isNotBlank(studentInfo.getCardNumber())) {
            // 查询学生的身份证号 看是否重复
            int studentCardNumberInfo = studentInfoMapper.getStudentCardNumberInfo(studentInfo.getCardNumber());
            if (studentCardNumberInfo > 0) {
                return AjaxResult.error("证件号：" + studentInfo.getCardNumber() + "与某个学生的证件号重复，请重新填写！");
            }
        }
        studentInfo.setCreateBy(createBy);
        studentInfo.setCreateTime(DateUtils.getNowDate());
        studentInfo.setDelFlag(0);
        studentInfo.setUserId(SecurityUtils.getUserId());
        //查询幼儿表id
        ClassInfo classInfo = classInfoMapper.selectClassInfoById(studentInfo.getClassId());
        if (Objects.nonNull(classInfo)) {
            studentInfo.setKindergartenId(Objects.isNull(classInfo.getKindergartenId()) ? 0L : classInfo.getKindergartenId());
        }
        //新增学生信息
        int insertStudentCount = studentInfoMapper.insertStudentInfo(studentInfo);
        if (insertStudentCount <= 0) {
            throw new ServiceException("新增学生信息失败");
        }
        //新增学生家长关系表信息
        Long studentId = studentInfo.getId();
        for (Long parentId : studentInfo.getParentIdList()) {
            ParentStudentInfo parentStudentInfo = new ParentStudentInfo();
            parentStudentInfo.setParentId(parentId);
            parentStudentInfo.setStudentId(studentId);
            parentStudentInfo.setDelFlag(0);
            parentStudentInfo.setCreateBy(createBy);
            parentStudentInfo.setCreateTime(DateUtils.getNowDate());
            int parentStudentCount = parentStudentInfoMapper.insertParentStudentInfo(parentStudentInfo);
            if (parentStudentCount <= 0) {
                throw new ServiceException("新增学生家长信息失败");
            }
        }
        return AjaxResult.success();
    }

    /**
     * 修改学生信息
     *
     * @param studentInfo 学生信息
     * @param createBy    创建人
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult updateStudentInfo(StudentInfoDTO studentInfo, String createBy) {
        if (CollectionUtils.isEmpty(studentInfo.getParentIdList())) {
            return AjaxResult.error("家长信息不能为空！");
        }
        StudentInfoVO studentInfoVO = studentInfoMapper.selectStudentInfoById(studentInfo.getId());
        if (Objects.isNull(studentInfoVO)) {
            return AjaxResult.error("学生信息不存在");
        }
        if (StringUtils.isNotBlank(studentInfo.getCardNumber())) {
            if (!studentInfo.getCardNumber().equals(studentInfoVO.getCardNumber())) {
                // 查询学生的身份证号 看是否重复
                int studentCardNumberInfo = studentInfoMapper.getStudentCardNumberInfo(studentInfo.getCardNumber());
                if (studentCardNumberInfo > 0) {
                    return AjaxResult.error("证件号：" + studentInfo.getCardNumber() + "与某个学生的证件号重复，请重新填写！");
                }
            }
        }
        //修改学生信息
        studentInfo.setUpdateTime(DateUtils.getNowDate());
        studentInfo.setUpdateBy(createBy);
        studentInfo.setDelFlag(0);
        //查询幼儿表id
        ClassInfo classInfo = classInfoMapper.selectClassInfoById(studentInfo.getClassId());
        if (Objects.nonNull(classInfo)) {
            studentInfo.setKindergartenId(Objects.isNull(classInfo.getKindergartenId()) ? 0L : classInfo.getKindergartenId());
        }
        int updateCount = studentInfoMapper.updateStudentInfo(studentInfo);
        if (updateCount <= 0) {
            throw new ServiceException("修改学生信息失败");
        }
        //删除学生关系表信息
        int counts = parentStudentInfoMapper.getParentStudentInfoByStudentId(studentInfo.getId());
        if (counts > 0) {
            int deleteCount = parentStudentInfoMapper.deleteParentStudentInfoById(studentInfo.getId());
            if (deleteCount <= 0) {
                throw new ServiceException("删除学生家长信息失败");
            }
        }
        //新增家长学生关系表信息
        for (Long parentId : studentInfo.getParentIdList()) {
            ParentStudentInfo parentStudentInfo = new ParentStudentInfo();
            parentStudentInfo.setParentId(parentId);
            parentStudentInfo.setStudentId(studentInfo.getId());
            parentStudentInfo.setDelFlag(0);
            parentStudentInfo.setCreateBy(createBy);
            parentStudentInfo.setCreateTime(DateUtils.getNowDate());
            int parentStudentCount = parentStudentInfoMapper.insertParentStudentInfo(parentStudentInfo);
            if (parentStudentCount <= 0) {
                throw new ServiceException("新增学生家长信息失败");
            }
        }
        return AjaxResult.success();
    }

    /**
     * 批量删除学生信息
     *
     * @param ids 需要删除的学生信息主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult deleteStudentInfoByIds(Long[] ids) {
        //删除学生信息表
        int deleteStudentCount = studentInfoMapper.updateStudentInfoByIds(ids);
        if (deleteStudentCount <= 0) {
            throw new ServiceException("删除学生信息失败");
        }
        //删除学生家长关系表信息
        int deleteParentStudentInfoCount = parentStudentInfoMapper.updateParentStudentInfoByIds(ids);
        if (deleteParentStudentInfoCount <= 0) {
            throw new ServiceException("删除学生家长信息失败");
        }
        return AjaxResult.success();
    }

    /**
     * 删除学生信息信息
     *
     * @param id 学生信息主键
     * @return 结果
     */
    @Override
    public int deleteStudentInfoById(Long id) {
        return studentInfoMapper.deleteStudentInfoById(id);
    }

    /**
     * 分页查询学生列表信息
     *
     * @param studentInfo 输入参数
     * @return 学生列表信息
     */
    private TableDataInfo getStudentInfoList(StudentInfoDTO studentInfo) {
        pageServiceUtil.startPage();
        List<StudentInfoVO> studentInfoList = studentInfoMapper.selectStudentInfoList(studentInfo);
        return pageServiceUtil.getDataTable(studentInfoList);
    }


    /**
     * 导入学生信息信息
     *
     * @param studentInfoList 学生信息集合
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult importData(List<StudentInforImportlVO> studentInfoList, Long kindergartenId, Long classId) throws Exception {
        if (CollectionUtils.isEmpty(studentInfoList)) {
            AjaxResult.error("请添加数据");
        }
        //获取民族的数据字典
        List<SysDictData> sysDictData = sysDictDataMapper.selectDictDataByType(Constants.NATION_TYPE);
        Map<String, Long> nationTypeMap = sysDictData.stream().filter(Objects::nonNull).collect(Collectors.toMap(SysDictData::getDictLabel, SysDictData::getDictCode));
        //添加传入的幼儿园id和班级id
        for (StudentInforImportlVO item : studentInfoList) {
            if (StringUtils.isNotBlank(item.getCardNumber())) {
                // 查询学生的身份证号 看是否重复
                int studentCardNumberInfo = studentInfoMapper.getStudentCardNumberInfo(item.getCardNumber());
                if (studentCardNumberInfo > 0) {
                    return AjaxResult.error("证件号：" + item.getCardNumber() + "与某个学生的身份证号码重复！");
                }
            }
            item.setKindergartenId(kindergartenId);
            item.setClassId(classId);
            item.setNationDictId(nationTypeMap.getOrDefault(item.getNationName(), 0L));
            item.setCreateTime(DateUtils.getNowDate());
            item.setDelFlag(0);
            item.setUserId(SecurityUtils.getUserId());
        }
        //获取班级下所有的学生信息
        List<StudentInforImportlVO> studentInfoListByClassIds = studentInfoMapper.selectStudentInfoListByClassId(classId);
        //获取差集进行新增
        Collection<StudentInforImportlVO> subtractList = CollectionUtils.subtract(studentInfoList, studentInfoListByClassIds);
        //求出并集,重复数据
        Collection<StudentInforImportlVO> intersectionList = CollectionUtils.intersection(studentInfoList, studentInfoListByClassIds);
        //如果差集为null直接返回
        if (CollectionUtils.isEmpty(subtractList)) {
            Map<String, Collection<StudentInforImportlVO>> map = new HashMap<>();
            map.put("successList", subtractList);
            map.put("failList", intersectionList);
            return AjaxResult.success(map);
        }
        int i = studentInfoMapper.insertStudentInfoList(subtractList);
        if (i <= 0) {
            throw new Exception("学生信息导入错误");
        }
        Map<String, Collection<StudentInforImportlVO>> map = new HashMap<>();
        map.put("successList", subtractList);
        map.put("failList", intersectionList);
        return AjaxResult.success(map);
    }
}
