package com.srs.dormitory.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
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.WeChatUtil;
import com.srs.comprehensive.domain.CphMsg;
import com.srs.comprehensive.domain.ViewStuInfo;
import com.srs.comprehensive.mapper.CphMsgMapper;
import com.srs.comprehensive.mapper.ViewStuInfoMapper;
import com.srs.comprehensive.service.impl.CphMsgServiceImpl;
import com.srs.dormitory.domain.DmsStuDaily;
import com.srs.dormitory.domain.Dto.SetNeedCardDto;
import com.srs.dormitory.domain.SrsDormitoryStudent;
import com.srs.dormitory.mapper.DmsStuDailyMapper;
import com.srs.dormitory.mapper.SrsDormitoryStudentMapper;
import com.srs.system.mapper.SysUserMapper;
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.DmsNeedCardStuMapper;
import com.srs.dormitory.domain.DmsNeedCardStu;
import com.srs.dormitory.service.IDmsNeedCardStuService;
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;
import static com.srs.common.utils.SecurityUtils.getUserId;
import static com.srs.common.utils.SecurityUtils.getUsername;

/**
 * 打卡设置Service业务层处理
 *
 * @author srs
 * @date 2025-07-08
 */
@Service
public class DmsNeedCardStuServiceImpl extends ServiceImpl<DmsNeedCardStuMapper,DmsNeedCardStu> implements IDmsNeedCardStuService {
    @Autowired
    private DmsNeedCardStuMapper dmsNeedCardStuMapper;

    @Autowired
    private ViewStuInfoMapper viewStuInfoMapper;

    @Autowired
    private DmsStuDailyMapper dmsStuDailyMapper;

    @Autowired
    private SrsDormitoryStudentMapper srsDormitoryStudentMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private CphMsgServiceImpl cphMsgService;

    @Autowired
    public WeChatUtil weChatUtil;


    @Autowired
    public PlatformTransactionManager transactionManager;

