/**
 * Copyright (c) 2025-2026, Michael Yang 杨福海 (fuhai999@gmail.com).
 * <p>
 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl-3.0.txt
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.easyagents.flow.core.chain.repository;

import com.easyagents.flow.core.chain.NodeState;

import java.util.EnumSet;

public interface NodeStateRepository {

    /**
     * 加载已存在的节点状态。
     *
     * @param instanceId 工作流实例 ID
     * @param nodeId 节点 ID
     * @return 节点状态；纯读取实现可在状态缺失时返回 {@code null}，兼容实现可惰性创建
     */
    NodeState load(String instanceId, String nodeId);

    /**
     * 显式创建节点状态。
     *
     * <p>缺省实现兼容旧仓储中由 {@link #load(String, String)} 完成首次创建的行为。
     * 支持持久化或分布式执行的实现应覆盖本方法并原子创建状态。</p>
     *
     * @param instanceId 工作流实例 ID
     * @param nodeId 节点 ID
     * @param chainStateVersion 创建时关联的工作流状态版本
     * @return 已存在或新创建的节点状态
     */
    default NodeState create(String instanceId, String nodeId, long chainStateVersion) {
        NodeState existing = load(instanceId, nodeId);
        if (existing != null) {
            return existing;
        }
        NodeState created = new NodeState();
        created.setChainInstanceId(instanceId);
        created.setNodeId(nodeId);
        if (tryUpdate(
                created,
                EnumSet.noneOf(NodeStateField.class),
                chainStateVersion)) {
            return created;
        }
        return load(instanceId, nodeId);
    }

    /**
     * 在当前触发器 fencing token 仍有效时显式创建节点状态。
     *
     * @param instanceId 工作流实例 ID
     * @param nodeId 节点 ID
     * @param chainStateVersion 工作流状态版本
     * @param fencingToken 当前触发器 token；非触发器调用为 {@code 0}
     * @return 已存在或新创建的节点状态
     */
    default NodeState create(
            String instanceId, String nodeId, long chainStateVersion, long fencingToken) {
        return create(instanceId, nodeId, chainStateVersion);
    }

    /**
     * 在实例锁和当前触发器认领租约均有效时显式创建节点状态。
     *
     * @param instanceId 工作流实例 ID
     * @param nodeId 节点 ID
     * @param chainStateVersion 工作流状态版本
     * @param lockFencingToken 当前实例锁 token；本地仓储调用为 {@code 0}
     * @param claimId 当前触发器 ID；非触发器调用为 {@code null}
     * @param claimGeneration 当前认领代际；非触发器调用为 {@code 0}
     * @return 已存在或新创建的节点状态
     */
    default NodeState create(
            String instanceId,
            String nodeId,
            long chainStateVersion,
            long lockFencingToken,
            String claimId,
            long claimGeneration) {
        return create(instanceId, nodeId, chainStateVersion, lockFencingToken);
    }

    /**
     * 按版本尝试提交节点状态。
     *
     * @param newState 待提交的新状态
     * @param fields 本次变更字段
     * @param chainStateVersion 本次提交依赖的工作流状态版本
     * @return 提交成功时为 {@code true}，版本冲突时为 {@code false}
     */
    boolean tryUpdate(NodeState newState, EnumSet<NodeStateField> fields, long chainStateVersion);

    /**
     * 在工作流版本和 fencing token 同时有效时提交节点状态。
     *
     * @param newState 待提交节点状态
     * @param fields 变化字段
     * @param chainStateVersion 工作流状态版本
     * @param fencingToken 当前触发器 token；非触发器调用为 {@code 0}
     * @return 提交成功时为 {@code true}
     */
    default boolean tryUpdate(
            NodeState newState,
            EnumSet<NodeStateField> fields,
            long chainStateVersion,
            long fencingToken) {
        return tryUpdate(newState, fields, chainStateVersion);
    }

    /**
     * 在工作流版本、实例锁和当前触发器认领租约同时有效时提交节点状态。
     *
     * @param newState 待提交节点状态
     * @param fields 变化字段
     * @param chainStateVersion 工作流状态版本
     * @param lockFencingToken 当前实例锁 token；本地仓储调用为 {@code 0}
     * @param claimId 当前触发器 ID；非触发器调用为 {@code null}
     * @param claimGeneration 当前认领代际；非触发器调用为 {@code 0}
     * @return 提交成功时为 {@code true}
     */
    default boolean tryUpdate(
            NodeState newState,
            EnumSet<NodeStateField> fields,
            long chainStateVersion,
            long lockFencingToken,
            String claimId,
            long claimGeneration) {
        return tryUpdate(newState, fields, chainStateVersion, lockFencingToken);
    }
}
