package com.fs.company.service.impl.call.node;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.fs.common.constant.Constants;
import com.fs.common.core.redis.RedisCacheT;
import com.fs.common.utils.StringUtils;
import com.fs.common.utils.spring.SpringUtils;
import com.fs.company.domain.*;
import com.fs.company.mapper.CompanyWxClientMapper;
import com.fs.company.param.ExecutionContext;
import com.fs.company.vo.AiCallWorkflowConditionVo;
import com.fs.company.vo.ExecutionResult;
import com.fs.enums.ExecutionStatusEnum;
import com.fs.enums.NodeTypeEnum;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author：peicj
 * @Description: AI企微添加个微节点
 * @Date：2026/2/27 11:05
 */
@Slf4j
public class AiQwAddWxTaskNode extends AbstractWorkflowNode {

    private static final CompanyWxClientMapper companyWxClientMapper = SpringUtils.getBean(CompanyWxClientMapper.class);
    @SuppressWarnings("unchecked")
    private static final RedisCacheT<String> redisCache = SpringUtils.getBean(RedisCacheT.class);
    public static final String DELAY_QW_ADD_WX_KEY = "qwAddWxTask:delay:%s:%s:";
    /**
     * 默认加微超时时间（分钟）
     */
    private static final int DEFAULT_ADD_WX_TIMEOUT_MINUTES = 30;

    public AiQwAddWxTaskNode(String nodeKey, String nodeName, Map<String, Object> properties) {
        super(nodeKey, nodeName, properties);
    }

    /**
     * 收到加微回调后，继续判定和执行下一步动作
     * 加微成功后不直接流转，而是改为等待状态，等待下一次回调
     *
     * @param context 执行上下文
     * @return 执行结果
     */
    @Override
    protected ExecutionResult doContinue(ExecutionContext context) {
        //收到回调代表加微通过了
        CompanyAiWorkflowExec exec = companyAiWorkflowExecMapper.selectByWorkflowInstanceId(context.getWorkflowInstanceId());
        List<CompanyWorkflowEdge> edges = companyWorkflowEdgeMapper.selectListByWorkflowIdAndNodeKey(exec.getWorkflowId(), nodeKey);

        // 获取业务数据
        CompanyVoiceRoboticBusiness business = super.getRoboticBusiness(context.getWorkflowInstanceId());
        // 获取加微记录
        CompanyWxClient wxClient = companyWxClientMapper.selectById(business.getWxClientId());

        log.info("收到加微回调 - workflowInstanceId: {}, wxClientId: {}, isAdd: {}",
                context.getWorkflowInstanceId(), business.getWxClientId(), wxClient != null ? wxClient.getIsAdd() : null);

        // 判断加微是否成功 (isAdd: 0否 1是 2待添加 3作废)
        boolean addSuccess = wxClient != null && Integer.valueOf(1).equals(wxClient.getIsAdd());
        //回调加微成功
        if (addSuccess) {
            List<CompanyWorkflowEdge> cList = edges.stream().filter(a -> {
                if (StringUtils.isBlank(a.getConditionExpr())) {
                    return false;
                }
                List<AiCallWorkflowConditionVo> list = JSONObject.parseArray(a.getConditionExpr(), AiCallWorkflowConditionVo.class);
                return list != null && !list.isEmpty() && list.get(0).isAdd();
            }).collect(Collectors.toList());
            if (!cList.isEmpty() && nodeKey.equals(exec.getCurrentNodeKey())) {
                super.runNextNode(context, cList.get(0));
            }
        }
        else {
            List<CompanyWorkflowEdge> cList = edges.stream().filter(a ->
                            StringUtils.isNotBlank(a.getConditionExpr()) && !JSONObject.parseArray(a.getConditionExpr(), AiCallWorkflowConditionVo.class).get(0).isAdd())
                    .collect(Collectors.toList());
            // 加微失败，根据条件判断走哪条边
            CompanyWorkflowEdge edge = cList.get(0);
            List<AiCallWorkflowConditionVo> conditions = JSONObject.parseArray(edge.getConditionExpr(), AiCallWorkflowConditionVo.class);
             AiCallWorkflowConditionVo condition = conditions.get(0);
                // 匹配失败条件
                if (!condition.isAdd()) {
                    log.info("加微失败，执行失败分支 - workflowInstanceId: {}", context.getWorkflowInstanceId());
                    super.runNextNode(context, edge);
                    return null;
                }

            log.error("加微失败但未找到失败分支 - workflowInstanceId: {}", context.getWorkflowInstanceId());
            return null;
        }
        return null;
    }

    /**
     * 执行加微节点逻辑（只准备数据，实际加微由定时任务执行）
     *
     * @param context 执行上下文
     * @return 执行结果
     */
    @Override
    protected ExecutionResult doExecute(ExecutionContext context) {
        if (!isAsync()) {
            return ExecutionResult.failure().nextNodeKey(null).build();
        }
        try {
            super.asyncWorkflowForBlockingNode(context.getWorkflowInstanceId(), context.getCurrentNodeKey(), context, ExecutionStatusEnum.WAITING);
            return ExecutionResult.waiting()
                    .outputData(context.getVariables())
                    .nextNodeKey("").build();
        } catch (Exception e) {
            log.error("准备加微任务数据异常 流程：{}：节点:{}执行失败，", context.getWorkflowInstanceId(), nodeKey, e);
            super.updateWorkflowStatus(context.getWorkflowInstanceId(), ExecutionStatusEnum.INTERRUPT);
            return ExecutionResult.failure().errorMessage("准备加微任务数据异常: " + e.getMessage()).build();
        }
    }

