package com.srs.flowable.listener.outsideAccommodation;


import com.srs.common.utils.SecurityUtils;
import com.srs.common.utils.WeChatUtil;
import com.srs.common.utils.spring.SpringUtils;
import com.srs.flowable.domain.DormitoryStudent;
import com.srs.flowable.domain.OutsideAccommodationApply;
import com.srs.flowable.domain.OutsideAccommodationApproval;
import com.srs.flowable.mapper.OutsideAccommodationApplyMapper;
import com.srs.flowable.mapper.OutsideAccommodationApprovalMapper;
import com.srs.flowable.mapper.RelieveMapper;
import lombok.extern.slf4j.Slf4j;
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 java.util.Date;


/**
 * 审批流程负责人自动流转监听器
 * 用于节点审批通过时，添加审批记录 + 给学生发送企业微信通知
 */
@Component("OutsideAccommodationEndListener") // Spring Bean名称，与BPMN表达式对应
@Slf4j
public class OutsideAccommodationEndListener implements ExecutionListener {

    // 用于查询流程定义中的节点信息
    @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 accommodationId = Long.valueOf(execution.getVariable("accommodationId").toString());

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

        // 获取签名
        String signature = (String) execution.getVariable("signature");

        // 获取审核状态（兼容Integer/Long类型）
        Object approvalResultObj = execution.getVariable("approvalResult");
        Long approvalResult = null;
        if (approvalResultObj != null) {
            // 先转为数字，再获取long值
            Number num = (Number) approvalResultObj;
            approvalResult = num.longValue();
        }


