package com.kt.ai.test.integration.kafka;

import com.kt.ai.kafka.message.AIJobMessage;
import com.kt.ai.service.CacheService;
import com.kt.ai.service.JobStatusService;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;

import java.util.concurrent.TimeUnit;

import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;

/**
 * AIJobConsumer Kafka 통합 테스트
 *
 * 실제 Kafka 브로커가 실행 중이어야 합니다.
 *
 * @author AI Service Team
 * @since 1.0.0
 */
@SpringBootTest
@ActiveProfiles("test")
@DisplayName("AIJobConsumer Kafka 통합 테스트")
class AIJobConsumerIntegrationTest {

    @Value("${spring.kafka.bootstrap-servers}")
    private String bootstrapServers;

    @Value("${kafka.topics.ai-job}")
    private String aiJobTopic;

    @Autowired
    private JobStatusService jobStatusService;

    @Autowired
    private CacheService cacheService;

    private KafkaTestProducer testProducer;

    @BeforeEach
    void setUp() {
        testProducer = new KafkaTestProducer(bootstrapServers, aiJobTopic);
    }

    @AfterEach
    void tearDown() {
        if (testProducer != null) {
            testProducer.close();
        }
    }

    @Test
    @DisplayName("Given valid AI job message, When send to Kafka, Then consumer processes and saves to Redis")
    void givenValidAIJobMessage_whenSendToKafka_thenConsumerProcessesAndSavesToRedis() {
        // Given
        String jobId = "test-job-" + System.currentTimeMillis();
        String eventId = "test-event-" + System.currentTimeMillis();
        AIJobMessage message = KafkaTestProducer.createSampleMessage(jobId, eventId);

        // When
        testProducer.sendAIJobMessage(message);

        // Then - Kafka Consumer가 메시지를 처리하고 Redis에 저장할 때까지 대기
        await()
                .atMost(30, TimeUnit.SECONDS)
                .pollInterval(1, TimeUnit.SECONDS)
                .untilAsserted(() -> {
                    // Job 상태가 Redis에 저장되었는지 확인
                    Object jobStatus = cacheService.getJobStatus(jobId);
                    assertThat(jobStatus).isNotNull();
                    System.out.println("Job 상태 확인: " + jobStatus);
                });

        // 최종 상태 확인 (COMPLETED 또는 FAILED)
        await()
                .atMost(60, TimeUnit.SECONDS)
                .pollInterval(2, TimeUnit.SECONDS)
                .untilAsserted(() -> {
                    Object jobStatus = cacheService.getJobStatus(jobId);
                    assertThat(jobStatus).isNotNull();

                    // AI 추천 결과도 저장되었는지 확인 (COMPLETED 상태인 경우)
                    Object recommendation = cacheService.getRecommendation(eventId);
                    System.out.println("AI 추천 결과: " + (recommendation != null ? "있음" : "없음"));
                });
    }

    @Test
    @DisplayName("Given multiple messages, When send to Kafka, Then all messages are processed")
    void givenMultipleMessages_whenSendToKafka_thenAllMessagesAreProcessed() {
        // Given
        int messageCount = 3;
        String[] jobIds = new String[messageCount];
        String[] eventIds = new String[messageCount];

        // When - 여러 메시지 전송
        for (int i = 0; i < messageCount; i++) {
            jobIds[i] = "batch-job-" + i + "-" + System.currentTimeMillis();
            eventIds[i] = "batch-event-" + i + "-" + System.currentTimeMillis();
            AIJobMessage message = KafkaTestProducer.createSampleMessage(jobIds[i], eventIds[i]);
            testProducer.sendAIJobMessage(message);
        }

        // Then - 모든 메시지가 처리되었는지 확인
        await()
                .atMost(90, TimeUnit.SECONDS)
                .pollInterval(2, TimeUnit.SECONDS)
                .untilAsserted(() -> {
                    int processedCount = 0;
                    for (int i = 0; i < messageCount; i++) {
                        Object jobStatus = cacheService.getJobStatus(jobIds[i]);
                        if (jobStatus != null) {
                            processedCount++;
                        }
                    }
                    assertThat(processedCount).isEqualTo(messageCount);
                    System.out.println("처리된 메시지 수: " + processedCount + "/" + messageCount);
                });
    }
}
