package gc.mda.signal_batch.global.config;

import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;

/**
 * Caffeine Cache 설정
 *
 * 용도: 선박 최신 위치 정보를 메모리에 캐싱하여 DB 부하 감소 및 실시간성 향상
 *
 * 특징:
 * - 최대 60분간 캐시 보관 (TTL)
 * - API 요청 시 minutes 파라미터로 동적 필터링
 * - 1분마다 자동 갱신 (VesselPositionCacheRefreshScheduler)
 */
@Slf4j
@Configuration
@EnableCaching
public class CacheConfig {

    @Value("${vessel.batch.cache.latest-position.ttl-minutes:60}")
    private int cacheTtlMinutes;

    @Value("${vessel.batch.cache.latest-position.max-size:50000}")
    private int cacheMaxSize;

    @Value("${vessel.batch.cache.previous-bucket.ttl-minutes:120}")
    private int previousBucketTtlMinutes;

    @Value("${vessel.batch.cache.previous-bucket.max-size:50000}")
    private int previousBucketMaxSize;

    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();

        // 1. vesselLatestPositions 캐시 (최신 위치 API용)
        cacheManager.registerCustomCache("vesselLatestPositions",
            latestPositionCacheBuilder().build());

        // 2. vesselPreviousBuckets 캐시 (버킷 점프 검출용)
        cacheManager.registerCustomCache("vesselPreviousBuckets",
            previousBucketCacheBuilder().build());

        log.info("Initialized Caffeine CacheManager:");
        log.info("  - vesselLatestPositions: TTL={}min, MaxSize={}", cacheTtlMinutes, cacheMaxSize);
        log.info("  - vesselPreviousBuckets: TTL={}min, MaxSize={}", previousBucketTtlMinutes, previousBucketMaxSize);

        return cacheManager;
    }

    /**
     * 최신 위치 캐시 빌더 (API 응답용)
     */
    private Caffeine<Object, Object> latestPositionCacheBuilder() {
        return Caffeine.newBuilder()
                // TTL: 마지막 접근 후 60분 (읽기/쓰기 시 리셋)
                // - 활성 선박: API 조회 또는 스케줄러 갱신 → TTL 계속 리셋
                // - 비활성 선박: 60분 미접근 → 자동 제거
                .expireAfterAccess(cacheTtlMinutes, TimeUnit.MINUTES)

                // 최대 선박 수 제한 (메모리 보호)
                .maximumSize(cacheMaxSize)

                // 통계 수집 활성화 (모니터링용)
                .recordStats()

                // 초기 용량 설정 (rehashing 최소화)
                .initialCapacity(1000);
    }

    /**
     * 이전 버킷 위치 캐시 빌더 (버킷 점프 검출용)
     */
    private Caffeine<Object, Object> previousBucketCacheBuilder() {
        return Caffeine.newBuilder()
                // TTL: 마지막 접근 후 120분 (읽기/쓰기 시 리셋)
                // - 활성 선박: 5분마다 접근 → TTL 계속 갱신 → 영구 유지
                // - 비활성 선박: 120분 미접근 → 자동 제거
                .expireAfterAccess(previousBucketTtlMinutes, TimeUnit.MINUTES)

                // 최대 선박 수 제한
                .maximumSize(previousBucketMaxSize)

                // 통계 수집 활성화
                .recordStats()

                // 초기 용량 설정
                .initialCapacity(1000);
    }
}
