package com.srs.dormitory.service.impl;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.srs.common.core.domain.AjaxResult;
import com.srs.comprehensive.domain.SrsStudent;
import com.srs.comprehensive.mapper.SrsStudentMapper;
import com.srs.dormitory.domain.DmsDormitory;
import com.srs.dormitory.domain.DmsNewRange;
import com.srs.dormitory.domain.Dto.DmsSearch;
import com.srs.dormitory.domain.SrsDormitoryStudent;
import com.srs.dormitory.domain.Vo.DomInfo;
import com.srs.dormitory.mapper.DmsDormitoryMapper;
import com.srs.dormitory.mapper.DmsNewRangeMapper;
import com.srs.dormitory.mapper.SrsDormitoryStudentMapper;
import com.srs.dormitory.service.ISrsDormitoryStudentService;
import com.srs.stureg.domain.SrsStuReg;
import com.srs.stureg.mapper.SrsStuRegMapper;
import liquibase.pro.packaged.D;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import com.srs.dormitory.mapper.DmsNewRegMapper;
import com.srs.dormitory.domain.DmsNewReg;
import com.srs.dormitory.service.IDmsNewRegService;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import static com.srs.common.utils.DateUtils.getNowDate;

/**
 * 新生宿舍Service业务层处理
 *
 * @author srs
 * @date 2024-03-30
 */
@Service
public class DmsNewRegServiceImpl extends ServiceImpl<DmsNewRegMapper, DmsNewReg> implements IDmsNewRegService {
    @Autowired
    private DmsNewRegMapper dmsNewRegMapper;

    @Autowired
    private SrsStuRegMapper srsStuRegMapper;

    @Autowired
    public SrsStudentMapper _stuMapper;

    @Autowired
    public SrsDormitoryStudentMapper _stuDormMapper;

    @Autowired
    public DmsDormitoryMapper _dormMapper;

    @Autowired
    public DmsNewRangeMapper _rangeMapper;

    @Autowired
    public PlatformTransactionManager transactionManager;

    @Autowired
    public ISrsDormitoryStudentService _stuDormService;


    @Override
    public AjaxResult getStuDorm(DmsSearch param) {
        DomInfo res = dmsNewRegMapper.getStuDorm(param);
        return AjaxResult.success(res);
    }

