package com.srs.dormitory.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.srs.common.core.domain.AjaxResult;
import com.srs.common.core.domain.entity.SysUser;
import com.srs.common.utils.DateUtils;
import com.srs.common.utils.SecurityUtils;
import com.srs.common.utils.StringUtils;
import com.srs.common.utils.WeChatUtil;
import com.srs.common.utils.sign.Md5Utils;
import com.srs.comprehensive.domain.CphMsg;
import com.srs.comprehensive.domain.CphTeacher;
import com.srs.comprehensive.domain.SrsStudent;
import com.srs.comprehensive.domain.ViewStuInfo;
import com.srs.comprehensive.domain.Vo.CphSearch;
import com.srs.comprehensive.domain.Vo.StuClass;
import com.srs.comprehensive.mapper.CphTeacherMapper;
import com.srs.comprehensive.mapper.ViewStuInfoMapper;
import com.srs.comprehensive.service.ISrsStudentService;
import com.srs.comprehensive.service.impl.CphMsgServiceImpl;
import com.srs.dormitory.domain.*;
import com.srs.dormitory.domain.Dto.*;
import com.srs.dormitory.domain.Vo.DomInfo;
import com.srs.dormitory.domain.Vo.SrsDormitoryStudentVo;
import com.srs.dormitory.domain.Vo.StuLog;
import com.srs.dormitory.mapper.*;
import com.srs.dormitory.service.IDmsChangeLogService;
import com.srs.dormitory.service.IDmsDormitoryClassService;
import com.srs.dormitory.service.IDmsDormitoryService;
import com.srs.dormitory.service.ISrsDormitoryStudentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.srs.dormitory.utils.DmsRedisLock;
import com.srs.stureg.domain.SrsStuReg;
import com.srs.stureg.mapper.SrsStuRegMapper;
import com.srs.system.mapper.SysUserMapper;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.joda.time.Instant;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

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

import static com.srs.common.utils.DateUtils.getNowDate;
import static com.srs.common.utils.SecurityUtils.getUserId;
import static com.srs.common.utils.SecurityUtils.getUsername;

/**
 * <p>
 * 宿舍学生关联表 服务实现类
 * </p>
 *
 * @author 猪油骨
 * @since 2023-07-14
 */
@Service
public class ISrsDormitoryStudentServiceImpl extends ServiceImpl<SrsDormitoryStudentMapper, SrsDormitoryStudent> implements ISrsDormitoryStudentService {
    @Autowired
    private ISrsStudentService srsStudentService;
    @Autowired
    private IDmsDormitoryClassService dmsDormitoryClassService;
    @Autowired
    private DmsDormitoryMapper dmsDormitoryMapper;
    @Autowired
    private IDmsDormitoryService dmsDormitoryService;
    @Autowired
    private IDmsChangeLogService dmsChangeLogService;
    @Autowired
    private SrsStuRegMapper srsStuRegMapper;
    @Autowired
    DmsDormitoryClassMapper classMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private DmsDormitoryBuildingMapper buildingMapper;
    @Autowired
    private ISrsDormitoryStudentService dormitoryStudentService;
    @Autowired
    public SrsDormitoryStudentMapper _dormStuMapper;
    @Autowired
    public DmsNewRecordMapper _newRecordMapper;
    @Autowired
    public DmsNewRegMapper _newRegMapper;
    @Autowired
    private SrsDormitoryStudentMapper srsDormitoryStudentMapper;
    @Autowired
    DmsNewRangeMapper _rangeMapper;

    @Autowired
    public ViewStuInfoMapper _viewStuInfoMapper;
    @Autowired
    public WeChatUtil weChatUtil;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private CphMsgServiceImpl _cphMsgService;

    @Autowired
    private CphTeacherMapper cphTeacherMapper;