        OutsideAccommodationApplyMapper outsideAccommodationApplyMapper = SpringUtils.getBean(OutsideAccommodationApplyMapper.class);
        // 根据Id查询外宿申请记录
        OutsideAccommodationApply outsideAccommodationApply = outsideAccommodationApplyMapper.selectDmsOutsideAccommodationApplyById(accommodationId);
        // 添加审批记录
        saveApprovalRecord(outsideAccommodationApply.getId(), outsideAccommodationApply.getProcessInstanceId(),outsideAccommodationApply.getApplyNo(),currentNodeName, outsideAccommodationApply.getStudentName(), outsideAccommodationApply.getStudentNo(), approvalOpinion, approvalResult, signature);
        Long status = 1L;
        if (currentNodeName.equals("辅导员审批")) {
            status = 2L;
        }
        if (currentNodeName.equals("二级学院书记审批")) {
            status = 3L;
        }
        if (currentNodeName.equals("学工处审批")) {
            status = 4L;
        }
        // 如果到了最后一个审批人，则修改申请表审核状态
        if (currentNodeName.equals("学校领导审批")){
            // 改变申请表中的审核状态（审核通过）
            status = 5L;
            DormitoryStudent dormitoryStudent = new DormitoryStudent();
            dormitoryStudent.setStuNo(outsideAccommodationApply.getStudentNo());
            dormitoryStudent.setIsInStudentsleep("外宿");
            // 审核通过改变学生住宿状态
            outsideAccommodationApplyMapper.updateSrsDormitoryStudent(dormitoryStudent);
        }
        outsideAccommodationApply.setStatus(status);
        outsideAccommodationApplyMapper.updateDmsOutsideAccommodationApply(outsideAccommodationApply);
        // ========== 给学生发送企业微信通知 ==========
        sendStudentWeChatNotification(execution, outsideAccommodationApply, currentNodeName, approvalResult, approvalOpinion);
    }

    /**
     * 给学生发送外宿申请审批结果的企业微信通知
     */
    private void sendStudentWeChatNotification(DelegateExecution execution, OutsideAccommodationApply outsideAccommodationApply,
                                               String currentNodeName, Long approvalResult, String approvalOpinion) {
        try {
            // 1. 获取需要的Mapper和工具类
            RelieveMapper relieveMapper = (RelieveMapper) SpringUtils.getBean("relieveMapper");
            WeChatUtil weChatUtil = SpringUtils.getBean(WeChatUtil.class);

            // 2. 获取学生学号和姓名（从外宿申请对象中获取）
            String studentNo = outsideAccommodationApply.getStudentNo();
            String studentName = outsideAccommodationApply.getStudentName();

            // 3. 先尝试从流程变量获取学生userId
            Long stuUserId = null;
            if (execution.hasVariable("stuUserId")) {
                stuUserId = Long.valueOf(execution.getVariable("stuUserId").toString());
            } else {
                // 补充逻辑：如果流程变量中没有stuUserId，通过申请表获取
                stuUserId = outsideAccommodationApply.getStudentId();
            }

            if (stuUserId == null) {
                log.warn("⚠ 未找到学生(学号:{},姓名:{})对应的用户ID，无法发送通知", studentNo, studentName);
                return;
            }

            // 4. 使用userId查询对应的企业微信账号
            String stuUserName = relieveMapper.getUserNameByUserId(stuUserId);

            if (stuUserName != null && !stuUserName.isEmpty()) {
                // 5. 拼接审批结果提示信息（适配外宿申请场景）
                String approveResultDesc = getApprovalResultDesc(approvalResult, currentNodeName);

                // 6. 拼接最终通知内容
                String content = String.format("您的外宿申请有新的审批进展：%s（%s），%s，<a href='https://zhxg.gxsdxy.cn/wab/#/pages/Approval/index'>点此查看详情</a>",
                        currentNodeName,
                        approveResultDesc,
                        (approvalOpinion != null && !approvalOpinion.isEmpty()) ? "审批意见：" + approvalOpinion : "");

                // 7. 发送企业微信消息
                weChatUtil.sendTextMessage(stuUserName, content);
                log.info("✅ 已成功向学生(姓名:{},学号:{},userName:{})发送外宿申请审批通知。审批节点：{}，结果：{}",
                        studentName, studentNo, stuUserName, currentNodeName, approveResultDesc);

            } else {
                log.warn("⚠ 找到了学生(学号:{},姓名:{},userId:{})，但其对应的企业微信账号为空，无法发送通知。",
                        studentNo, studentName, stuUserId);
            }
        } catch (Exception e) {
            // 捕获所有异常，仅记录日志，不影响主流程
            String studentNo = outsideAccommodationApply.getStudentNo();
            log.error("❌ 向学生(学号:{})发送外宿申请审批通知时出现异常，但流程将继续。错误详情:", studentNo, e);
        }
    }

    /**
     * 转换审批结果为可读描述（适配外宿申请的审批状态）
     */
    private String getApprovalResultDesc(Long approvalResult, String currentNodeName) {
        if (approvalResult == null) {
            return "审批已处理";
        }
        switch (approvalResult.intValue()) {
            case 0:
                return currentNodeName + "驳回";
            case 1:
                return currentNodeName + "通过";
            case 2:
                return "审批中";
            default:
                return "审批已完成";
        }
    }

    /**
     * 根据节点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 void saveApprovalRecord(Long ApplyId,String processInstanceId, String applyNo, String nodeName, String studentName, String studentNo, String approvalOpinion, Long approvalResult, String signature) {
        OutsideAccommodationApproval outsideAccommodationApproval = new OutsideAccommodationApproval();
        // 赋值
        outsideAccommodationApproval.setApplyId(ApplyId);
        outsideAccommodationApproval.setProcessInstanceId(processInstanceId);
        outsideAccommodationApproval.setApplyNo(applyNo);
        outsideAccommodationApproval.setApprovalNode(nodeName);
        outsideAccommodationApproval.setApproverId(SecurityUtils.getLoginUser().getUser().getUserId());
        // SecurityUtils.getUserName()是工号
        outsideAccommodationApproval.setApproverName(SecurityUtils.getLoginUser().getUser().getNickName());
//        System.out.println(SecurityUtils.getLoginUser().getUser());
        // 若变量未传递，直接用默认值“同意”（前端点击同意按钮的默认意见）
        outsideAccommodationApproval.setApprovalOpinion(approvalOpinion);

        // 审核状态
        outsideAccommodationApproval.setApprovalResult(approvalResult == null ? 0L : approvalResult);

        // 审批时间：当前系统时间
        outsideAccommodationApproval.setApprovalTime(new Date());
        outsideAccommodationApproval.setStudentName(studentName);
        outsideAccommodationApproval.setStudentNo(studentNo);
        // 设置签名
        outsideAccommodationApproval.setSignature(signature);
        OutsideAccommodationApprovalMapper outsideAccommodationApprovalMapper = (OutsideAccommodationApprovalMapper) SpringUtils.getBean(OutsideAccommodationApprovalMapper.class);
        // 查询审批记录是否存在
        OutsideAccommodationApproval approval = outsideAccommodationApprovalMapper.selectOutsideAccommodationApprovalByStuName(studentName, studentNo, SecurityUtils.getLoginUser().getUser().getUserId());
        if (approval == null) {
            outsideAccommodationApprovalMapper.insertDmsOutsideAccommodationApproval(outsideAccommodationApproval);
        } else {
            outsideAccommodationApproval.setId(approval.getId());
            outsideAccommodationApprovalMapper.updateDmsOutsideAccommodationApproval(outsideAccommodationApproval);
        }
    }
}