package com.srs.flowable.listener.disbasic;

import com.srs.common.core.domain.entity.SysUser;
import com.srs.common.doman.vo.TeacherVo;

import com.srs.common.utils.DateUtils;
import com.srs.common.utils.SecurityUtils;
import com.srs.common.utils.WeChatUtil;
import com.srs.common.utils.spring.SpringUtils;
import com.srs.flowable.domain.DisBasic;
import com.srs.flowable.domain.NotificationManage;
import com.srs.flowable.mapper.DisBasicMapper;
import com.srs.flowable.mapper.EnlistmentReserveMapper;
import com.srs.flowable.mapper.LeaveMapper;
import com.srs.system.service.ISysUserService;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

@Component("DiscListenerListener")
public class DiscListener implements ExecutionListener {

    @Autowired
    private ISysUserService sysUserService; // 用户服务（查询部门/学院负责人）


    // 用于查询流程定义中的节点信息
    @Autowired
    private RepositoryService repositoryService;

    // 定义日志对象
    private static final Logger log = LoggerFactory.getLogger(DiscListener.class);

    @Override
    public void notify(DelegateExecution execution) {
        // 1. 获取当前节点ID和流程定义ID
        String currentActivityId = execution.getCurrentActivityId(); // 当前节点ID（兼容所有版本）
        String processDefinitionId = execution.getProcessDefinitionId(); // 流程定义ID

        // 2. 根据节点ID查询节点名称（核心修正：通过流程定义获取名称）
        String currentNodeName = getNodeNameByActivityId(processDefinitionId, currentActivityId);
        if (currentNodeName == null) {
            throw new RuntimeException("未找到节点ID=" + currentActivityId + "的名称");
        }

        // 3. 获取流程实例ID
        String processInstanceId = execution.getProcessInstanceId();

        // 获取申请表id 、开启流程ID
//        Long enlistmentId = Long.valueOf(execution.getVariable("enlistmentId").toString());

        Long stId = (Long) execution.getVariable("basicId");

//       Integer intData = (Integer) execution.getVariable("basicId");
//        Long stId = null;
//        if (intData != null) {
//            // 先转为数字，再获取long值
//            Number num = (Number) intData;
//            stId = num.longValue();
//        }

        // 获取审核意见
        String approvalOpinion = (String) execution.getVariable("approvalOpinion");

//        // 获取审核状态
//        Long approvalResult = (Long) execution.getVariable("approvalResult");

        // 4. 后续逻辑不变：查询下一个节点负责人并更新变量
//        Long nextAssigneeId = getNextAssignee(currentNodeName, processInstanceId, stId, currentActivityId, approvalOpinion, approvalResult);
        Long nextAssigneeId = getNextAssignee(currentNodeName, processInstanceId, stId, currentActivityId);
        if (nextAssigneeId != null) {
            execution.setVariable("approval", nextAssigneeId);
            execution.setVariable("currentNode", currentNodeName);
        }
        // ========== 发送通知逻辑 ==========
        sendApprovalNotification(execution, currentNodeName, nextAssigneeId, stId);
    }

    /**
     * 根据节点ID和流程定义ID，查询节点名称（兼容所有版本的核心方法）
     */
    private String getNodeNameByActivityId(String processDefinitionId, String activityId) {
        // 获取流程模型
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        if (bpmnModel == null) {
            throw new RuntimeException("未找到流程定义ID=" + processDefinitionId + "的模型");
        }

        // 从模型中获取节点信息（FlowNode包含用户任务、网关等节点）
        FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(activityId);
        return flowNode != null ? flowNode.getName() : null;
    }


