package tech.easyflow.ai.config;

import org.junit.Assert;
import org.junit.Test;
import org.springframework.boot.actuate.health.Health;

import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 健康检查短缓存测试。
 */
public class CachedHealthIndicatorSupportTest {

    /**
     * 验证 TTL 内重复健康检查复用缓存。
     */
    @Test
    public void shouldReuseHealthWithinCacheTtl() {
        RagHealthProperties properties = new RagHealthProperties();
        properties.setCacheTtl(Duration.ofSeconds(5));
        MutableClock clock = new MutableClock();
        CountingHealthIndicator indicator = new CountingHealthIndicator(properties, clock);

        indicator.cachedHealth();
        indicator.cachedHealth();

        Assert.assertEquals(1, indicator.count());
    }

    /**
     * 验证 TTL 过期后重新执行健康检查。
     */
    @Test
    public void shouldRefreshHealthAfterCacheExpired() {
        RagHealthProperties properties = new RagHealthProperties();
        properties.setCacheTtl(Duration.ofSeconds(5));
        MutableClock clock = new MutableClock();
        CountingHealthIndicator indicator = new CountingHealthIndicator(properties, clock);

        indicator.cachedHealth();
        clock.plus(Duration.ofSeconds(6));
        indicator.cachedHealth();

        Assert.assertEquals(2, indicator.count());
    }

    private static class CountingHealthIndicator extends CachedHealthIndicatorSupport {

        private final AtomicInteger counter = new AtomicInteger();

        private CountingHealthIndicator(RagHealthProperties properties, Clock clock) {
            super(properties, clock);
        }

        @Override
        protected Health doHealthCheck() {
            counter.incrementAndGet();
            return Health.up().build();
        }

        private int count() {
            return counter.get();
        }
    }

    private static class MutableClock extends Clock {

        private Instant instant = Instant.parse("2026-05-25T00:00:00Z");

        @Override
        public ZoneId getZone() {
            return ZoneId.of("UTC");
        }

        @Override
        public Clock withZone(ZoneId zone) {
            return this;
        }

        @Override
        public Instant instant() {
            return instant;
        }

        private void plus(Duration duration) {
            instant = instant.plus(duration);
        }
    }
}
