package com.kt.event.analytics.batch;

import com.kt.event.analytics.entity.EventStats;
import com.kt.event.analytics.repository.EventStatsRepository;
import com.kt.event.analytics.service.AnalyticsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;

/**
 * Analytics 배치 스케줄러
 *
 * 5분 단위로 Analytics 대시보드 데이터를 갱신하는 배치 작업
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AnalyticsBatchScheduler {

    private final AnalyticsService analyticsService;
    private final EventStatsRepository eventStatsRepository;
    private final RedisTemplate<String, String> redisTemplate;

    /**
     * 5분 단위 Analytics 데이터 갱신 배치
     *
     * - 각 이벤트마다 Redis 캐시 확인
     * - 캐시 있음 → 건너뛰기 (1시간 유효)
     * - 캐시 없음 → PostgreSQL + 외부 API → Redis 저장
     */
    @Scheduled(fixedRate = 300000) // 5분 = 300,000ms
    public void refreshAnalyticsDashboard() {
        log.info("===== Analytics 배치 시작: {} =====", LocalDateTime.now());

        try {
            // 1. 모든 활성 이벤트 조회
            List<EventStats> activeEvents = eventStatsRepository.findAll();
            log.info("활성 이벤트 수: {}", activeEvents.size());

            // 2. 각 이벤트별로 캐시 확인 및 갱신
            int successCount = 0;
            int skipCount = 0;
            int failCount = 0;

            for (EventStats event : activeEvents) {
                String cacheKey = "analytics:dashboard:" + event.getEventId();

                try {
                    // 2-1. Redis 캐시 확인
                    if (redisTemplate.hasKey(cacheKey)) {
                        log.debug("✅ 캐시 유효, 건너뜀: eventId={}", event.getEventId());
                        skipCount++;
                        continue;
                    }

                    // 2-2. 캐시 없음 → 데이터 갱신
                    log.info("캐시 만료, 갱신 시작: eventId={}, title={}",
                             event.getEventId(), event.getEventTitle());

                    // refresh=true로 호출하여 캐시 갱신 및 외부 API 호출
                    analyticsService.getDashboardData(event.getEventId(), true);

                    successCount++;
                    log.info("✅ 배치 갱신 완료: eventId={}", event.getEventId());

                } catch (Exception e) {
                    failCount++;
                    log.error("❌ 배치 갱신 실패: eventId={}, error={}",
                             event.getEventId(), e.getMessage(), e);
                }
            }

            log.info("===== Analytics 배치 완료: 성공={}, 건너뜀={}, 실패={}, 종료시각={} =====",
                    successCount, skipCount, failCount, LocalDateTime.now());

        } catch (Exception e) {
            log.error("Analytics 배치 실행 중 오류 발생: {}", e.getMessage(), e);
        }
    }

    /**
     * 초기 데이터 로딩 (애플리케이션 시작 후 30초 뒤 1회 실행)
     *
     * - 서버 시작 직후 캐시 워밍업
     * - 첫 API 요청 시 응답 시간 단축
     */
    @Scheduled(initialDelay = 30000, fixedDelay = Long.MAX_VALUE)
    public void initialDataLoad() {
        log.info("===== 초기 데이터 로딩 시작: {} =====", LocalDateTime.now());

        try {
            List<EventStats> allEvents = eventStatsRepository.findAll();
            log.info("초기 로딩 대상 이벤트 수: {}", allEvents.size());

            for (EventStats event : allEvents) {
                try {
                    analyticsService.getDashboardData(event.getEventId(), true);
                    log.debug("초기 데이터 로딩 완료: eventId={}", event.getEventId());
                } catch (Exception e) {
                    log.warn("초기 데이터 로딩 실패: eventId={}, error={}",
                            event.getEventId(), e.getMessage());
                }
            }

            log.info("===== 초기 데이터 로딩 완료: {} =====", LocalDateTime.now());

        } catch (Exception e) {
            log.error("초기 데이터 로딩 중 오류 발생: {}", e.getMessage(), e);
        }
    }
}