    /**
     * 根据当前节点查询下一个节点的负责人
     */
//    private Long getNextAssignee(String currentNodeName, String processInstanceId, Long stId, String currentActivityId, String approvalOpinion, Long approvalResult) {
    private Long getNextAssignee(String currentNodeName, String processInstanceId, Long stId, String currentActivityId) {
        EnlistmentReserveMapper rtEnlistmentReserveMapper = (EnlistmentReserveMapper) SpringUtils.getBean(EnlistmentReserveMapper.class);
        DisBasicMapper sysDisBasicMapper = (DisBasicMapper)SpringUtils.getBean(DisBasicMapper.class);
        // 根据学生学号来获取对应辅导员的信息  sysDisBasic.getStId()
        DisBasic sysDisId = sysDisBasicMapper.selectSysDisBasicById(stId);

        TeacherVo counselorInfo = rtEnlistmentReserveMapper.getCounselorInfo(sysDisId.getStId());
        // 获取辅导员的部门id
        Long currentDeptId = counselorInfo.getDeptId();
        if (currentDeptId == null) {
            throw new RuntimeException("未分配部门，无法匹配负责人");
        }
        // 注意：节点名称需与BPMN模型中完全一致（区分大小写）
        switch (currentNodeName) {

            case "招生与就业处":
                List<TeacherVo> zjcData = sysDisBasicMapper.getShenDataInfo("招就处");
                return zjcData.get(0).getUserId();


            case "辅导员审核":

                // 返回匹配的辅导员用户ID（作为下一个节点负责人）
                return counselorInfo.getUserId();

            case "学务审核":

                // 辅导员通过后 → 下一个节点：学务（筛选出角色ID=105，且与当前部门一致）
                // 查询角色ID=105（学务）的所有用户
                SysUser queryUser = new SysUser();
                queryUser.setRoleId(105L); // 学务角色固定ID
                List<SysUser> academicAffairsUsers = sysUserService.selectAllocatedList(queryUser);
                if (academicAffairsUsers.isEmpty()) {
                    throw new RuntimeException("未查询到角色（学务）的用户");
                }

                // 从学务用户中筛选出部门ID与当前辅导员部门一致的用户
                SysUser targetAcademic = academicAffairsUsers.stream()
                        .filter(user -> currentDeptId.equals(user.getDeptId())) // 部门ID匹配
                        .findFirst() // 取第一个匹配的学务（若有多个，可根据排序或优先级调整）
                        .orElseThrow(() -> new RuntimeException("未找到部门ID=" + currentDeptId + "的学务负责人"));
                return targetAcademic.getUserId();

                // 学务通过后 → 下一个节点：二级学院（角色ID=106，匹配学生所属学院）
                // 查询当前流程对应的业务数据（获取学生所属学院ID）
//                RtEnlistmentReserve reserve = enlistmentReserveMapper.selectRtEnlistmentReserveByProcessInstanceId(processInstanceId);
//                if (reserve == null) {
//                    throw new RuntimeException("未查询到流程对应的业务数据，processInstanceId=" + processInstanceId);
//                }



            case "二级学院审核":
                // 二级学院通过后 → 下一个节点：学籍管理科
                // 查询角色ID=106（二级学院）的所有用户
                SysUser qUser = new SysUser();
                qUser.setRoleId(106L); // 二级学院角色固定ID=106
                List<SysUser> collegeUsers = sysUserService.selectAllocatedList(qUser);
                if (collegeUsers.isEmpty()) {
                    throw new RuntimeException("未查询到角色（二级学院）的用户");
                }

                // 筛选出部门ID（学院ID）与登录用户所属学院一致的二级学院负责人
                SysUser targetCollegeLeader = collegeUsers.stream()
                        .filter(user -> currentDeptId.equals(user.getDeptId())) // 学院ID匹配（部门ID即学院ID）
                        .findFirst()
                        .orElseThrow(() -> new RuntimeException("未找到学院ID=" + currentDeptId + "的二级学院负责人（角色ID=106）"));



                // 返回匹配的二级学院负责人ID
                return targetCollegeLeader.getUserId();
            // 学籍管理科通过后 → 下一个节点：教务处主管领导（假设部门ID=40）

            // 获取学教务处主管领导审核人


            case "学籍管理":

                // 获取学籍管理科审核人
                List<TeacherVo> shenDataInfo = sysDisBasicMapper.getShenDataInfo("学籍管理科");

                if (shenDataInfo.isEmpty()) {
                    throw new RuntimeException("未查询到对应的用户");
                }


                // 暂时选择学籍管理科第一个人作为审核人
                return shenDataInfo.get(0).getUserId();

            case "教务处主管":
                // 最后一个节点通过后 → 流程结束（无需设置负责人）
                List<TeacherVo> teacherVos = sysDisBasicMapper.getShenDataInfo("教务处主管领导");

                if (teacherVos.isEmpty()) {
                    throw new RuntimeException("未查询到对应的用户");
                }

                // 暂时选择教务处主管领导第一个人作为审核人
                return teacherVos.get(0).getUserId();

            default:
                throw new RuntimeException("未配置节点[" + currentNodeName + "]的下一个负责人规则");
        }
    }

