package tech.easyflow.common.cache;

import java.io.Serializable;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 支持原子版本比较的对象存储。
 */
public interface VersionedObjectStore {

    /**
     * 加载对象。
     *
     * @param key 存储键
     * @param type 对象类型
     * @param <T> 对象类型
     * @return 已存在的对象；不存在时返回 {@code null}
     */
    <T> T load(String key, Class<T> type);

    /**
     * 批量加载对象并保持输入键顺序。
     *
     * @param keys 存储键
     * @param type 对象类型
     * @param <T> 对象类型
     * @return 与输入键等长的对象列表；缺失位置为 {@code null}
     */
    default <T> List<T> loadAll(List<String> keys, Class<T> type) {
        List<T> values = new ArrayList<>(keys.size());
        for (String key : keys) {
            values.add(load(key, type));
        }
        return values;
    }

    /**
     * 批量删除对象。
     *
     * @param keys 存储键
     */
    default void deleteAll(List<String> keys) {
        throw new UnsupportedOperationException("Batch delete is not supported");
    }

    /**
     * 两个守卫版本均匹配时原子批量删除对象。
     *
     * @param keys 待删除对象键
     * @param guardKey 第一守卫键
     * @param guardVersion 第一守卫版本
     * @param secondaryGuardKey 第二守卫键
     * @param secondaryGuardVersion 第二守卫版本
     * @return 守卫匹配并执行删除时为 {@code true}
     */
    default boolean deleteAll(
            List<String> keys,
            String guardKey,
            long guardVersion,
            String secondaryGuardKey,
            long secondaryGuardVersion) {
        throw new UnsupportedOperationException(
                "Guarded batch delete is not supported");
    }

    /**
     * 批量刷新对象有效期。
     *
     * @param keys 存储键
     * @param ttl 新有效期
     */
    default void refreshExpirations(List<String> keys, Duration ttl) {
        throw new UnsupportedOperationException("Expiration refresh is not supported");
    }

    /**
     * 原子创建对象。
     *
     * @param key 存储键
     * @param value 初始对象
     * @param version 初始版本
     * @param ttl 有效期
     * @return 创建成功时为 {@code true}，对象已存在时为 {@code false}
     */
    boolean createIfAbsent(String key, Serializable value, long version, Duration ttl);

    /**
     * 在守卫对象版本匹配时原子创建对象。
     *
     * @param key 存储键
     * @param value 初始对象
     * @param version 初始版本
     * @param guardKey 守卫对象键
     * @param guardVersion 期望的守卫版本
     * @param ttl 有效期
     * @return 创建成功时为 {@code true}，对象已存在或守卫版本冲突时为 {@code false}
     */
    boolean createIfAbsent(String key,
                           Serializable value,
                           long version,
                           String guardKey,
                           long guardVersion,
                           Duration ttl);

    /**
     * 两个守卫版本均匹配时原子创建对象。
     *
     * @param key 存储键
     * @param value 初始对象
     * @param version 初始版本
     * @param guardKey 第一守卫键
     * @param guardVersion 第一守卫版本
     * @param secondaryGuardKey 第二守卫键
     * @param secondaryGuardVersion 第二守卫版本
     * @param ttl 有效期
     * @return 创建成功时为 {@code true}
     */
    default boolean createIfAbsent(
            String key,
            Serializable value,
            long version,
            String guardKey,
            long guardVersion,
            String secondaryGuardKey,
            long secondaryGuardVersion,
            Duration ttl) {
        return createIfAbsent(key, value, version, guardKey, guardVersion, ttl);
    }

    /**
     * 原子比较并更新对象。
     *
     * @param key 存储键
     * @param expectedVersion 期望的当前版本
     * @param value 新对象
     * @param newVersion 新版本
     * @param ttl 有效期
     * @return 更新成功时为 {@code true}，对象缺失或版本冲突时为 {@code false}
     */
    boolean compareAndSet(String key,
                          long expectedVersion,
                          Serializable value,
                          long newVersion,
                          Duration ttl);

    /**
     * 在守卫对象版本匹配时原子比较并更新对象。
     *
     * @param key 存储键
     * @param expectedVersion 期望的当前版本
     * @param value 新对象
     * @param newVersion 新版本
     * @param guardKey 守卫对象键
     * @param guardVersion 期望的守卫版本
     * @param ttl 有效期
     * @return 更新成功时为 {@code true}，对象缺失或任一版本冲突时为 {@code false}
     */
    boolean compareAndSet(String key,
                          long expectedVersion,
                          Serializable value,
                          long newVersion,
                          String guardKey,
                          long guardVersion,
                          Duration ttl);

