package com.srs.dormitory.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.Query;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.srs.common.core.domain.AjaxResult;
import com.srs.common.utils.WeChatUtil;
import com.srs.comprehensive.domain.SrsStuYear;
import com.srs.comprehensive.domain.SrsStudent;
import com.srs.comprehensive.domain.CphMsg;
import com.srs.comprehensive.mapper.SrsStuYearMapper;
import com.srs.comprehensive.mapper.SrsStudentMapper;
import com.srs.comprehensive.mapper.CphMsgMapper;
import com.srs.dormitory.domain.DmsNewRange;
import com.srs.dormitory.domain.Dto.DmsSearch;
import com.srs.dormitory.domain.Vo.DomInfo;
import com.srs.dormitory.mapper.DmsNewRangeMapper;
import com.srs.dormitory.mapper.SrsDormitoryStudentMapper;
import liquibase.pro.packaged.A;
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.DmsNewRecordMapper;
import com.srs.dormitory.domain.DmsNewRecord;
import com.srs.dormitory.service.IDmsNewRecordService;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.bind.annotation.PathVariable;

import static com.srs.common.utils.SecurityUtils.getUsername;

/**
 * 住宿记录Service业务层处理
 *
 * @author srs
 * @date 2024-03-15
 */
@Service
public class DmsNewRecordServiceImpl extends ServiceImpl<DmsNewRecordMapper,DmsNewRecord> implements IDmsNewRecordService {
    @Autowired
    private DmsNewRecordMapper dmsNewRecordMapper;
    @Autowired
    public SrsDormitoryStudentMapper _srsDormStuMapper;
    @Autowired
    public DmsNewRangeMapper _rangeMapper;
    @Autowired
    public SrsStuYearMapper _yearMapper;
    @Autowired
    public SrsStudentMapper _stuMapper;

    @Autowired
    public WeChatUtil weChatUtil;

    @Autowired
    private CphMsgMapper cphMsgMapper;

    @Autowired
    public PlatformTransactionManager transactionManager;

