package com.srs.flowable.listener.enlistmentReserve;

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.EnlistmentReserve;
import com.srs.flowable.domain.EnlistmentReserveApproval;
import com.srs.flowable.domain.NotificationManage;
import com.srs.flowable.mapper.EnlistmentReserveApprovalMapper;
import com.srs.flowable.mapper.EnlistmentReserveMapper;
import com.srs.flowable.mapper.LeaveMapper;
import com.srs.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
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 java.util.Date;
import java.util.List;


/**
 * 审批流程负责人自动流转监听器
 * 用于节点审批之前时，更新下一个节点的负责人变量(approval)
 */
@Component("startApprovalAssigneeListener") // Spring Bean名称，与BPMN表达式对应
@Slf4j
public class StartApprovalAssigneeListener implements ExecutionListener {

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

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

    @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 + "的名称");
        }

        // 获取申请表id
        Long enlistmentId = Long.valueOf(execution.getVariable("enlistmentId").toString());


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

    /**
     * 根据节点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, Long enlistmentId) {
        EnlistmentReserveMapper rtEnlistmentReserveMapper = (EnlistmentReserveMapper) SpringUtils.getBean(EnlistmentReserveMapper.class);
        // 根据Id查询入伍申请记录
        EnlistmentReserve enlistmentReserve = rtEnlistmentReserveMapper.selectRtEnlistmentReserveById(enlistmentId);
        // 根据学生学号来获取对应辅导员的信息
        TeacherVo counselorInfo = rtEnlistmentReserveMapper.getCounselorInfo(enlistmentReserve.getStudentNo());
        // 获取辅导员的部门id
        Long currentDeptId = counselorInfo.getDeptId();
        if (currentDeptId == null) {
            throw new RuntimeException("未分配部门，无法匹配负责人");
        }
        // 注意：节点名称需与BPMN模型中完全一致（区分大小写）
        switch (currentNodeName) {
            case "辅导员审批":
                // 辅导员开始审批前 → 找到对应辅导员
                // 返回匹配的辅导员用户ID（作为当前节点负责人）
                return counselorInfo.getUserId();

            case "学务审批":

                // 学务开始审批前 → 找到对应学务
                // 查询角色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 + "的学务负责人"));


                // 返回匹配的学务用户ID（作为当前节点负责人）
                return targetAcademic.getUserId();

            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();

            case "学籍管理科审批":

                // 学籍管理科开始审批前 → 找到对应学籍管理科

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

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


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

            case "教务处主管领导审批":
                // 教务处主管领导开始审批前 → 找到对应教务处主管领导

                // 获取学教务处主管领导审核人
                List<TeacherVo> teacherVos = rtEnlistmentReserveMapper.getShenDataInfo("教务处主管领导");

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

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

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

    /**
     * 发送审批通知（系统通知+企业微信通知）
     */
    private void sendApprovalNotification(DelegateExecution execution, String currentNodeName,
                                          Long nextAssigneeId, Long enlistmentId) {
        try {
            // 获取需要的Mapper和工具类
            EnlistmentReserveMapper enlistmentReserveMapper = (EnlistmentReserveMapper) SpringUtils.getBean(EnlistmentReserveMapper.class);
            LeaveMapper leaveMapper = (LeaveMapper) SpringUtils.getBean("leaveMapper");
            WeChatUtil weChatUtil = SpringUtils.getBean(WeChatUtil.class);

            // 1. 查询入伍保留学籍申请详情
            EnlistmentReserve enlistmentReserve = enlistmentReserveMapper.selectRtEnlistmentReserveById(enlistmentId);
            if (enlistmentReserve == null) {
                log.warn("未找到入伍保留学籍申请记录，ID:{}", enlistmentId);
                return;
            }

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

            log.info("开始发送【入伍保留学籍审批】通知，审批节点：{}，审批人：{}({})",
                    currentNodeName, approverName, approverUserName);

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

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

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

            // 4. 企业微信推送消息
            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("企业微信通知发送成功，接收人工号:{}，节点:{}", approverUserName, currentNodeName);
            } else {
                log.warn("审批人工号为空，无法发送企业微信通知，用户ID:{}", nextAssigneeId);
            }

            // ========== 删除当前审批人的待处理通知 ==========
            // 4.1 获取当前审批人ID（当前操作人=已完成审批的人）
            Long currentApproverId = SecurityUtils.getUserId();
            if (currentApproverId == null) {
                log.warn("当前审批人ID为空，无法删除其待处理通知");
                return;
            }

            // 4.2 构造当前审批人的待处理通知查询条件
            NotificationManage currentNotifyQuery = new NotificationManage();
            // 内容匹配：当前节点的待处理通知（关键词+节点名称）
            currentNotifyQuery.setContent(String.format("您有一条【入伍保留学籍审批】待处理（节点：%s）", currentNodeName));
            currentNotifyQuery.setReceiver(currentApproverId); // 接收人=当前审批人

            // 4.3 查询当前审批人的该节点待处理通知
            NotificationManage currentExistNotify = leaveMapper.selectCphMsgListForFlowable(currentNotifyQuery);
            if (currentExistNotify != null) {
                // 4.4 删除该通知（清理已处理的待办）
                int currentDelRes = leaveMapper.deleteCphMsgById(currentExistNotify.getId());
                log.info("删除当前审批人({})的【{}】待处理通知，通知ID:{}，删除结果:{}",
                        currentApproverId, currentNodeName, currentExistNotify.getId(), currentDelRes);
            } else {
                log.info("当前审批人({})无【{}】节点的待处理通知，无需删除", currentApproverId, currentNodeName);
            }

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