    /**
     * 发送审批通知（系统通知+企业微信通知）
     * 适配DisBasic（退伍复学）业务场景
     */
    private void sendApprovalNotification(DelegateExecution execution, String currentNodeName,
                                          Long nextAssigneeId, Long basicId) {
        try {
            // 1. 获取需要的Mapper和工具类（通过SpringUtils获取，避免Autowired循环依赖）
            LeaveMapper leaveMapper = (LeaveMapper) SpringUtils.getBean("leaveMapper");
            WeChatUtil weChatUtil = SpringUtils.getBean(WeChatUtil.class);

            // 2. 查询退伍复学申请详情
            DisBasicMapper disBasicMapper = (DisBasicMapper) SpringUtils.getBean(DisBasicMapper.class);
            DisBasic disBasic = disBasicMapper.selectSysDisBasicById(basicId);
            if (disBasic == null) {
                log.warn("未找到退伍复学申请记录，basicId:{}", basicId);
                return;
            }

            // 3. 查询下一个审批人的信息
            SysUser nextApprover = sysUserService.selectUserById(nextAssigneeId);
            if (nextApprover == null) {
                log.warn("未找到审批人信息，用户ID:{}", nextAssigneeId);
                return;
            }
            String approverUserName = nextApprover.getUserName(); // 审批人工号/用户名
            String approverName = nextApprover.getNickName(); // 审批人姓名

            log.info("开始发送【退伍复学审批】通知，审批节点：{}，审批人：{}({})，申请ID：{}",
                    currentNodeName, approverName, approverUserName, basicId);

            // 4. 处理系统通知（先删后加，避免重复通知）
            NotificationManage notificationManage = new NotificationManage();
            notificationManage.setContent(String.format("您有一条【退伍复学审批】待处理（节点：%s）", currentNodeName));
            notificationManage.setReceiver(nextAssigneeId); // 接收人：下一个审批人

            // 4.1 查询是否已有相同通知，有则删除
            NotificationManage existNotify = leaveMapper.selectCphMsgListForFlowable(notificationManage);
            if (existNotify != null) {
                int delRes = leaveMapper.deleteCphMsgById(existNotify.getId());
                log.info("删除重复的系统通知，通知ID:{}，删除结果:{}", existNotify.getId(), delRes);
            }

            // 4.2 添加新的系统通知
            notificationManage.setSender(SecurityUtils.getUserId()); // 发送人：当前操作人
            notificationManage.setCreateTime(DateUtils.getNowDate()); // 创建时间
            int addRes = leaveMapper.insertCphMsg(notificationManage);
            log.info("新增系统通知成功，接收人ID:{}，添加结果:{}", nextAssigneeId, addRes);

            // 5. 企业微信推送消息（带超链接）
            if (approverUserName != null && !approverUserName.isEmpty()) {
                String weChatContent = String.format(
                        "您有一条【退伍复学审批】待处理（节点：%s），<a href='https://zhxg.gxsdxy.cn/wab/#/pages/Approval/index'>请点击前往处理</a>",
                        currentNodeName
                );
                weChatUtil.sendTextMessage(approverUserName, weChatContent);
                log.info("企业微信通知发送成功，接收人工号:{}，节点:{}，申请ID：{}", approverUserName, currentNodeName, basicId);
            } else {
                log.warn("审批人工号为空，无法发送企业微信通知，用户ID:{}，申请ID：{}", nextAssigneeId, basicId);
            }

            // 6. 删除当前审批人的待处理通知（清理已处理的待办）
            Long currentApproverId = SecurityUtils.getUserId();
            if (currentApproverId == null) {
                log.warn("当前审批人ID为空，无法删除其待处理通知，申请ID：{}", basicId);
                return;
            }

            NotificationManage currentNotifyQuery = new NotificationManage();
            currentNotifyQuery.setContent(String.format("您有一条【退伍复学审批】待处理（节点：%s）", currentNodeName));
            currentNotifyQuery.setReceiver(currentApproverId);

            NotificationManage currentExistNotify = leaveMapper.selectCphMsgListForFlowable(currentNotifyQuery);
            if (currentExistNotify != null) {
                int currentDelRes = leaveMapper.deleteCphMsgById(currentExistNotify.getId());
                log.info("删除当前审批人({})的【{}】待处理通知，通知ID:{}，删除结果:{}，申请ID：{}",
                        currentApproverId, currentNodeName, currentExistNotify.getId(), currentDelRes, basicId);
            } else {
                log.info("当前审批人({})无【{}】节点的待处理通知，无需删除，申请ID：{}", currentApproverId, currentNodeName, basicId);
            }

        } catch (Exception e) {
            // 捕获所有异常，仅记录日志，不影响主流程
            log.error("发送退伍复学审批通知失败，节点：{}，审批人ID：{}，申请ID：{}，错误信息：{}",
                    currentNodeName, nextAssigneeId, basicId, e.getMessage(), e);
        }
    }

}