package tech.easyflow.ai.config;

import org.springframework.boot.actuate.health.Health;

import java.time.Clock;
import java.time.Duration;

/**
 * 健康检查短缓存支持。
 */
public abstract class CachedHealthIndicatorSupport {

    private final RagHealthProperties properties;
    private final Clock clock;
    private volatile CacheEntry cacheEntry;

    /**
     * 创建健康检查缓存支持。
     *
     * @param properties RAG 健康检查配置
     */
    protected CachedHealthIndicatorSupport(RagHealthProperties properties) {
        this(properties, Clock.systemUTC());
    }

    /**
     * 创建健康检查缓存支持。
     *
     * @param properties RAG 健康检查配置
     * @param clock 时钟
     */
    protected CachedHealthIndicatorSupport(RagHealthProperties properties, Clock clock) {
        this.properties = properties;
        this.clock = clock;
    }

    /**
     * 执行带短缓存的健康检查。
     *
     * @return 健康状态
     */
    protected Health cachedHealth() {
        long now = clock.millis();
        CacheEntry current = cacheEntry;
        if (current != null && current.expireAtMillis > now) {
            return current.health;
        }
        synchronized (this) {
            current = cacheEntry;
            if (current != null && current.expireAtMillis > now) {
                return current.health;
            }
            Health health = doHealthCheck();
            cacheEntry = new CacheEntry(health, now + cacheTtlMillis());
            return health;
        }
    }

    /**
     * 执行实际健康检查。
     *
     * @return 健康状态
     */
    protected abstract Health doHealthCheck();

    private long cacheTtlMillis() {
        Duration cacheTtl = properties.getCacheTtl();
        if (cacheTtl == null || cacheTtl.isZero() || cacheTtl.isNegative()) {
            return 0L;
        }
        return cacheTtl.toMillis();
    }

    private static class CacheEntry {

        private final Health health;
        private final long expireAtMillis;

        private CacheEntry(Health health, long expireAtMillis) {
            this.health = health;
            this.expireAtMillis = expireAtMillis;
        }
    }
}