    @Override
    public AjaxResult sendStudentConfirmMsg(SendConfirmDto param){
        try{
            QueryWrapper<ViewStuInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("grade_id", param.getGradeId());
            queryWrapper.eq("status","01");
            List<ViewStuInfo> stuList = _viewStuInfoMapper.selectList(queryWrapper);
            List<String> stuNos = stuList.stream().map(ViewStuInfo::getStuNo).collect(Collectors.toList());
            if(stuNos.isEmpty()){
                throw new Exception("该年级无在校生");
            }

//            List<String> test = new ArrayList<>();
//            test.add("20240116");
//            test.add("20210080");
//            test.add("20200016");
//            test.add("20190025");
//            test.add("20210081");

            int batchSize = 900;
            for (int i = 0; i < stuNos.size(); i += batchSize) {
                List<String> batch = stuNos.subList(i, Math.min(i + batchSize, stuNos.size()));
                // 拼接成"2023001|2023002|2023003"格式
                String toUser = String.join("|", batch);
                // 调用你的发送消息方法
                weChatUtil.sendTextMessage(toUser, "请于"+param.endDate+"前，前往学工系统->宿舍管理->住宿费用->学生住宿确认宿舍入住情况，如宿舍入住信息有误请反馈给辅导员。");
            }

            List<SysUser> userList = sysUserMapper.selectList(
                    new QueryWrapper<SysUser>()
                            .in("user_name", stuNos)
            );

            List<CphMsg> addList = new ArrayList<>();
            for (SysUser user : userList) {
                CphMsg cphMsg = new CphMsg();
                cphMsg.setCreateTime(getNowDate());
                cphMsg.setCreateBy(getUsername());
                cphMsg.setReceiver(user.getUserId());
                cphMsg.setSender(getUserId());
                cphMsg.setContent("请于"+param.endDate+"前，前往学工系统->宿舍管理->住宿费用->学生住宿确认宿舍入住情况，如宿舍入住信息有误请反馈给辅导员。");
                addList.add(cphMsg);
            }
            boolean res = _cphMsgService.saveBatch(addList);
            if(!res){
                throw new Exception("系统推送消息失败");
            }



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



    @Override
    public List<SrsDormitoryStudentVo> list(DmsSearch param){
        return _dormStuMapper.list(param);
    }

    @Override
    public List<StuClass> listView(CphSearch param){
        return _dormStuMapper.listView(param);
    }

    @Override
    public String doImport(List<ImportDormStuDto> list , boolean updateSupport){
        String msg = "";
        List<DomInfo> dormList = dmsDormitoryMapper.viewDormInfo();
        List<SrsDormitoryStudent> addList = new ArrayList<>();
        List<SrsDormitoryStudent> updateList = new ArrayList<>();
        int addCount =0;
        int updateCount =0;
        QueryWrapper<DmsNewRange> rangeQueryWrapper = new QueryWrapper<>();
        rangeQueryWrapper.eq("range_status",1);
        DmsNewRange dmsNewRange = _rangeMapper.selectOne(rangeQueryWrapper);
        if(dmsNewRange == null){
            return "当前未设置入住时间范围，请联系管理员！";
        }

        LocalDateTime checkInTime = LocalDateTime.ofInstant(dmsNewRange.getStartDate().toInstant(), ZoneId.systemDefault());

        for (ImportDormStuDto dto : list) {
            QueryWrapper<SrsDormitoryStudent> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("stu_no", dto.getStuNo());
            SrsDormitoryStudent srsDormitoryStudent = srsDormitoryStudentMapper.selectOne(queryWrapper);
            if (srsDormitoryStudent == null) {
                DomInfo dormInfo = dormList.stream()
                       .filter(x -> x.parkName.equals(dto.parkName)
                            && x.buildingName.equals(dto.buildingName)
                               && x.roomNo.equals(dto.roomNo)
                       )
                       .findFirst().orElse(null);
                if (dormInfo != null) {
                    SrsDormitoryStudent student = new SrsDormitoryStudent();
                    student.setStuNo(dto.getStuNo());
                    student.setDormitoryId(Long.parseLong(dormInfo.getId().toString()));
                    student.setCheckinTime(checkInTime);
                    addList.add(student);
                    msg += "学号:"+dto.getStuNo() + "导入！ <br/>";
                    addCount ++;
                }else{
                    msg += "学号:"+dto.getStuNo() + "的宿舍信息不存在，请检查！ <br/>";
                }

            }else{
                if(updateSupport){
                    DomInfo dormInfo = dormList.stream()
                            .filter(x -> x.parkName.equals(dto.parkName)
                                    && x.buildingName.equals(dto.buildingName)
                                    && x.roomNo.equals(dto.roomNo)
                            )
                            .findFirst().orElse(null);
                    if (dormInfo != null) {
                        SrsDormitoryStudent student = new SrsDormitoryStudent();
                        student.setId(srsDormitoryStudent.getId());
                        student.setStuNo(dto.getStuNo());
                        student.setDormitoryId(Long.parseLong(dormInfo.getId().toString()));
                        updateList.add(student);
                        msg += "学号:"+dto.getStuNo() + "修改！ <br/>";
                        updateCount ++;
                    }else{
                        msg += "学号:"+dto.getStuNo() + "的宿舍信息不存在，请检查！ <br/>";
                    }
                }else{
                    msg += "学号:"+dto.getStuNo() + "已存在，不导入！ <br/>";
                }
            }
        }

        if(addList.size() > 0){
            boolean res1 = this.saveBatch(addList);
            if(res1){
                msg += "成功导入"+addCount+"条数据！ <br/>";
            }else{
                msg += "导入失败！ <br/>";
            }
        }

        if(updateList.size() > 0){
            boolean res2 = this.updateBatchById(updateList);
            if(res2){
                msg += "成功修改"+updateCount+"条数据！ <br/>";
            }else{
                msg += "修改失败！ <br/>";
            }
        }



        return msg;
    }

    @Override
    public AjaxResult getStuLog( String stuNo){
        DmsSearch dormStuQuery = new DmsSearch();
        dormStuQuery.setStuNo(stuNo);
        List<SrsDormitoryStudentVo> dormStus = _dormStuMapper.list(dormStuQuery);
        SrsDormitoryStudentVo dormStu = null;
        if(dormStus.size() != 0){
            dormStu = dormStus.get(0);
        }
        DmsNewRecord recordQuery = new DmsNewRecord();
        recordQuery.setStuNo(stuNo);
        List<DmsNewRecord> record = _newRecordMapper.selectDmsNewRecordList(recordQuery);

        Date setTime = new Date();
        setTime.setTime(0);

        record.forEach(x->{
            if(x.getStartDate().getTime() == x.getRangeStart().getTime()){
                x.setStartDate(setTime);
            }
            if(x.getEndDate().getTime() == x.getRangeEnd().getTime()){
                x.setEndDate(setTime);
            }
        });

        StuLog log = new StuLog();
        log.dormStu = dormStu;
        log.record = record;
        return AjaxResult.success(log);
    }

    /**
     * 学生自主选择床位
     *
     * @param studentDormitoryDto 请求参数
     * @return
     */
    @Transactional
    @Override
    public AjaxResult addStudentDormitory(StudentDormitoryDto studentDormitoryDto) {
        List<Map<String, Object>> maps = null;
        DmsRedisLock lock = new DmsRedisLock(studentDormitoryDto.getBedId() + "", stringRedisTemplate);
        boolean tryLock = lock.tryLock(5);
        try {
            if (!tryLock) {
                return AjaxResult.error("该床位已被占用");
            }
            SrsStuReg stuReg = srsStuRegMapper.getOwnInfoByKsh(SecurityUtils.getUsername());
            //校验当前学生是否已经选择床位
            SrsDormitoryStudent one = lambdaQuery().eq(SrsDormitoryStudent::getStuNo, stuReg.getXH())
                    .one();
            if (one != null) {
                return AjaxResult.error("您已选择床位，无法重复选择");
            }
            //校验该宿舍是否为当前学生班级的宿舍
            List<DmsDormitoryClass> list = dmsDormitoryClassService.lambdaQuery()
                    .eq(DmsDormitoryClass::getBJDM, stuReg.getBJDM())
                    .list();
            boolean check = false;
            for (DmsDormitoryClass dmsDormitoryClass : list) {
                if (Objects.equals(studentDormitoryDto.getDormitoryId(), dmsDormitoryClass.getDormitoryId())) {
                    check = true;
                    break;
                }
            }
            if (!check) {
                return AjaxResult.error("只能选择本班级的宿舍");
            }
            //校验该床位ID是否存在和学生所选的宿舍性别是否正确
            Map<String, Object> map = new HashMap<>();
            map.put("dormitoryId", studentDormitoryDto.getDormitoryId());
            List<Map<String, Object>> dormitoryInfoList = dmsDormitoryMapper.getDormitoryInfoList(map);
            if (dormitoryInfoList.get(0) == null) {
                return AjaxResult.error("床位ID不存在");
            }
            if (!dormitoryInfoList.get(0).get("gender").toString().equals(stuReg.getXB())) {
                return AjaxResult.error("您无法入住该宿舍");
            }
            //校验当前床位是否已经有人
            LambdaQueryWrapper<SrsDormitoryStudent> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SrsDormitoryStudent::getBedId, studentDormitoryDto.getBedId());
            SrsDormitoryStudent dormitoryStudent = baseMapper.selectOne(wrapper);
            if (dormitoryStudent != null) {
                return AjaxResult.error("当前床位已经有人占用");
            }
            //开始添加关联
            SrsDormitoryStudent srsDormitoryStudent = new SrsDormitoryStudent();
            BeanUtils.copyProperties(studentDormitoryDto, srsDormitoryStudent);
            srsDormitoryStudent.setCheckinTime(LocalDateTime.now());
            srsDormitoryStudent.setStuNo(stuReg.getXH());
            int insert = baseMapper.insert(srsDormitoryStudent);
            if (insert <= 0) throw new RuntimeException("添加学生宿舍关联错误");
            //修改学生表的宿舍id
            SrsStudent srsStudent = srsStudentService.selectSrsStudentByStuNo(stuReg.getXH());
            if (srsStudent != null) {
                srsStudent.setRoomId(studentDormitoryDto.getDormitoryId());
                int updateStudent = srsStudentService.updateSrsStudent(srsStudent);
                if (updateStudent <= 0) throw new RuntimeException("修改学生信息错误");
            }
            //修改宿舍入住人数
            boolean success = dmsDormitoryService.lambdaUpdate()
                    .eq(DmsDormitory::getId, studentDormitoryDto.getDormitoryId())
                    .setSql("occupancy = occupancy + 1")
                    .update();
            if (!success) {
                throw new RuntimeException("修改宿舍入住人数错误");
            }
            maps = classMapper.selectBeds(studentDormitoryDto.getDormitoryId());
        } finally {
            if (tryLock) lock.unlock();
        }
        return AjaxResult.success(maps);
    }

    /**
     * 管理员分配床位
     *
     * @param studentDormitoryDto 请求参数
     * @return
     */
    @Transactional
    @Override
    public AjaxResult AdminAddStudentDormitory(StudentDormitoryDto studentDormitoryDto) {
        //校验当前学生是否已经选择床位
        SrsDormitoryStudent one = lambdaQuery().eq(SrsDormitoryStudent::getStuNo, studentDormitoryDto.getStuNo())
                .one();
        if (one != null) {
            return AjaxResult.error("该学生已经选择床位，无法重复选择");
        }
        //添加学生和宿舍关联
        SrsDormitoryStudent dormitoryStudent = new SrsDormitoryStudent();
        BeanUtils.copyProperties(studentDormitoryDto, dormitoryStudent);
        dormitoryStudent.setCheckinTime(LocalDateTime.now());
        int i = baseMapper.insert(dormitoryStudent);
        if (i <= 0) throw new RuntimeException("添加学生宿舍关联错误");
        //添加学生宿舍信息记录
        DmsChangeLog changeLog = new DmsChangeLog();
        changeLog.setType("入住");
        changeLog.setStuNo(studentDormitoryDto.getStuNo());
        changeLog.setTargetDormId(studentDormitoryDto.getDormitoryId());
        changeLog.setTargetBedId(studentDormitoryDto.getBedId());
        changeLog.setApprover(SecurityUtils.getUsername());
        boolean save = dmsChangeLogService.save(changeLog);
        if (!save) {
            throw new RuntimeException("添加学生宿舍信息记录错误");
        }
        //修改宿舍人数
        boolean success = dmsDormitoryService.lambdaUpdate()
                .eq(DmsDormitory::getId, studentDormitoryDto.getDormitoryId())
                .setSql("occupancy = occupancy + 1")
                .update();
        if (!success) {
            throw new RuntimeException("修改宿舍人数错误");
        }
        return AjaxResult.success();
    }

    /**
     * 自动分配床位
     *
     * @param majorCodes 需要分配的专业代码列表
     * @return
     */
//    @Transactional
//    @Override
//    public AjaxResult batchAdd(List<String> majorCodes) {
//        List<String> genders = new ArrayList<>();
//        genders.add("男");
//        genders.add("女");
//        int num = 0;
//        List<SrsDormitoryStudent> srsDormitoryStudentList = new ArrayList<>();
//        List<DmsChangeLog> changeLogList = new ArrayList<>();
//        Map<Long, Integer> map = new HashMap<>();
//        for (String code : majorCodes) {
//            for (String gender : genders) {
//                List<SrsStuReg> srsStuRegs = baseMapper.selectStudentNoBed(code, gender);
//                List<DmsDormitoryBed> bedList = baseMapper.selectBedNoStudent(code, gender);
//                if (srsStuRegs.size() > bedList.size()) {
//                    num += srsStuRegs.size() - bedList.size();
//                }
//                for (int i = 0; i < srsStuRegs.size() && i < bedList.size(); i++) {
//                    SrsDormitoryStudent dormitoryStudent = new SrsDormitoryStudent();
//                    dormitoryStudent.setDormitoryId(bedList.get(i).getDormitoryId());
//                    dormitoryStudent.setBedId(bedList.get(i).getId());
//                    dormitoryStudent.setStuNo(srsStuRegs.get(i).getXH());
//                    dormitoryStudent.setCheckinTime(LocalDateTime.now());
//                    srsDormitoryStudentList.add(dormitoryStudent);
//                    DmsChangeLog changeLog = new DmsChangeLog();
//                    changeLog.setStuNo(srsStuRegs.get(i).getXH());
//                    changeLog.setType("入住");
//                    changeLog.setTargetDormId(bedList.get(i).getDormitoryId());
//                    changeLog.setTargetBedId(bedList.get(i).getId());
//                    changeLog.setApprover(SecurityUtils.getUsername());
//                    changeLogList.add(changeLog);
//                    map.merge(bedList.get(i).getDormitoryId(), 1, Integer::sum);
//                }
//            }
//        }
//        for (Long key : map.keySet()) {
//            boolean updateDormitory = dmsDormitoryService.lambdaUpdate()
//                    .eq(DmsDormitory::getId, key)
//                    .setSql("occupancy = occupancy + " + map.get(key))
//                    .update();
//            if (!updateDormitory) throw new RuntimeException("修改宿舍人数失败");
//        }
//        boolean saveLog = dmsChangeLogService.saveBatch(changeLogList);
//        if (!saveLog) throw new RuntimeException("添加学生宿舍修改记录失败");
//        boolean save = saveBatch(srsDormitoryStudentList);
//        if (!save) throw new RuntimeException("添加学生宿舍关联失败");
//        if (num > 0) return AjaxResult.warn("还有" + num + "名学生没有床位分配，请手动分配这些学生");
//        return AjaxResult.success();
//    }

    /**
     * 批量搬出宿舍
     *
     * @param ids 学生宿舍关联ID列表
     * @return
     */
    @Transactional
    @Override
    public AjaxResult batchDelete(List<Long> ids) {
        List<DmsChangeLog> changeLogList = new ArrayList<>();
        Map<Long, Integer> map = new HashMap<>();
        for (Long id : ids) {
            SrsDormitoryStudent dormitoryStudent = baseMapper.selectById(id);
            if (dormitoryStudent == null) {
                throw new RuntimeException("ID" + id + "不存在");
            }
            map.merge(dormitoryStudent.getDormitoryId(), 1, Integer::sum);
            DmsChangeLog changeLog = new DmsChangeLog();
            changeLog.setApprover(SecurityUtils.getUsername());
            changeLog.setStuNo(dormitoryStudent.getStuNo());
            changeLog.setCurrentDormId(dormitoryStudent.getDormitoryId());
            changeLog.setCurrentBedId(dormitoryStudent.getBedId());
            changeLog.setType("退宿");
            changeLogList.add(changeLog);
        }
        for (Long key : map.keySet()) {
            boolean updateDormitory = dmsDormitoryService.lambdaUpdate()
                    .eq(DmsDormitory::getId, key)
                    .setSql("occupancy = occupancy - " + map.get(key))
                    .update();
            if (!updateDormitory) throw new RuntimeException("修改宿舍人数错误");
        }
        boolean b = removeBatchByIds(ids);
        if (!b) throw new RuntimeException("删除学生宿舍关联信息错误");
        boolean saveLog = dmsChangeLogService.saveBatch(changeLogList);
        if (!saveLog) throw new RuntimeException("添加学生宿舍信息修改记录错误");
        return AjaxResult.success();
    }

    /**
     * 取消选择床位
     *
     * @return
     */
    @Override
    public AjaxResult cancel() {
        String username = SecurityUtils.getUsername();
        SrsStuReg stuReg = srsStuRegMapper.getOwnInfoByKsh(username);
        SrsDormitoryStudent dormitoryStudent = lambdaQuery().eq(SrsDormitoryStudent::getStuNo, stuReg.getXH()).one();
        if (dormitoryStudent == null) return AjaxResult.error("您尚未选择床位");
        if (dormitoryStudent.getStatus() == 1) return AjaxResult.error("您已完成缴费，无法取消");
        boolean remove = removeById(dormitoryStudent);
        boolean updateDormitory = dmsDormitoryService.lambdaUpdate()
                .eq(DmsDormitory::getId, dormitoryStudent.getDormitoryId())
                .setSql("occupancy = occupancy - 1")
                .update();
        if (!updateDormitory) throw new RuntimeException("修改宿舍人数失败");
        if (!remove) return AjaxResult.error("取消失败");
        return AjaxResult.success("取消成功");
    }

    /**
     * 查看还没有选择床位的学生
     *
     * @return
     */
    @Override
    public List<SrsStuReg> getNoBedStudent() {
        return baseMapper.getNoBedStudent();
    }

    /**
     * 毕业生一键退宿
     *
     * @param gradeId 年级id
     * @param deptId  学院id
     * @param majorId 专业id
     * @return
     */
    @Override
    @Transactional
    public AjaxResult out(Long gradeId, Long deptId, Long majorId) {
        List<String> nos = baseMapper.selectStuNo(gradeId, deptId, majorId);
        List<SrsDormitoryStudent> dormitoryStudentList = lambdaQuery().in(SrsDormitoryStudent::getStuNo, nos).list();
        List<DmsChangeLog> changeLogList = new ArrayList<>();
        List<Long> dormIds = new ArrayList<>();
        Map<Long, Integer> map = new HashMap<>();
        for (SrsDormitoryStudent dormitoryStudent : dormitoryStudentList) {
            DmsChangeLog changeLog = new DmsChangeLog();
            changeLog.setStuNo(dormitoryStudent.getStuNo());
            changeLog.setCurrentBedId(dormitoryStudent.getBedId());
            changeLog.setCurrentDormId(dormitoryStudent.getDormitoryId());
            changeLog.setType("退宿");
            changeLog.setApprover(SecurityUtils.getUsername());
            changeLogList.add(changeLog);
            map.merge(dormitoryStudent.getDormitoryId(), 1, Integer::sum);
            dormIds.add(dormitoryStudent.getDormitoryId());
        }
        List<DmsDormitory> list = dmsDormitoryService.lambdaQuery().in(DmsDormitory::getId, dormIds).list();
        for (DmsDormitory dormitory : list) {
            dormitory.setOccupancy(dormitory.getOccupancy() - map.get(dormitory.getId()));
        }
        boolean update = dmsDormitoryService.updateBatchById(list);
        boolean remove = lambdaUpdate().in(SrsDormitoryStudent::getStuNo, nos).remove();
        boolean saveBatch = dmsChangeLogService.saveBatch(changeLogList);
        if (!update) throw new RuntimeException("修改宿舍人数失败");
        if (!remove) throw new RuntimeException("删除学生宿舍关联失败");
        if (!saveBatch) throw new RuntimeException("添加住宿日志失败");
        return AjaxResult.success();
    }

    /**
     * 新生请求分配宿舍
     * @return
     */
    @Transactional
    @Override
    public AjaxResult allocateDormitory() {
        String username = SecurityUtils.getUsername();
        SrsStuReg stuReg = srsStuRegMapper.getOwnInfoByKsh(username);
        try{
            String stuNo = "202301001";
            String idCode = "451102200412131314";
            String strKey = "GLJP";
            String strSysDatetime = DateUtils.getTime();
            String ext = Md5Utils.hash(stuNo + strKey + strSysDatetime );
            String url = "http://xsjf.gxsdxy.cn:8560/Interface/GetStudentChargeItems?verify="
                    +ext+"&strSysDatetime="+strSysDatetime
                    +"&SID="+stuNo+"&IDCode="+idCode;
            url = url.replace(" ","%20");
            HttpClient client= HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(url);
            HttpResponse res = client.execute(httpGet);
            JSONObject jsonObject = JSONObject.parseObject(EntityUtils.toString(res.getEntity()));
            double arrears = Double.parseDouble(jsonObject.getJSONObject("data").get("TotalArrearsAmount").toString());
            if (arrears>0){
                return AjaxResult.error("请先完成缴费");
            }
            Long count = lambdaQuery()
                    .eq(SrsDormitoryStudent::getStuNo, stuNo)
                    .count();
            if (count>0) return AjaxResult.error("您已完成宿舍分配");
            Long dormitoryId = null;
            List<DmsDormitory> hasBedDormitory = dmsDormitoryMapper.getHasBedDormitory(stuReg.getBJDM(),0);
            if (!CollectionUtils.isEmpty(hasBedDormitory)){
                //修改宿舍人数
                for (DmsDormitory dormitory : hasBedDormitory){
                    boolean update = dmsDormitoryService.lambdaUpdate()
                            .eq(DmsDormitory::getId, dormitory.getId())
                            .setSql("occupancy = occupancy + 1")
                            .lt(DmsDormitory::getOccupancy, dormitory.getBedNum())
                            .update();
                    if (update){
                        dormitoryId = dormitory.getId();
                        break;
                    }
                }
            }
            if (dormitoryId == null){
                List<DmsDormitory> hasBedDormitoryIsMixed = dmsDormitoryMapper.getHasBedDormitory(stuReg.getBJDM(), 1);
                if (!CollectionUtils.isEmpty(hasBedDormitoryIsMixed)){
                    //修改宿舍人数
                    for (DmsDormitory dormitory : hasBedDormitoryIsMixed){
                        boolean update = dmsDormitoryService.lambdaUpdate()
                                .eq(DmsDormitory::getId, dormitory.getId())
                                .setSql("occupancy = occupancy + 1")
                                .lt(DmsDormitory::getOccupancy, dormitory.getBedNum())
                                .update();
                        if (update){
                            dormitoryId = dormitory.getId();
                            break;
                        }
                    }
                }
            }
            if (dormitoryId == null) return AjaxResult.error("没有空余宿舍");
            DmsChangeLog changeLog = new DmsChangeLog();
            changeLog.setStuNo(stuReg.getXH());
            changeLog.setCurrentDormId(dormitoryId);
            changeLog.setType("入住");
            boolean saveLog = dmsChangeLogService.save(changeLog);
            if (!saveLog) throw new RuntimeException("操作失败");
            SrsDormitoryStudent dormitoryStudent = new SrsDormitoryStudent();
            dormitoryStudent.setDormitoryId(dormitoryId);
            dormitoryStudent.setStuNo(stuReg.getXH());
            dormitoryStudent.setCheckinTime(LocalDateTime.now());
            boolean save = save(dormitoryStudent);
            if (!save) throw new RuntimeException("操作失败");
            return AjaxResult.success();
        }catch(Exception e){
            throw new RuntimeException("操作失败");
        }
    }

    /**
     * 查询学生宿舍关联表信息
     * @param queryDto
     * @return
     */
    @Override
    public List<Map<String, Object>> getList(DormitoryQueryDto queryDto) {
        List<Map<String, Object>> dormitoryList = baseMapper.getList(queryDto);
        if (CollectionUtils.isEmpty(dormitoryList)){
            return null;
        }
        List<String> stuNoList = dormitoryList.stream().map(item -> item.get("stuNo").toString()).collect(Collectors.toList());
        List<Map<String, Object>> studentList = baseMapper.selectStudentByStuNoList(stuNoList);
        if (studentList.size()<stuNoList.size()){
            List<Map<String, Object>> stuRegList = baseMapper.selectSrsStuRegByStuNoList(stuNoList);
            studentList.addAll(stuRegList);
        }
        Map<Long, Map<String, Object>> studentMap = new HashMap<>();
        studentList.forEach(student -> {
            if (student != null && student.get("dormitoryId") != null) {
                Long dormitoryId = Long.valueOf(student.get("dormitoryId").toString());
                studentMap.put(dormitoryId, student);
                student.remove("dormitoryId");
            }
        });
        dormitoryList.forEach(item -> {
            if (item != null && item.get("checkInTime") != null) {
                item.put("checkInTime", item.get("checkInTime").toString().replace("T", " "));
            }
            if (item != null && item.get("dormitoryId") != null) {
                Long dormitoryId = Long.valueOf(item.get("dormitoryId").toString());
                if (studentMap.containsKey(dormitoryId)) {
                    item.put("student", studentMap.get(dormitoryId));
                }
            }
        });
        return dormitoryList;
    }

    @Override
    public AjaxResult get(Long id) {
        Map<String,Object> result =  baseMapper.selectDetailById(id);
        if (result == null){
            return AjaxResult.error("id不存在");
        }
        if(result.get("checkinTime")!=null){
            result.put("checkinTime",result.get("checkinTime").toString().replace("T"," "));
        }else{
            result.put("checkinTime",null);
        }
        List<String> stuNo = new ArrayList<>();
        stuNo.add(result.get("stuNo").toString());
        List<Map<String, Object>> student = baseMapper.selectStudentByStuNoList(stuNo);
        if (!CollectionUtils.isEmpty(student)){
            result.put("student",student.get(0));
            return AjaxResult.success(result);
        }
        List<Map<String, Object>> stuReg = baseMapper.selectSrsStuRegByStuNoList(stuNo);
        if (!CollectionUtils.isEmpty(stuReg)){
            result.put("student",stuReg.get(0));
            return AjaxResult.success(result);
        }
        return AjaxResult.success(result);
    }

    /**
     * 导入数据
     * @param list
     * @return
     */
    @Override
    @Transactional
    public AjaxResult importData(List<DormitoryImportModel> list) {
        Map<String,Map<Long,DmsDormitory>> mapList = new HashMap<>();
        List<DmsDormitoryBuilding> buildingList = buildingMapper.selectBuildingNameAndParkName();
        buildingList.forEach(building -> {
            List<DmsDormitory> dmsDormitories = dmsDormitoryMapper.selectAllByBuildingId(building.getId());
            Map<Long,DmsDormitory> map = new HashMap<>();
            dmsDormitories.forEach(dor -> {
                map.put(dor.getRoomNo(),dor);
            });
            mapList.put(building.getName(),map);
        });
        List<SrsDormitoryStudent> dormitoryStudentList = new ArrayList<>();
        String stuNo = null;
        for (DormitoryImportModel dormitoryImportModel : list) {
            stuNo = dormitoryImportModel.getStuNo();
            try{
                int f = 0;
                if (!StringUtils.isEmpty(dormitoryImportModel.getRoomNo2()) && dormitoryImportModel.getRoomNo2().length() <= 7 && dormitoryImportModel.getRoomNo2().length() >= 6) {
                    f = 2;
                    dormitoryImportModel.setRoomNo2(dormitoryImportModel.getRoomNo2().replaceAll("\\\\s*|\\r|\\n|\\t", ""));
                } else if (!StringUtils.isEmpty(dormitoryImportModel.getRoomNo2()) && dormitoryImportModel.getRoomNo1().length() <= 7 && dormitoryImportModel.getRoomNo1().length() >= 6) {
                    f = 1;
                    dormitoryImportModel.setRoomNo1(dormitoryImportModel.getRoomNo1().replaceAll("\\\\s*|\\r|\\n|\\t", ""));
                } else {
                    continue;
                }
                SrsDormitoryStudent dormitoryStudent = new SrsDormitoryStudent();
                dormitoryStudent.setStuNo(dormitoryImportModel.getStuNo());
                dormitoryStudent.setIsDormitoryHead(dormitoryImportModel.getIsManager().equals("是") ? 1 : 0);
                dormitoryStudent.setCheckinTime(LocalDateTime.now());
                String buildingAndParkName = "";
                String roomNo = "";

                if (f == 2) {
                    buildingAndParkName = dormitoryImportModel.getRoomNo2().substring(0, dormitoryImportModel.getRoomNo2().length() - 3);
                    roomNo = dormitoryImportModel.getRoomNo2().substring(dormitoryImportModel.getRoomNo2().length() - 3);
                } else {
                    buildingAndParkName = dormitoryImportModel.getRoomNo1().substring(0, dormitoryImportModel.getRoomNo1().length() - 3);
                    roomNo = dormitoryImportModel.getRoomNo1().substring(dormitoryImportModel.getRoomNo1().length() - 3);
                }
                String[] Number = {"一","二","三","四","五","六","七","八","九"};
                for (int i = 0; i < Number.length; i++) {
                    if (buildingAndParkName.contains(Number[i])){
                        buildingAndParkName = buildingAndParkName.replace(Number[i], (i+1)+"");
                    }
                }
                if (mapList.get(buildingAndParkName).get(Long.valueOf(roomNo)) == null) continue;
                dormitoryStudent.setDormitoryId(mapList.get(buildingAndParkName).get(Long.valueOf(roomNo)).getId());
                mapList.get(buildingAndParkName).get(Long.valueOf(roomNo)).setOccupancy(mapList.get(buildingAndParkName).get(Long.valueOf(roomNo)).getOccupancy() + 1);
                dormitoryStudentList.add(dormitoryStudent);
            }catch (Exception e){
                e.printStackTrace();
                throw new RuntimeException("学号为："+stuNo+"的数据错误");
            }
        }
        boolean saveDormitoryStudent = dormitoryStudentService.saveBatch(dormitoryStudentList);
        if (!saveDormitoryStudent) throw new RuntimeException("添加住宿数据失败");
        List<DmsDormitory> dormitoryList = new ArrayList<>();
        mapList.forEach((k,v) -> {
            v.forEach((k2,v2) -> {
                dormitoryList.add(v2);
            });
        });
        boolean b = dmsDormitoryService.updateBatchById(dormitoryList);
        if (!b) throw new RuntimeException("修改宿舍人数失败");
        return AjaxResult.success();
    }

    @Override
    public List<DomInfo> doExport(DmsSearch param){
        return _dormStuMapper.doExport(param);
    }
    @Override
    public boolean updateSrsDormitoryStudent(SrsDormitoryStudent dormitoryStudent){
        return  _dormStuMapper.updateSrsDormitoryStudent(dormitoryStudent);
    }
    @Override
    public  AjaxResult rankingCount(){
        return AjaxResult.success(_dormStuMapper.rankingCount());
    }

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 根据教师工号分配宿舍（按吸烟和早睡习惯分配）
     *
     * @param teacherEmployeeId 教师工号
     * @return 分配结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult assignDormitoryByTeacher(String teacherEmployeeId) {
        try {
            List<SrsStuReg> stuList = srsDormitoryStudentMapper.listSmokeEarly(teacherEmployeeId);

            List<String> kshList = stuList.stream().map(SrsStuReg::getKSH).collect(Collectors.toList());

            QueryWrapper<DmsNewReg>  queryWrapper = new QueryWrapper<>();
            queryWrapper.in("ksh",kshList);
            _newRegMapper.delete(queryWrapper);

            List<DmsDormitoryClass> dormList = srsDormitoryStudentMapper.listFdyCanDorm(teacherEmployeeId);

            // 查询所有已分配的ksh，避免重复插入
            Set<String> assignedKshSet = new HashSet<>();
            List<String> assignedKshList = _newRegMapper.selectAllKsh();
            assignedKshSet.addAll(assignedKshList);

            // 查询数据库中每个宿舍已分配人数
            Map<Long, Integer> dormUsed = new HashMap<>();
            List<Map<String, Object>> usedList = jdbcTemplate.queryForList(
                    "SELECT dormitory_id, COUNT(*) AS cnt FROM dms_new_reg WHERE del_flag = '0' GROUP BY dormitory_id"
            );
            for (Map<String, Object> row : usedList) {
                dormUsed.put(((Number)row.get("dormitory_id")).longValue(), ((Number)row.get("cnt")).intValue());
            }
            for (DmsDormitoryClass dorm : dormList) {
                dormUsed.putIfAbsent(dorm.getDormitoryId(), 0);
            }

            // 1. 按班级分组
            Map<String, List<SrsStuReg>> classMap = new LinkedHashMap<>();
            for (SrsStuReg stu : stuList) {
                classMap.computeIfAbsent(stu.getBJDM(), k -> new ArrayList<>()).add(stu);
            }

            // 2. 按性别分组宿舍
            Map<String, List<DmsDormitoryClass>> dormGroupMap = new LinkedHashMap<>();
            for (DmsDormitoryClass dorm : dormList) {
                String key = dorm.getGender();
                dormGroupMap.computeIfAbsent(key, k -> new ArrayList<>()).add(dorm);
            }

            // 3. 统计每个宿舍已分配班级
            Map<Long, String> dormClass = new HashMap<>(); // 宿舍已分配的班级
            for (DmsDormitoryClass dorm : dormList) {
                dormClass.put(dorm.getDormitoryId(), null); // 初始无班级
            }

            int successCount = 0;
            int failureCount = 0;
            List<String> errorMessages = new ArrayList<>();

            // 4. 班级顺序分配
            for (Map.Entry<String, List<SrsStuReg>> classEntry : classMap.entrySet()) {
                String bjdm = classEntry.getKey();
                List<SrsStuReg> classStuList = classEntry.getValue();
                // 4.1 班内按性别分组
                Map<String, List<SrsStuReg>> genderMap = classStuList.stream()
                        .collect(Collectors.groupingBy(SrsStuReg::getXB, LinkedHashMap::new, Collectors.toList()));
                for (Map.Entry<String, List<SrsStuReg>> genderEntry : genderMap.entrySet()) {
                    String gender = genderEntry.getKey();
                    List<SrsStuReg> genderStuList = genderEntry.getValue();
                    // 4.2 班内同一性别再按吸烟/早睡分组
                    Map<String, List<SrsStuReg>> habitMap = new LinkedHashMap<>();
                    for (SrsStuReg stu : genderStuList) {
                        String key = stu.getIsSmoke() + "_" + stu.getIsEarly();
                        habitMap.computeIfAbsent(key, k -> new ArrayList<>()).add(stu);
                    }
                    List<DmsDormitoryClass> candidateDorms = dormGroupMap.getOrDefault(gender, new ArrayList<>());
                    int dormIdx = 0;
                    for (Map.Entry<String, List<SrsStuReg>> habitEntry : habitMap.entrySet()) {
                        List<SrsStuReg> habitStuList = habitEntry.getValue();
                        for (SrsStuReg stu : habitStuList) {
                            if (assignedKshSet.contains(stu.getKSH())) {
                                // 已分配，跳过
                                continue;
                            }
                            boolean assigned = false;
                            for (int i = dormIdx; i < candidateDorms.size(); i++) {
                                DmsDormitoryClass dorm = candidateDorms.get(i);
                                int used = dormUsed.getOrDefault(dorm.getDormitoryId(), 0);
                                String assignedClass = dormClass.get(dorm.getDormitoryId());
                                // 只允许同班入住
                                if ((assignedClass == null || assignedClass.equals(bjdm)) && used < dorm.getBedCount()) {
                                    // 插入dms_new_reg
                                    DmsNewReg reg = new DmsNewReg();
                                    reg.setDormitoryId(dorm.getDormitoryId());
                                    reg.setKsh(stu.getKSH());
                                    reg.setDelFlag("0");
                                    _newRegMapper.insert(reg);
                                    dormUsed.put(dorm.getDormitoryId(), used + 1);
                                    dormClass.put(dorm.getDormitoryId(), bjdm); // 标记该宿舍已分配给该班
                                    assignedKshSet.add(stu.getKSH());
                                    assigned = true;
                                    successCount++;
                                    break;
                                }
                            }
                            if (!assigned) {
                                failureCount++;
                                errorMessages.add("学生" + stu.getKSH() + "分配失败：无可用床位");
                            }
                        }
                    }
                }
            }

            Map<String, Object> result = new HashMap<>();
            result.put("successCount", successCount);
            result.put("failureCount", failureCount);
            result.put("errorMessages", errorMessages);
            if (successCount > 0) {
                return AjaxResult.success("分配完成", result);
            } else {
                return AjaxResult.error("分配失败", result);
            }
        } catch (Exception e) {
            return AjaxResult.error("分配过程中发生错误: " + e.getMessage());
        }
    }

}