    @Override
    public AjaxResult checkAllDorm() {
        //如果有后来人要改这个功能 我的建议是写个队列 或者用线程池
        try {
            List<Map<Object, Object>> res = new ArrayList<>();//操作结果

            QueryWrapper<SrsStuReg> regQuery = new QueryWrapper<>();
            regQuery.eq("reg_status", 3);
            List<SrsStuReg> stuList = srsStuRegMapper.selectList(regQuery); //已经报到的学生
            if (stuList.size() == 0) {
                throw new Exception("当前没有新生已报到");
            }

            QueryWrapper<DmsNewRange> rangeQuery = new QueryWrapper<>();
            rangeQuery.eq("range_status", "1")
                    .last("limit 1");
            DmsNewRange range = _rangeMapper.selectOne(rangeQuery); //当前开启的住宿区间

            if (range == null) {
                throw new Exception("当前未开启住宿区间");
            }

            Instant instant = range.getStartDate().toInstant();
            LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());

            List<SrsStuReg> hasStuNoList = new ArrayList<>(); //有学号的学生

            for (SrsStuReg stu : stuList) {
                if (stu.getXH() != null) {
                    hasStuNoList.add(stu);
                } else {
                    Map<Object, Object> temp = new HashMap<>();
                    temp.put("stuName", stu.getXSXM());
                    temp.put("ksh", stu.getKSH());
                    temp.put("status", "入住失败");
                    temp.put("remark", "该生没有学号");
                    res.add(temp);
                }
            }

            if (hasStuNoList.size() != 0) {

                //有学号的学生的学号list
                List<String> stuNoList = hasStuNoList.stream().map(SrsStuReg::getXH).collect(Collectors.toList());
                QueryWrapper<SrsStudent> schoolStuQuery = new QueryWrapper<>();
                schoolStuQuery.in("stu_no", stuNoList);
                //通过学号list查出在系统中的学生
                List<SrsStudent> schoolStuList = _stuMapper.selectList(schoolStuQuery);

                //有学号并且在系统中查询出的学生的考生号list
                List<String> existStuKshList;
                if (schoolStuList.size() == 0) {
                    existStuKshList = new ArrayList<>();
                    for (SrsStuReg stu : hasStuNoList) {
                        Map<Object, Object> temp = new HashMap<>();
                        temp.put("stuName", stu.getXSXM());
                        temp.put("ksh", stu.getKSH());
                        temp.put("status", "入住失败");
                        temp.put("remark", "未能在系统中查询到该生的学号:" + stu.getXH());
                        res.add(temp);
                    }
                } else if (schoolStuList.size() != hasStuNoList.size()) {
                    //现在在系统中的学生的学号list
                    List<String> nowSchoolStuNoList = schoolStuList.stream().map(SrsStudent::getStuNo).collect(Collectors.toList());

                    //现在不在系统中的学生
                    List<SrsStuReg> notExistStuList = hasStuNoList.stream().filter(x -> !nowSchoolStuNoList.contains(x.getXH())).collect(Collectors.toList());
                    for (SrsStuReg stu : notExistStuList) {
                        Map<Object, Object> temp = new HashMap<>();
                        temp.put("stuName", stu.getXSXM());
                        temp.put("ksh", stu.getKSH());
                        temp.put("status", "入住失败");
                        temp.put("remark", "未能在系统中查询到该生的学号:" + stu.getXH());
                        res.add(temp);
                    }

                    //现在在系统中的学生
                    List<SrsStuReg> existStuList = hasStuNoList.stream().filter(x -> nowSchoolStuNoList.contains(x.getXH())).collect(Collectors.toList());

                    existStuKshList = existStuList.stream().map(SrsStuReg::getKSH).collect(Collectors.toList());

                } else {
                    existStuKshList = hasStuNoList.stream().map(SrsStuReg::getKSH).collect(Collectors.toList());
                }

                if (existStuKshList.size() != 0) {

                    //在系统中的学生的宿舍分配情况
                    QueryWrapper<DmsNewReg> dmsQuery = new QueryWrapper<>();
                    dmsQuery.in("ksh", existStuKshList);
                    List<DmsNewReg> stuDormList = dmsNewRegMapper.selectList(dmsQuery);

                    //在系统中的学生分配的宿舍id集合
                    Set<Long> dormIdList;

                    if (stuDormList.size() == 0) {
                        dormIdList = new HashSet<>();
                        List<SrsStuReg> noDormStuList = hasStuNoList.stream().filter(x -> existStuKshList.contains(x.getKSH())).collect(Collectors.toList());
                        for (SrsStuReg stu : noDormStuList) {
                            Map<Object, Object> temp = new HashMap<>();
                            temp.put("stuName", stu.getXSXM());
                            temp.put("ksh", stu.getKSH());
                            temp.put("status", "入住失败");
                            temp.put("remark", "该生没有分配宿舍");
                            res.add(temp);
                        }
                    } else if (stuDormList.size() != existStuKshList.size()) {
                        List<String> hasDormStuKshList = stuDormList.stream().map(DmsNewReg::getKsh).collect(Collectors.toList());
                        List<SrsStuReg> noDormStuList = hasStuNoList.stream().filter(x -> !hasDormStuKshList.contains(x.getKSH())).collect(Collectors.toList());
                        for (SrsStuReg stu : noDormStuList) {
                            Map<Object, Object> temp = new HashMap<>();
                            temp.put("stuName", stu.getXSXM());
                            temp.put("ksh", stu.getKSH());
                            temp.put("status", "入住失败");
                            temp.put("remark", "该生没有分配宿舍");
                            res.add(temp);
                        }

                        dormIdList = stuDormList.stream().map(DmsNewReg::getDormitoryId).collect(Collectors.toSet());
                    }else{
                        dormIdList = stuDormList.stream().map(DmsNewReg::getDormitoryId).collect(Collectors.toSet());
                    }


                    if(dormIdList.size() != 0){
                        //通过宿舍id查询宿舍是否在系统中存在
                        QueryWrapper<DmsDormitory> dormQuery = new QueryWrapper<>();
                        dormQuery.in("id",dormIdList);
                        List<DmsDormitory> dormList = _dormMapper.selectList(dormQuery);

                        //存在在系统中的宿舍id集合
                        Set<Long> existDormIdList;

                        if(dormList.size() == 0){
                            existDormIdList = new HashSet<>();
                            for (SrsStuReg stu : hasStuNoList) {
                                Map<Object, Object> temp = new HashMap<>();
                                temp.put("stuName", stu.getXSXM());
                                temp.put("ksh", stu.getKSH());
                                temp.put("status", "入住失败");
                                temp.put("remark", "该生分配的宿舍不存在");
                                res.add(temp);
                            }
                        }else if(dormList.size() != dormIdList.size()){
                            List<String> notExistDormKshList = stuDormList.stream().filter(x->dormIdList.contains(x.getDormitoryId())).map(DmsNewReg::getKsh).collect(Collectors.toList());

                            List<SrsStuReg> notExistDormStuList = hasStuNoList.stream().filter(x->notExistDormKshList.contains(x.getKSH())).collect(Collectors.toList());
                            for (SrsStuReg stu : notExistDormStuList) {
                                Map<Object, Object> temp = new HashMap<>();
                                temp.put("stuName", stu.getXSXM());
                                temp.put("ksh", stu.getKSH());
                                temp.put("status", "入住失败");
                                temp.put("remark", "该生分配的宿舍不存在");
                                res.add(temp);
                            }
                            existDormIdList = dormList.stream().map(DmsDormitory::getId).collect(Collectors.toSet());
                        }else{
                            existDormIdList = dormList.stream().map(DmsDormitory::getId).collect(Collectors.toSet());
                        }


                        //通过系统中存在的宿舍id查询宿舍的入住情况
                        QueryWrapper<SrsDormitoryStudent> stuInQuery = new QueryWrapper<>();
                        stuInQuery.in("dormitory_id", existDormIdList);
                        List<SrsDormitoryStudent> stuInDormList = _stuDormMapper.selectList(stuInQuery);

                        List<SrsDormitoryStudent> needInsertList = new ArrayList<>();
                        List<SrsDormitoryStudent> needUpdateList = new ArrayList<>();

                        QueryWrapper<DmsNewReg> canQuery = new QueryWrapper<>();
                        canQuery.in("ksh",existStuKshList)
                                .in("dormitory_id",existDormIdList);

                        List<DmsNewReg> canList = dmsNewRegMapper.selectList(canQuery);

                        List<String> canKshList = canList.stream().map(DmsNewReg::getKsh).collect(Collectors.toList());

                        QueryWrapper<SrsStuReg> canStuQuery = new QueryWrapper<>();
                        canStuQuery.in("KSH",canKshList);
                        List<SrsStuReg> canStuList = srsStuRegMapper.selectList(canStuQuery);

                        List<String> canStuNoList = canStuList.stream().map(SrsStuReg::getXH).collect(Collectors.toList());

                        QueryWrapper<SrsDormitoryStudent> isInStuQuery = new QueryWrapper<>();
                        isInStuQuery.in("stu_no",canStuNoList);
                        List<SrsDormitoryStudent> isInStuList = _stuDormMapper.selectList(isInStuQuery);
                        if(isInStuList.size() != 0){
                            for(SrsDormitoryStudent item:isInStuList){
                                canStuNoList.remove(item.getStuNo());
                                SrsStuReg stu = canStuList.stream().filter(x-> Objects.equals(x.getXH(), item.getStuNo())).findAny().orElse(null);
                                if(stu!= null){
                                    String ksh = stu.getKSH();
                                    DmsNewReg newDorm = canList.stream().filter(x-> Objects.equals(x.getKsh(), ksh)).findAny().orElse(null);
                                    if(newDorm != null){
                                        SrsDormitoryStudent needUpdate = new SrsDormitoryStudent();
                                        needUpdate.setId(item.getId());
                                        needUpdate.setDormitoryId(newDorm.getDormitoryId());
                                        needUpdateList.add(needUpdate);

                                        Map<Object, Object> temp = new HashMap<>();
                                        temp.put("stuName", stu.getXSXM());
                                        temp.put("ksh", stu.getKSH());
                                        temp.put("status", "更新入住信息");
                                        temp.put("remark", "");
                                        res.add(temp);

                                    }
                                }
                            }
                        }

                        for(String stuNo : canStuNoList){
                            SrsStuReg stu = canStuList.stream().filter(x-> Objects.equals(x.getXH(), stuNo)).findAny().orElse(null);
                            if(stu!= null){
                                String ksh = stu.getKSH();
                                DmsNewReg newDorm = canList.stream().filter(x-> Objects.equals(x.getKsh(), ksh)).findAny().orElse(null);
                                if(newDorm != null){
                                    SrsDormitoryStudent needInsertDorm = new SrsDormitoryStudent();
                                    needInsertDorm.setStuNo(stuNo);
                                    needInsertDorm.setCheckinTime(localDateTime);
                                    needInsertDorm.setDormitoryId(newDorm.getDormitoryId());
                                    needInsertDorm.setIsDormitoryHead(0);
                                    needInsertDorm.setStatus(0);
                                    needInsertDorm.setInStatus("1");

                                    needInsertList.add(needInsertDorm);

                                    Map<Object, Object> temp = new HashMap<>();
                                    temp.put("stuName", stu.getXSXM());
                                    temp.put("ksh", stu.getKSH());
                                    temp.put("status", "添加入住信息");
                                    temp.put("remark", "");
                                    res.add(temp);
                                }
                            }
                        }

                        if(needInsertList.size() != 0 ){
                            _stuDormService.saveBatch(needInsertList);
                        }

                        if(needUpdateList.size() != 0){
                            _stuDormService.updateBatchById(needUpdateList);
                        }




                    }


                }


            }


            return AjaxResult.success(res);
        } catch (Exception ex) {
            return AjaxResult.error(ex.getMessage());
        }
    }


    @Override
    public AjaxResult checkDorm(String ksh) {
        TransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(def);
        try {
            QueryWrapper<SrsStuReg> regQuery = new QueryWrapper<>();
            regQuery.eq("KSH", ksh)
                    .last("limit 1");
            SrsStuReg stu = srsStuRegMapper.selectOne(regQuery);
            if (stu == null) {
                throw new Exception("该考生号的学生无记录");
            }

            if (stu.getXH() == null || Objects.equals(stu.getXH(), "")) {
                throw new Exception("该生没有学号");
            }

            String stuNo = stu.getXH();

            QueryWrapper<SrsStudent> stuQuery = new QueryWrapper<>();
            stuQuery.eq("stu_no", stuNo)
                    .last("limit 1");
            SrsStudent getStu = _stuMapper.selectOne(stuQuery);
            if (getStu == null) {
                throw new Exception("未能查询到该生学号的相关信息");
            }

            QueryWrapper<DmsNewReg> dmsQuery = new QueryWrapper<>();
            dmsQuery.eq("ksh", ksh)
                    .last("limit 1");
            DmsNewReg stuDorm = dmsNewRegMapper.selectOne(dmsQuery);
            if (stuDorm == null) {
                throw new Exception("该生未分配宿舍");
            }

            Long dormId = stuDorm.getDormitoryId();

            QueryWrapper<SrsDormitoryStudent> stuInQuery = new QueryWrapper<>();
            stuInQuery.eq("dormitory_id", dormId)
                    .ne("stu_no",stuNo);
            List<SrsDormitoryStudent> stuInDormList = _stuDormMapper.selectList(stuInQuery);

            DmsDormitory dorm = _dormMapper.selectById(dormId);

            if (dorm == null) {
                throw new Exception("宿舍不存在");
            }

            int canNum = dorm.getBedNum();

            if (stuInDormList.size() == canNum) {
                throw new Exception("该宿舍入住人数已满,不能加入");
            }

            QueryWrapper<DmsNewRange> rangeQuery = new QueryWrapper<>();
            rangeQuery.eq("range_status", "1")
                    .last("limit 1");
            DmsNewRange range = _rangeMapper.selectOne(rangeQuery);

            if (range == null) {
                throw new Exception("当前未开启住宿区间");
            }


            Instant instant = range.getStartDate().toInstant();
            LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());

            QueryWrapper<SrsDormitoryStudent> findInStuDormQuery = new QueryWrapper<>();
            findInStuDormQuery.eq("stu_no", stuNo)
                    .last("limit 1");
            SrsDormitoryStudent findInStu = _stuDormMapper.selectOne(findInStuDormQuery);
            if (findInStu == null) {
                SrsDormitoryStudent needInsertDorm = new SrsDormitoryStudent();
                needInsertDorm.setStuNo(stuNo);
                needInsertDorm.setCheckinTime(localDateTime);
                needInsertDorm.setDormitoryId(dormId);
                needInsertDorm.setIsDormitoryHead(0);
                needInsertDorm.setStatus(0);
                needInsertDorm.setInStatus("1");

                int res1 = _stuDormMapper.insert(needInsertDorm);
                if (res1 == 0) {
                    throw new Exception("插入学生宿舍信息表失败");
                }
            } else {
                findInStu.setDormitoryId(dormId);
                findInStu.setCheckinTime(localDateTime);
                int res1 = _stuDormMapper.updateById(findInStu);
                if (res1 == 0) {
                    throw new Exception("更新学生宿舍信息失败");
                }
            }


            transactionManager.commit(status);
            return AjaxResult.success();
        } catch (Exception ex) {
            transactionManager.rollback(status);
            return AjaxResult.error(ex.getMessage());
        }
    }


    /**
     * 查询新生宿舍
     *
     * @param id 新生宿舍主键
     * @return 新生宿舍
     */
    @Override
    public DmsNewReg selectDmsNewRegById(Long id) {
        return dmsNewRegMapper.selectDmsNewRegById(id);
    }

    /**
     * 查询新生宿舍列表
     *
     * @param dmsNewReg 新生宿舍
     * @return 新生宿舍
     */
    @Override
    public List<DmsNewReg> selectDmsNewRegList(DmsNewReg dmsNewReg) {
        return dmsNewRegMapper.selectDmsNewRegList(dmsNewReg);
    }

    /**
     * 新增新生宿舍
     *
     * @param dmsNewReg 新生宿舍
     * @return 结果
     */
    @Override
    public int insertDmsNewReg(DmsNewReg dmsNewReg) {
        dmsNewReg.setCreateTime(getNowDate());
        return dmsNewRegMapper.insertDmsNewReg(dmsNewReg);
    }

    /**
     * 修改新生宿舍
     *
     * @param dmsNewReg 新生宿舍
     * @return 结果
     */
    @Override
    public int updateDmsNewReg(DmsNewReg dmsNewReg) {
        dmsNewReg.setUpdateTime(getNowDate());
        return dmsNewRegMapper.updateDmsNewReg(dmsNewReg);
    }

    /**
     * 批量删除新生宿舍
     *
     * @param ids 需要删除的新生宿舍主键
     * @return 结果
     */
    @Override
    public int deleteDmsNewRegByIds(Long[] ids) {
        return dmsNewRegMapper.deleteDmsNewRegByIds(ids);
    }

    /**
     * 删除新生宿舍信息
     *
     * @param id 新生宿舍主键
     * @return 结果
     */
    @Override
    public int deleteDmsNewRegById(Long id) {
        return dmsNewRegMapper.deleteDmsNewRegById(id);
    }
}
