package study.springcaps;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Component;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * U49 JMX 教学模型：缓存状态通过注解暴露到 MBeanServer。
 * 只写字段不加 @ManagedAttribute 的成员不会出现在 MBeanInfo 中——这是本票第一条断言。
 */
@Component
@ManagedResource(objectName = "study.springcaps:name=cacheStats,type=CacheStats",
        description = "U49 教学缓存统计")
public class CacheStats implements AutoCloseable {

    private final AtomicInteger hits = new AtomicInteger();
    private final AtomicInteger misses = new AtomicInteger();
    private final AtomicLong evictions = new AtomicLong();
    private volatile boolean closed;

    @ManagedAttribute(description = "命中次数")
    public int getHits() {
        return hits.get();
    }

    @ManagedAttribute(description = "未命中次数")
    public int getMisses() {
        return misses.get();
    }

    @ManagedAttribute(description = "逐出次数（只读暴露内部字段）")
    public long getEvictions() {
        return evictions.get();
    }

    /** 没有 @ManagedAttribute：不应出现在 MBeanInfo。 */
    public int getHiddenField() {
        return 42;
    }

    @ManagedOperation(description = "把命中/未命中清零，返回清零前的和")
    public int resetCounters() {
        int h = hits.getAndSet(0);
        int m = misses.getAndSet(0);
        return h + m;
    }

    public void recordHit() {
        hits.incrementAndGet();
    }

    public void recordMiss() {
        misses.incrementAndGet();
    }

    public void recordEviction() {
        evictions.incrementAndGet();
    }

    @PostConstruct
    public void start() {
        closed = false;
    }

    @PreDestroy
    @Override
    public void close() {
        closed = true;
    }

    public boolean isClosed() {
        return closed;
    }
}