    /**
     * 两个守卫版本均匹配时原子比较并更新对象。
     *
     * @param key 存储键
     * @param expectedVersion 期望的当前版本
     * @param value 新对象
     * @param newVersion 新版本
     * @param guardKey 第一守卫键
     * @param guardVersion 第一守卫版本
     * @param secondaryGuardKey 第二守卫键
     * @param secondaryGuardVersion 第二守卫版本
     * @param ttl 有效期
     * @return 更新成功时为 {@code true}
     */
    default boolean compareAndSet(
            String key,
            long expectedVersion,
            Serializable value,
            long newVersion,
            String guardKey,
            long guardVersion,
            String secondaryGuardKey,
            long secondaryGuardVersion,
            Duration ttl) {
        return compareAndSet(
                key, expectedVersion, value, newVersion, guardKey, guardVersion, ttl);
    }

    /**
     * 一次读取字段化状态及其版本。
     *
     * @param key 存储键
     * @return 字段化状态；不存在时返回 {@code null}
     */
    default VersionedFields loadFields(String key) {
        throw new UnsupportedOperationException("Field storage is not supported");
    }

    /**
     * 只读取对象版本。
     *
     * @param key 存储键
     * @return 当前版本；对象不存在或缺少版本时返回 {@code null}
     */
    default Long loadVersion(String key) {
        VersionedFields fields = loadFields(key);
        return fields == null ? null : fields.getVersion();
    }

    /**
     * 原子创建字段化状态。
     *
     * @param key 存储键
     * @param fields 初始字段
     * @param version 初始版本
     * @param ttl 有效期
     * @return 创建成功时为 {@code true}
     */
    default boolean createFieldsIfAbsent(String key,
                                         Map<String, ? extends Serializable> fields,
                                         long version,
                                         Duration ttl) {
        throw new UnsupportedOperationException("Field storage is not supported");
    }

    /**
     * 守卫版本匹配时原子创建字段化状态。
     *
     * @param key 存储键
     * @param fields 初始字段
     * @param version 初始版本
     * @param guardKey 守卫状态键
     * @param guardVersion 期望守卫版本
     * @param ttl 有效期
     * @return 创建成功时为 {@code true}
     */
    default boolean createFieldsIfAbsent(String key,
                                         Map<String, ? extends Serializable> fields,
                                         long version,
                                         String guardKey,
                                         long guardVersion,
                                         Duration ttl) {
        throw new UnsupportedOperationException("Field storage is not supported");
    }

    /**
     * 两个守卫版本均匹配时原子创建字段化状态。
     *
     * @param key 存储键
     * @param fields 初始字段
     * @param version 初始版本
     * @param guardKey 第一守卫键
     * @param guardVersion 第一守卫版本
     * @param secondaryGuardKey 第二守卫键
     * @param secondaryGuardVersion 第二守卫版本
     * @param ttl 有效期
     * @return 创建成功时为 {@code true}
     */
    default boolean createFieldsIfAbsent(
            String key,
            Map<String, ? extends Serializable> fields,
            long version,
            String guardKey,
            long guardVersion,
            String secondaryGuardKey,
            long secondaryGuardVersion,
            Duration ttl) {
        return createFieldsIfAbsent(key, fields, version, guardKey, guardVersion, ttl);
    }

    /**
     * 三个守卫版本均匹配时原子创建字段化状态。
     *
     * @param key 存储键
     * @param fields 初始字段
     * @param version 初始版本
     * @param guardKey 第一守卫键
     * @param guardVersion 第一守卫版本
     * @param secondaryGuardKey 第二守卫键
     * @param secondaryGuardVersion 第二守卫版本
     * @param tertiaryGuardKey 第三守卫键
     * @param tertiaryGuardVersion 第三守卫版本
     * @param ttl 有效期
     * @return 创建成功时为 {@code true}
     */
    default boolean createFieldsIfAbsent(
            String key,
            Map<String, ? extends Serializable> fields,
            long version,
            String guardKey,
            long guardVersion,
            String secondaryGuardKey,
            long secondaryGuardVersion,
            String tertiaryGuardKey,
            long tertiaryGuardVersion,
            Duration ttl) {
        return createFieldsIfAbsent(
                key,
                fields,
                version,
                guardKey,
                guardVersion,
                secondaryGuardKey,
                secondaryGuardVersion,
                ttl);
    }

    /**
     * 原子比较版本并仅提交变化字段。
     *
     * @param key 存储键
     * @param expectedVersion 期望版本
     * @param fields 变化字段
     * @param newVersion 新版本
     * @param ttl 有效期
     * @return 更新成功时为 {@code true}
     */
    default boolean compareAndSetFields(String key,
                                        long expectedVersion,
                                        Map<String, ? extends Serializable> fields,
                                        long newVersion,
                                        Duration ttl) {
        throw new UnsupportedOperationException("Field storage is not supported");
    }