    @Override
    public NodeTypeEnum getType() {
        return NodeTypeEnum.AI_QW_ADD_WX_TASK;
    }

    @Override
    public Boolean isAsync() {
        return true;
    }


    /**
     * 从节点配置获取超时时间（分钟）
     */
    private int getTimeoutFromProperties() {
        if (properties != null && properties.containsKey("timeout")) {
            Object timeout = properties.get("timeout");
            if (timeout instanceof Number) {
                return ((Number) timeout).intValue();
            }
            if (timeout instanceof String) {
                try {
                    return Integer.parseInt((String) timeout);
                } catch (NumberFormatException e) {
                    log.warn("解析超时时间失败: {}, 使用默认值: {}", timeout, DEFAULT_ADD_WX_TIMEOUT_MINUTES);
                }
            }
        }
        return DEFAULT_ADD_WX_TIMEOUT_MINUTES;
    }

    /**
     * 检查并标记已执行（用于互斥逻辑）
     * 如果返回 true 表示当前是第一个执行的，可以继续
     * 如果返回 false 表示已经被其他路径执行过了，不再执行
     *
     * @param workflowInstanceId 工作流实例ID
     * @param wxClientId         加微客户ID
     * @return 是否可以执行
     */
    public static boolean tryMarkAsExecuted(String workflowInstanceId, Long wxClientId) {
        String executedKey = Constants.WORKFLOW_QW_ADD_WX_EXECUTED + workflowInstanceId + ":" + wxClientId;
        String existingValue = redisCache.getCacheObject(executedKey);
        if (existingValue != null) {
            // 已经被执行过了
            return false;
        }
        // 标记为已执行，设置1小时过期
        redisCache.setCacheObject(executedKey, "1");
        redisCache.expire(executedKey, 3600);
        return true;
    }

    /**
     * 清除超时检测 Key
     *
     * @param workflowInstanceId 工作流实例ID
     * @param wxClientId         加微客户ID
     */
    public static void clearTimeoutKey(String workflowInstanceId, Long wxClientId) {
        String timeoutKey = Constants.WORKFLOW_QW_ADD_WX_TIMEOUT + workflowInstanceId + ":" + wxClientId;
        redisCache.deleteObject(timeoutKey);
        log.info("清除加微超时检测 Key: {}", timeoutKey);
    }

    /**
     * getRedisCacheKey
     *
     */
    public static String getDelayAddWxKeyPrefix(Integer cidGroupNo,Long time) {
        Date nowDay;
        if (null != time) {
            nowDay = new Date(time);
        }else{
            nowDay = new Date();
        }
        return String.format(DELAY_QW_ADD_WX_KEY,cidGroupNo, nowDay.getHours(), nowDay.getMinutes());
    }

    /**
     * 完成加微动作
     *
     */
    public void doneQwAddWx(String workflowInstanceId) {
        ExecutionContext context = createExecutionContext(workflowInstanceId, nodeKey);
        context.setVariable("lastNodeKey", nodeKey);
        //启动定时节点倒计时
        CompanyAiWorkflowExec exec = companyAiWorkflowExecMapper.selectByWorkflowInstanceId(context.getWorkflowInstanceId());
        if (!exec.getCurrentNodeKey().equals(nodeKey)) {
            //当前节点已流转
            log.error("当前节点已流转 ,目标：{}，实际：{}", nodeKey, exec.getCurrentNodeKey());
            return;
        }
        //更新加微日志执行状态
        super.updateLogStatusIfExist(context, ExecutionStatusEnum.WAITING, ExecutionStatusEnum.WAITING);
        super.asyncWorkflowForBlockingNode(context.getWorkflowInstanceId(), nodeKey, context, ExecutionStatusEnum.WAITING);
        List<CompanyWorkflowEdge> edges = companyWorkflowEdgeMapper.selectListByWorkflowIdAndNodeKey(exec.getWorkflowId(), nodeKey);
        edges.forEach(edge -> {
            List<AiCallWorkflowConditionVo> conditions = JSONObject.parseArray(edge.getConditionExpr(), AiCallWorkflowConditionVo.class);
            if (CollectionUtil.isEmpty(conditions)) {
                super.runNextNode(context, edge);
            } else {
                AiCallWorkflowConditionVo condition = conditions.get(0);
                //节点包含延时条件
                if (null != condition.getAddTime() && !condition.isAdd()) {
                    long l = System.currentTimeMillis() + condition.getAddTime() * 60 * 1000;
                    String redisKey = getDelayAddWxKeyPrefix(exec.getCidGroupNo(),l) + workflowInstanceId;
                    ExecutionContext nextContext = context.clone();
                    nextContext.setCurrentNodeKey(edge.getTargetNodeKey());
                    super.redisCache.setCacheObject(redisKey, nextContext);
                }
            }
        });
    }
}
