/**
 * 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.ChainState;

import java.util.EnumSet;
import java.util.concurrent.TimeUnit;

public interface ChainStateRepository {

    ChainState load(String instanceId);

    /**
     * 轻量读取工作流状态版本。
     *
     * <p>分布式仓储应覆盖本方法并只读取版本字段，避免节点状态提交前反序列化完整
     * 工作流热状态。</p>
     *
     * @param instanceId 工作流实例 ID
     * @return 当前版本；状态不存在时返回 {@code null}
     */
    default Long loadVersion(String instanceId) {
        ChainState state = load(instanceId);
        return state == null ? null : state.getVersion();
    }

    /**
     * 创建工作流实例状态。
     *
     * @param instanceId 工作流实例 ID
     * @return 已存在或新创建的状态
     */
    default ChainState create(String instanceId) {
        return load(instanceId);
    }

    boolean tryUpdate(ChainState newState, EnumSet<ChainStateField> fields);

    /**
     * 在当前实例锁 fencing token 仍有效时提交状态。
     *
     * <p>单进程仓储可沿用普通乐观锁；分布式仓储应覆盖本方法并在同一原子操作中校验
     * token。</p>
     *
     * @param newState 待提交状态
     * @param fields 变化字段
     * @param fencingToken 当前实例锁 token；本地仓储调用为 {@code 0}
     * @return 提交成功时为 {@code true}
     */
    default boolean tryUpdate(
            ChainState newState, EnumSet<ChainStateField> fields, long fencingToken) {
        return tryUpdate(newState, fields);
    }

    /**
     * 在实例锁和当前触发器认领租约均有效时提交状态。
     *
     * <p>分布式仓储应在同一原子操作中校验实例锁 fencing token 与 claim generation，
     * 同时拒绝锁过期后的旧执行者和租约过期后的旧 owner。</p>
     *
     * @param newState 待提交状态
     * @param fields 变化字段
     * @param lockFencingToken 当前实例锁 token；本地仓储调用为 {@code 0}
     * @param claimId 当前触发器 ID；非触发器调用为 {@code null}
     * @param claimGeneration 当前认领代际；非触发器调用为 {@code 0}
     * @return 提交成功时为 {@code true}
     */
    default boolean tryUpdate(
            ChainState newState,
            EnumSet<ChainStateField> fields,
            long lockFencingToken,
            String claimId,
            long claimGeneration) {
        return tryUpdate(newState, fields, lockFencingToken);
    }

    /**
     * 获取指定 instanceId 的分布式锁
     *
     * @param instanceId 链实例 ID
     * @param timeout    获取锁的超时时间
     * @param unit       时间单位
     * @return ChainLock 句柄，调用方必须负责 close()
     * @throws IllegalArgumentException if instanceId is blank
     */
    default ChainLock getLock(String instanceId, long timeout, TimeUnit unit) {
        return new LocalChainLock(instanceId, timeout, unit);
    }
}