    /**
     * 两个守卫版本均匹配时原子提交变化字段。
     *
     * @param key 存储键
     * @param expectedVersion 当前对象期望版本
     * @param fields 变化字段
     * @param newVersion 新版本
     * @param guardKey 第一守卫键
     * @param guardVersion 第一守卫版本
     * @param secondaryGuardKey 第二守卫键
     * @param secondaryGuardVersion 第二守卫版本
     * @param ttl 有效期
     * @return 提交成功时为 {@code true}
     */
    default boolean compareAndSetFields(
            String key,
            long expectedVersion,
            Map<String, ? extends Serializable> fields,
            long newVersion,
            String guardKey,
            long guardVersion,
            String secondaryGuardKey,
            long secondaryGuardVersion,
            Duration ttl) {
        return compareAndSetFields(
                key, expectedVersion, fields, newVersion, guardKey, guardVersion, ttl);
    }

    /**
     * 三个守卫版本均匹配时原子提交变化字段。
     *
     * @param key 存储键
     * @param expectedVersion 当前对象期望版本
     * @param fields 变化字段
     * @param newVersion 新版本
     * @param guardKey 第一守卫键
     * @param guardVersion 第一守卫版本
     * @param secondaryGuardKey 第二守卫键
     * @param secondaryGuardVersion 第二守卫版本
     * @param tertiaryGuardKey 第三守卫键
     * @param tertiaryGuardVersion 第三守卫版本
     * @param ttl 有效期
     * @return 提交成功时为 {@code true}
     */
    default boolean compareAndSetFields(
            String key,
            long expectedVersion,
            Map<String, ? extends Serializable> fields,
            long newVersion,
            String guardKey,
            long guardVersion,
            String secondaryGuardKey,
            long secondaryGuardVersion,
            String tertiaryGuardKey,
            long tertiaryGuardVersion,
            Duration ttl) {
        return compareAndSetFields(
                key,
                expectedVersion,
                fields,
                newVersion,
                guardKey,
                guardVersion,
                secondaryGuardKey,
                secondaryGuardVersion,
                ttl);
    }

    /**
     * 两个守卫版本均匹配时提交字段，并在同一原子操作中刷新关联键有效期。
     *
     * @param key 存储键
     * @param expectedVersion 当前对象期望版本
     * @param fields 变化字段
     * @param newVersion 新版本
     * @param guardKey 第一守卫键
     * @param guardVersion 第一守卫版本
     * @param secondaryGuardKey 第二守卫键
     * @param secondaryGuardVersion 第二守卫版本
     * @param ttl 有效期
     * @param refreshKey 需要刷新有效期的关联键
     * @param refreshTtl 关联键有效期
     * @return 提交成功时为 {@code true}
     */
    default boolean compareAndSetFieldsAndRefresh(
            String key,
            long expectedVersion,
            Map<String, ? extends Serializable> fields,
            long newVersion,
            String guardKey,
            long guardVersion,
            String secondaryGuardKey,
            long secondaryGuardVersion,
            Duration ttl,
            String refreshKey,
            Duration refreshTtl) {
        return compareAndSetFields(
                key,
                expectedVersion,
                fields,
                newVersion,
                guardKey,
                guardVersion,
                secondaryGuardKey,
                secondaryGuardVersion,
                ttl);
    }

    /**
     * 守卫版本匹配时原子比较版本并仅提交变化字段。
     *
     * @param key 存储键
     * @param expectedVersion 期望版本
     * @param fields 变化字段
     * @param newVersion 新版本
     * @param guardKey 守卫状态键
     * @param guardVersion 期望守卫版本
     * @param ttl 有效期
     * @return 更新成功时为 {@code true}
     */
    default boolean compareAndSetFields(String key,
                                        long expectedVersion,
                                        Map<String, ? extends Serializable> fields,
                                        long newVersion,
                                        String guardKey,
                                        long guardVersion,
                                        Duration ttl) {
        throw new UnsupportedOperationException("Field storage is not supported");
    }

    /**
     * 将同版本完整对象原子改写为字段化状态。
     *
     * @param key 存储键
     * @param expectedVersion 期望版本
     * @param fields 完整字段
     * @param ttl 有效期
     * @return 改写成功时为 {@code true}
     */
    default boolean rewriteAsFields(String key,
                                    long expectedVersion,
                                    Map<String, ? extends Serializable> fields,
                                    Duration ttl) {
        throw new UnsupportedOperationException("Field storage is not supported");
    }
}
