package gc.mda.signal_batch.monitoring.controller;

import gc.mda.signal_batch.domain.vessel.service.VesselLatestPositionCache;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * 캐시 모니터링 컨트롤러
 *
 * 엔드포인트:
 * - GET /api/monitoring/cache/stats : 캐시 통계 조회
 * - POST /api/monitoring/cache/clear : 캐시 강제 초기화
 */
@Slf4j
@RestController
@RequestMapping("/api/monitoring/cache")
@RequiredArgsConstructor
@Tag(name = "Cache Monitoring", description = "캐시 모니터링 API")
@ConditionalOnProperty(name = "vessel.cache.latest-position.enabled", havingValue = "true")
public class CacheMonitoringController {

    @Autowired(required = false)
    private VesselLatestPositionCache cache;

    /**
     * 캐시 통계 조회
     */
    @GetMapping("/stats")
    @Operation(summary = "캐시 통계 조회", description = "Vessel Latest Position 캐시의 통계 정보를 조회합니다.")
    public ResponseEntity<Map<String, Object>> getCacheStats() {
        if (cache == null) {
            return ResponseEntity.ok(Map.of(
                    "enabled", false,
                    "message", "Cache is not enabled"
            ));
        }

        try {
            VesselLatestPositionCache.CacheStats stats = cache.getStats();

            Map<String, Object> response = new HashMap<>();
            response.put("enabled", true);
            response.put("currentSize", stats.currentSize());
            response.put("estimatedSize", stats.estimatedSize());
            response.put("hitRate", String.format("%.2f%%", stats.hitRate()));
            response.put("missRate", String.format("%.2f%%", stats.missRate()));
            response.put("hitCount", stats.hitCount());
            response.put("missCount", stats.missCount());
            response.put("totalRequests", stats.hitCount() + stats.missCount());

            // 효율성 평가
            double efficiency;
            long totalRequests = stats.hitCount() + stats.missCount();
            if (totalRequests > 0) {
                efficiency = (double) stats.hitCount() / totalRequests * 100;
            } else {
                efficiency = 0.0;
            }
            response.put("efficiency", String.format("%.2f%%", efficiency));

            // 상태 평가
            String status;
            if (stats.currentSize() == 0) {
                status = "EMPTY";
            } else if (efficiency > 90) {
                status = "EXCELLENT";
            } else if (efficiency > 70) {
                status = "GOOD";
            } else if (efficiency > 50) {
                status = "FAIR";
            } else {
                status = "POOR";
            }
            response.put("status", status);

            return ResponseEntity.ok(response);

        } catch (Exception e) {
            log.error("Failed to get cache stats", e);
            return ResponseEntity.internalServerError()
                    .body(Map.of("error", "Failed to get cache stats: " + e.getMessage()));
        }
    }

    /**
     * 캐시 강제 초기화 (주의: 운영 환경에서 신중하게 사용)
     */
    @PostMapping("/clear")
    @Operation(
            summary = "캐시 강제 초기화",
            description = "모든 캐시 데이터를 삭제합니다. 운영 환경에서는 신중하게 사용하세요."
    )
    public ResponseEntity<Map<String, Object>> clearCache() {
        if (cache == null) {
            return ResponseEntity.ok(Map.of(
                    "enabled", false,
                    "message", "Cache is not enabled"
            ));
        }

        try {
            VesselLatestPositionCache.CacheStats statsBefore = cache.getStats();
            cache.clear();
            VesselLatestPositionCache.CacheStats statsAfter = cache.getStats();

            log.warn("Cache manually cleared - before size: {}, after size: {}",
                    statsBefore.currentSize(), statsAfter.currentSize());

            return ResponseEntity.ok(Map.of(
                    "success", true,
                    "message", "Cache cleared successfully",
                    "clearedEntries", statsBefore.currentSize()
            ));

        } catch (Exception e) {
            log.error("Failed to clear cache", e);
            return ResponseEntity.internalServerError()
                    .body(Map.of("error", "Failed to clear cache: " + e.getMessage()));
        }
    }

    /**
     * 캐시 상태 체크 (헬스체크용)
     */
    @GetMapping("/health")
    @Operation(summary = "캐시 헬스체크", description = "캐시가 정상 작동 중인지 확인합니다.")
    public ResponseEntity<Map<String, Object>> checkCacheHealth() {
        Map<String, Object> health = new HashMap<>();

        if (cache == null) {
            health.put("status", "DISABLED");
            health.put("message", "Cache is not enabled");
            return ResponseEntity.ok(health);
        }

        try {
            VesselLatestPositionCache.CacheStats stats = cache.getStats();

            boolean isHealthy = stats.currentSize() >= 0; // 기본 체크

            health.put("status", isHealthy ? "UP" : "DOWN");
            health.put("cacheSize", stats.currentSize());
            health.put("healthy", isHealthy);

            // 경고 조건 체크
            if (stats.currentSize() == 0) {
                health.put("warning", "Cache is empty");
            }

            long totalRequests = stats.hitCount() + stats.missCount();
            if (totalRequests > 100 && stats.hitRate() < 50.0) {
                health.put("warning", "Low cache hit rate: " + String.format("%.2f%%", stats.hitRate()));
            }

            return ResponseEntity.ok(health);

        } catch (Exception e) {
            log.error("Cache health check failed", e);
            health.put("status", "ERROR");
            health.put("error", e.getMessage());
            return ResponseEntity.status(503).body(health);
        }
    }
}