    @Override
    public void autoSetDailyCheckTask(){
        dmsNeedCardStuMapper.callAutoSetDailyCheckTask();
        DmsNeedCardStu param = new DmsNeedCardStu();
        param.setNeedDate(getNowDate());
        List<DmsNeedCardStu> list = dmsNeedCardStuMapper.listView(param);
        if(list.isEmpty()){
            System.out.println("系统设置打卡：今天没有需要打卡的学生");
            return;
        }
        String msg = "您今天需要宿舍打卡，记得前往学工系统手机端打卡。";
        List<String> stuNos = list.stream().map(DmsNeedCardStu::getStuNo).collect(Collectors.toList());
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("user_name",stuNos);
        List<SysUser> userList = sysUserMapper.selectList(queryWrapper);
        if(userList.isEmpty()){
            System.out.println("系统设置打卡：未找到需要打卡的学生信息");
            return;
        }
        List<Long> userIds = userList.stream().map(SysUser::getUserId).collect(Collectors.toList());
        List<CphMsg> msgList = new ArrayList<>();
        for(Long userId : userIds){
            CphMsg cphMsg = new CphMsg();
            cphMsg.setSender(1L);
            cphMsg.setReceiver(userId);
            cphMsg.setContent(msg);
            cphMsg.setCreateBy("admin");
            cphMsg.setCreateTime(getNowDate());
            msgList.add(cphMsg);
        }

        boolean res = cphMsgService.saveBatch(msgList);
        if(!res){
            System.out.println("发送消息失败");
            return;
        }
        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, msg);
        }

    }


    @Override
    public AjaxResult sendTodayNeedCardMsg(){
        TransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(def);
        try{

            DmsNeedCardStu param = new DmsNeedCardStu();
            param.setFdyNo(getUsername());
            param.setNeedDate(getNowDate());
            List<DmsNeedCardStu> list = dmsNeedCardStuMapper.listView(param);
            if(list.isEmpty()){
                throw new Exception("今天没有需要打卡的学生");
            }

            String msg = "您今天需要宿舍打卡，记得前往学工系统手机端打卡。";
            List<String> stuNos = list.stream().map(DmsNeedCardStu::getStuNo).collect(Collectors.toList());
            QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("user_name",stuNos);
            List<SysUser> userList = sysUserMapper.selectList(queryWrapper);
            if(userList.isEmpty()){
                throw new Exception("未找到需要打卡的学生信息");
            }
            List<Long> userIds = userList.stream().map(SysUser::getUserId).collect(Collectors.toList());
            List<CphMsg> msgList = new ArrayList<>();
            for(Long userId : userIds){
                CphMsg cphMsg = new CphMsg();
                cphMsg.setSender(getUserId());
                cphMsg.setReceiver(userId);
                cphMsg.setContent(msg);
                cphMsg.setCreateBy(getUsername());
                cphMsg.setCreateTime(getNowDate());
                msgList.add(cphMsg);
            }

            boolean res = cphMsgService.saveBatch(msgList);
            if(!res){
                throw new Exception("发送消息失败");
            }

            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, msg);
            }


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

    @Override
    public AjaxResult setNeedCardByClass(SetNeedCardDto param) {
        // 参数校验
        if (CollectionUtils.isEmpty(param.getClassIds()) || CollectionUtils.isEmpty(param.getNeedDates())) {
            return AjaxResult.error("班级ID或需要打卡的日期不能为空");
        }

        try {
            // 1. 查询班级学生
            List<ViewStuInfo> students = viewStuInfoMapper.selectList(new QueryWrapper<ViewStuInfo>()
                    .eq("t_no", getUsername())
                    .in("class_id", param.getClassIds()));

            if (students.isEmpty()) {
                return AjaxResult.error("未找到该班级的学生");
            }

            List<String> studentNos = students.stream()
                    .map(ViewStuInfo::getStuNo)
                    .collect(Collectors.toList());

            // 2. 查询学生宿舍信息
            List<SrsDormitoryStudent> dormitoryStudents = srsDormitoryStudentMapper.selectList(
                    new QueryWrapper<SrsDormitoryStudent>().in("stu_no", studentNos));

            if (dormitoryStudents.isEmpty()) {
                return AjaxResult.error("未找到该班级的学生宿舍信息");
            }

            List<String> validStudentNos = dormitoryStudents.stream()
                    .map(SrsDormitoryStudent::getStuNo)
                    .collect(Collectors.toList());

            // 3. 批量查询已存在的打卡记录
            Set<String> existingKeys = new HashSet<>();
            if (!validStudentNos.isEmpty() && !param.getNeedDates().isEmpty()) {
                List<DmsNeedCardStu> existingRecords = dmsNeedCardStuMapper.selectList(
                        new QueryWrapper<DmsNeedCardStu>()
                                .in("stu_no", validStudentNos)
                                .in("need_date", param.getNeedDates()));

                existingKeys = existingRecords.stream()
                        .map(record -> record.getStuNo() + "_" + record.getNeedDate())
                        .collect(Collectors.toSet());
            }

            // 4. 准备需要插入的数据
            List<DmsNeedCardStu> needInsertList = new ArrayList<>();
            String currentUser = getUsername();
            Date currentTime = getNowDate();

            for (String stuNo : validStudentNos) {
                for (Date needDate : param.getNeedDates()) {
                    String key = stuNo + "_" + needDate;
                    if (!existingKeys.contains(key)) {
                        DmsNeedCardStu record = new DmsNeedCardStu();
                        record.setStuNo(stuNo);
                        record.setNeedDate(needDate);
                        record.setCreateBy(currentUser);
                        record.setCreateTime(currentTime);
                        needInsertList.add(record);
                    }
                }
            }

            // 5. 批量插入
            if (!needInsertList.isEmpty()) {
                boolean res = this.saveBatch(needInsertList);
                if (!res) {
                    return AjaxResult.error("插入记录失败");
                }
            }

            return AjaxResult.success();

        } catch (Exception ex) {
            log.error("设置班级打卡信息失败", ex);
            return AjaxResult.error("系统内部错误，请稍后重试");
        }
    }

    @Override
    public AjaxResult cardNeedCard(Long id){
        try{

            DmsNeedCardStu find = dmsNeedCardStuMapper.selectById(id);
            if(find == null){
                throw new Exception("未找到需要打卡的学生");
            }

            QueryWrapper<ViewStuInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("stu_no", find.getStuNo());
            ViewStuInfo viewStuInfo = viewStuInfoMapper.selectOne(wrapper);
            if(viewStuInfo == null){
                throw new Exception("未找到学生信息");
            }
            if(!Objects.equals(viewStuInfo.getTNo(), getUsername())){
                throw new Exception("不是您的学生");
            }
            QueryWrapper<SrsDormitoryStudent> wrapper2 = new QueryWrapper<>();
            wrapper2.eq("stu_no", find.getStuNo());
            SrsDormitoryStudent srsDormitoryStudent = srsDormitoryStudentMapper.selectOne(wrapper2);
            if(srsDormitoryStudent == null){
                throw new Exception("未找到学生宿舍信息");
            }

            QueryWrapper<DmsStuDaily> wrapper3 = new QueryWrapper<>();
            wrapper3.eq("stu_no", find.getStuNo())
                    .apply("DATE(submit_time) = DATE({0})", find.getNeedDate())
                    .last("limit 1");
            DmsStuDaily dmsStuDaily = dmsStuDailyMapper.selectOne(wrapper3);
            if(dmsStuDaily != null){
                throw new Exception("该生已打卡");
            }

            DmsStuDaily dmsStuDaily2 = new DmsStuDaily();
            dmsStuDaily2.setStuNo(find.getStuNo());
            dmsStuDaily2.setSubmitTime(find.getNeedDate());
            dmsStuDaily2.dormitoryId = srsDormitoryStudent.getDormitoryId();
            dmsStuDaily2.remark = "辅导员帮忙打卡";
            int res =  dmsStuDailyMapper.insert(dmsStuDaily2);
            if(res == 0){
                throw new Exception("帮忙打卡失败");
            }

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

    @Override
    public AjaxResult cancelNeedCard(Long id){
        try{
            DmsNeedCardStu find = dmsNeedCardStuMapper.selectById(id);
            if(find == null){
                throw new Exception("未找到需要取消的打卡设置");
            }

            QueryWrapper<ViewStuInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("stu_no", find.getStuNo());
            ViewStuInfo viewStuInfo = viewStuInfoMapper.selectOne(wrapper);
            if(viewStuInfo == null){
                throw new Exception("未找到学生信息");
            }
            if(!Objects.equals(viewStuInfo.getTNo(), getUsername())){
                throw new Exception("不是您的学生");
            }

            int res = dmsNeedCardStuMapper.deleteById(id);
            if(res == 0){
                throw new Exception("取消失败");
            }

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

    @Override
    public List<DmsNeedCardStu> listView(DmsNeedCardStu params){
        return dmsNeedCardStuMapper.listView(params);
    }

    /**
     * 查询打卡设置
     *
     * @param id 打卡设置主键
     * @return 打卡设置
     */
    @Override
    public DmsNeedCardStu selectDmsNeedCardStuById(Long id) {
        return dmsNeedCardStuMapper.selectDmsNeedCardStuById(id);
    }

    /**
     * 查询打卡设置列表
     *
     * @param dmsNeedCardStu 打卡设置
     * @return 打卡设置
     */
    @Override
    public List<DmsNeedCardStu> selectDmsNeedCardStuList(DmsNeedCardStu dmsNeedCardStu) {
        return dmsNeedCardStuMapper.selectDmsNeedCardStuList(dmsNeedCardStu);
    }

    /**
     * 新增打卡设置
     *
     * @param dmsNeedCardStu 打卡设置
     * @return 结果
     */
    @Override
    public int insertDmsNeedCardStu(DmsNeedCardStu dmsNeedCardStu) {
                dmsNeedCardStu.setCreateTime(getNowDate());
            return dmsNeedCardStuMapper.insertDmsNeedCardStu(dmsNeedCardStu);
    }

    /**
     * 修改打卡设置
     *
     * @param dmsNeedCardStu 打卡设置
     * @return 结果
     */
    @Override
    public int updateDmsNeedCardStu(DmsNeedCardStu dmsNeedCardStu) {
                dmsNeedCardStu.setUpdateTime(getNowDate());
        return dmsNeedCardStuMapper.updateDmsNeedCardStu(dmsNeedCardStu);
    }

    /**
     * 批量删除打卡设置
     *
     * @param ids 需要删除的打卡设置主键
     * @return 结果
     */
    @Override
    public int deleteDmsNeedCardStuByIds(Long[] ids) {
        return dmsNeedCardStuMapper.deleteDmsNeedCardStuByIds(ids);
    }

    /**
     * 删除打卡设置信息
     *
     * @param id 打卡设置主键
     * @return 结果
     */
    @Override
    public int deleteDmsNeedCardStuById(Long id) {
        return dmsNeedCardStuMapper.deleteDmsNeedCardStuById(id);
    }
}