    @Override
    public AjaxResult initRecord(DmsSearch param){
        TransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(def);
        try{
            List<DmsNewRecord> needInsertList = new ArrayList<>();

            List<DomInfo> findList = _srsDormStuMapper.findByParam(param);

            List<String> stuNoList = new ArrayList<>();
            for(DomInfo domInfo : findList){
                stuNoList.add(domInfo.stuNo);
            }
            Set<String> stuNoSet = new HashSet<>(stuNoList);
            if(stuNoSet.size() == 0){
                throw new Exception("您选择的年级没有学生正在住宿");
            }

            QueryWrapper<DmsNewRecord> recordQuery = new QueryWrapper<>();
            recordQuery.in("stu_no",stuNoSet)
                    .eq("range_code",param.rangeCode);
            List<DmsNewRecord> existRecordList = dmsNewRecordMapper.selectList(recordQuery);

            QueryWrapper<DmsNewRange> rangeQuery = new QueryWrapper<>();
            rangeQuery.eq("range_code",param.rangeCode)
                    .last("limit 1");

            DmsNewRange range = _rangeMapper.selectOne(rangeQuery);
            if(range == null){
                throw new Exception("该区间不存在");
            }
            QueryWrapper<SrsStuYear> yearQuery = new QueryWrapper<>();
            yearQuery.eq("xndm",range.getXndm())
                    .last("limit 1");
            SrsStuYear year = _yearMapper.selectOne(yearQuery);
            if(year == null){
                throw new Exception("该区间学年不存在");
            }
            Long stuYearId = year.getId();

            Date startDate = range.getStartDate();
            Date endDate = range.getEndDate();

            Calendar endTime = Calendar.getInstance();
            Calendar startTime = Calendar.getInstance();
            startTime.setTime(startDate);
            endTime.setTime(endDate);

            int i1 = startTime.get(Calendar.DAY_OF_MONTH);
            int i2 = endTime.get(Calendar.DAY_OF_MONTH);
            double month = 0.5;
            if (i2 >= 15 && i1 <= 15) month = 1;
            int yearDiff = endTime.get(Calendar.YEAR) - startTime.get(Calendar.YEAR);
            int monthDiff = endTime.get(Calendar.MONTH) - startTime.get(Calendar.MONTH);
            double totalMonthDiff = yearDiff * 12 + monthDiff + month;

            for (DomInfo domInfo:findList ) {
                List<DmsNewRecord> list = existRecordList.stream().filter(x-> Objects.equals(x.getStuNo(), domInfo.stuNo)).collect(Collectors.toList());
                if(list.size() == 0){
                    if (domInfo.getChargeStandard() == null){
                        domInfo.setChargeStandard(new BigDecimal("0"));
                    }
                    if(domInfo.bankCard == null || domInfo.bankCard.equals("")){
                        domInfo.bankCard = "无";
                    }
                    if(domInfo.stuPhone == null || domInfo.stuPhone.equals("")){
                        domInfo.stuPhone = "无";
                    }
                    DmsNewRecord record = new DmsNewRecord();
                    record.setApplyStatus("6");
                    record.setStuNo(domInfo.stuNo);
                    record.setRoomId(domInfo.dormitoryId);
                    record.setIsHead(domInfo.isDormitoryHead);
                    record.setStartDate(startDate);
                    record.setEndDate(endDate);
                    record.setInMonth(new BigDecimal(totalMonthDiff));
                    record.setMainMoney(domInfo.chargeStandard);
                    record.setNeedMoney(new BigDecimal(totalMonthDiff).multiply(domInfo.getChargeStandard().divide(new BigDecimal("10"), 2, RoundingMode.HALF_UP)));
                    record.setBankCard(domInfo.bankCard);
                    record.setStuYearId(stuYearId);
                    record.setStuPhone(domInfo.stuPhone);
                    record.setRangeCode(param.rangeCode);
                    needInsertList.add(record);
                }
            }

            if(needInsertList.size() != 0){
                boolean res = this.saveBatch(needInsertList);
                if(!res){
                    throw new Exception("插入记录失败");
                }
            }

            // 发送住宿费用确认消息
            try {
                String messageContent = "请前往电脑端学工系统-宿舍管理-住宿费用-学生住宿，进行宿舍费用确认，如不进行手动确认，系统将会在一周后自动确认！";

                // 构建年级ID列表
                List<String> gradeIds = new ArrayList<>();
                gradeIds.add(String.valueOf(param.gradeId));

                // 发送企业微信消息
                List<String> studentNos = dmsNewRecordMapper.selectStudentNosByGrades(gradeIds);
                if (studentNos != null && !studentNos.isEmpty()) {
                    sendWechatMessage(studentNos, messageContent);
                }

                // 发送系统消息
                List<Long> studentIds = dmsNewRecordMapper.selectStudentIdsByGrades(gradeIds);
                if (studentIds != null && !studentIds.isEmpty()) {
                    sendSystemMessage(studentIds, messageContent);
                }
            } catch (Exception e) {
                // 消息发送失败不影响主流程，只记录日志
                System.err.println("发送住宿费用确认消息失败: " + e.getMessage());
            }

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


    @Override
    public AjaxResult oneConfirm(Long id){
        try{
            DmsNewRecord record = dmsNewRecordMapper.selectDmsNewRecordById(id);
            if(record == null){
                throw new Exception("该记录不存在");
            }
            record.setApplyStatus("0");

            int res = dmsNewRecordMapper.updateById(record);
            if(res== 0){
                throw new Exception("更新状态失败");
            }

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

    @Override
    public AjaxResult fdyManyConfirm(List<Long> ids){
        try{

            QueryWrapper<DmsNewRecord> query = new QueryWrapper<>();
            query.in("id",ids)
                    .eq("apply_status",1);
            List<DmsNewRecord> list = dmsNewRecordMapper.selectList(query);
            if(list.size() == 0){
                throw new Exception("您选择的记录并不需要您确认");
            }

            list.forEach(x->{
                x.setApplyStatus("2");
            });

            boolean res = this.updateBatchById(list);
            if(!res){
                throw new Exception("更新记录状态失败");
            }

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


    @Override
    public AjaxResult fullInfo(Long id){
        try{
            DmsNewRecord record = dmsNewRecordMapper.selectDmsNewRecordById(id);
            String stuNo = record.getStuNo();

            if(!Objects.equals(stuNo, getUsername())){
                throw new Exception("不是本人");
            }

            SrsStudent stu = _stuMapper.selectSrsStudentByStuNo(stuNo);
            if(stu == null){
                throw new Exception("学生学号不存在");
            }

            if(stu.xhk == null || stu.xhk.equals("") || Objects.equals(stu.getPhone(), "") || stu.getPhone() == null){
                throw new Exception("请完善个人信息");
            }

            record.setBankCard(stu.xhk);
            record.setStuPhone(stu.getPhone());
            int res = dmsNewRecordMapper.updateById(record);
            if(res == 0){
                throw new Exception("更新失败");
            }

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


    @Override
    public AjaxResult fastConfirm(){
        try{
            int res = dmsNewRecordMapper.fastConfirm();
            if(res == 0){
                throw new Exception("无记录更新");
            }

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

    @Override
    public AjaxResult confirmUnconfirmedStudents(){
        try{
            int res = dmsNewRecordMapper.confirmUnconfirmedStudents();
            if(res == 0){
                throw new Exception("无未确认的学生记录");
            }

            return AjaxResult.success("成功确认 " + res + " 条学生记录");
        }catch(Exception ex){
            return AjaxResult.error(ex.getMessage());
        }
    }


    @Override
    public AjaxResult fdyConfirm(Long id){
        try{
            DmsNewRecord record = dmsNewRecordMapper.selectDmsNewRecordById(id);
            if(record == null){
                throw new Exception("该记录不存在");
            }

            if(!Objects.equals(record.getApplyStatus(), "1")){
                throw new Exception("该记录您已确认");
            }

            record.setApplyStatus("2");

            int res = dmsNewRecordMapper.updateById(record);
            if(res== 0){
                throw new Exception("更新状态失败");
            }

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

    @Override
    public AjaxResult jwcConfirm(Long id){
        try{
            DmsNewRecord record = dmsNewRecordMapper.selectDmsNewRecordById(id);
            if(record == null){
                throw new Exception("该记录不存在");
            }

            if(!Objects.equals(record.getApplyStatus(), "2")){
                throw new Exception("该记录不需要您确认");
            }

            record.setApplyStatus("3");

            int res = dmsNewRecordMapper.updateById(record);
            if(res== 0){
                throw new Exception("更新状态失败");
            }

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


    @Override
    public AjaxResult stuConfirm(Long id){
        try{
            DmsNewRecord record = dmsNewRecordMapper.selectDmsNewRecordById(id);
            if(record == null){
                throw new Exception("该记录不存在");
            }

            if(!Objects.equals(record.getStuNo(), getUsername())){
                throw new Exception("你是谁?");
            }

            record.setApplyStatus("1");

            int res = dmsNewRecordMapper.updateById(record);
            if(res== 0){
                throw new Exception("更新状态失败");
            }

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


    @Override
    public AjaxResult sendConfirm(DmsSearch param){
        TransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(def);
        try{
            List<DmsNewRecord> needUpdateList = dmsNewRecordMapper.findByParam(param);
            needUpdateList.forEach(x->{
                x.setApplyStatus("0");
            });

            boolean res = this.updateBatchById(needUpdateList);
            if(!res){
                throw new Exception("更新状态失败");
            }

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


    @Override
    public AjaxResult exportJwc(DmsSearch param){
        List<DomInfo> list = dmsNewRecordMapper.listView(param);
        return AjaxResult.success(list);
    }



    /**
     * 查询住宿记录
     *
     * @param id 住宿记录主键
     * @return 住宿记录
     */
    @Override
    public DmsNewRecord selectDmsNewRecordById(Long id) {
        return dmsNewRecordMapper.selectDmsNewRecordById(id);
    }

    /**
     * 查询住宿记录列表
     *
     * @param dmsNewRecord 住宿记录
     * @return 住宿记录
     */
    @Override
    public List<DmsNewRecord> selectDmsNewRecordList(DmsNewRecord dmsNewRecord) {
        return dmsNewRecordMapper.selectDmsNewRecordList(dmsNewRecord);
    }

    /**
     * 新增住宿记录
     *
     * @param dmsNewRecord 住宿记录
     * @return 结果
     */
    @Override
    public int insertDmsNewRecord(DmsNewRecord dmsNewRecord) {
        return dmsNewRecordMapper.insertDmsNewRecord(dmsNewRecord);
    }

    /**
     * 修改住宿记录
     *
     * @param dmsNewRecord 住宿记录
     * @return 结果
     */
    @Override
    public int updateDmsNewRecord(DmsNewRecord dmsNewRecord) {
        return dmsNewRecordMapper.updateDmsNewRecord(dmsNewRecord);
    }

    /**
     * 批量删除住宿记录
     *
     * @param ids 需要删除的住宿记录主键
     * @return 结果
     */
    @Override
    public int deleteDmsNewRecordByIds(Long[] ids) {
        return dmsNewRecordMapper.deleteDmsNewRecordByIds(ids);
    }

    /**
     * 删除住宿记录信息
     *
     * @param id 住宿记录主键
     * @return 结果
     */
    @Override
    public int deleteDmsNewRecordById(Long id) {
        return dmsNewRecordMapper.deleteDmsNewRecordById(id);
    }

    /**
     * 发送系统消息
     *
     * @param userIdList 用户ID列表
     * @param content 消息内容
     */
    @Override
    public void sendSystemMessage(List<Long> userIdList, String content) {
        if (userIdList == null || userIdList.isEmpty()) {
            return;
        }

        try {
            List<CphMsg> messages = new ArrayList<>();
            Date now = new Date();
            String currentUser = getUsername();

            for (Long userId : userIdList) {
                CphMsg msg = new CphMsg();
                msg.setSender(1L); // 系统发送者ID
                msg.setReceiver(userId);
                msg.setContent(content);
                msg.setCreateBy(currentUser);
                msg.setCreateTime(now);
                msg.setUpdateBy(currentUser);
                msg.setUpdateTime(now);
                messages.add(msg);
            }

            // 使用批量插入提高性能
            dmsNewRecordMapper.batchInsertCphMsg(messages);
        } catch (Exception e) {
            // 记录日志但不影响主流程
            System.err.println("发送系统消息失败: " + e.getMessage());
        }
    }

    /**
     * 发送企业微信消息
     *
     * @param stuNoList 学生学号列表
     * @param content 消息内容
     */
    @Override
    public void sendWechatMessage(List<String> stuNoList, String content) {
        if (stuNoList == null || stuNoList.isEmpty()) {
            return;
        }

        try {
            // 企业微信批量发送限制，每次最多发送1000个用户
            int batchSize = 1000;

            for (int i = 0; i < stuNoList.size(); i += batchSize) {
                List<String> batch = stuNoList.subList(i, Math.min(i + batchSize, stuNoList.size()));
                // 拼接成"2023001|2023002|2023003"格式
                String toUser = String.join("|", batch);
                // 调用企业微信发送消息方法
                // TODO: 发送消息
                 //weChatUtil.sendTextMessage(toUser, content);
               // System.out.println("企业微信消息发送到: " + toUser + ", 内容: " + content);
            }
        } catch (Exception e) {
            System.err.println("发送企业微信消息失败: " + e.getMessage());
        }
    }
}
