package com.example.sse.config;

import com.example.sse.core.ChannelIdParser;
import com.example.sse.core.SseChannelBus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.file.tail.ApacheCommonsFileTailingMessageProducer;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.io.File;

@Configuration
public class LogFileMonitorConfig {

    private static final String LOG_PATH = "C:/Projects/labs/logs/monitor/channel.log"; // 로그파일 경로

    /** 로그 읽기용 채널 정의 */
    @Bean
    public MessageChannel logInputChannel() {
        return new DirectChannel();
    }

    /** Tail 모듈을 이용한 로그 감시 */
    @Bean
    public ApacheCommonsFileTailingMessageProducer tailAdapter(MessageChannel logInputChannel, TaskExecutor tailExecutor) {
        ApacheCommonsFileTailingMessageProducer adapter = new ApacheCommonsFileTailingMessageProducer();
        File file = new File(LOG_PATH);

        System.out.println("[TAIL] Watching file: " + file.getAbsolutePath()); // 경로 확인용

        adapter.setTaskExecutor(tailExecutor);
        adapter.setFile(file); // 실제 로그 파일 경로
        adapter.setOutputChannel(logInputChannel);  // 빈 주입
        adapter.setTailAttemptsDelay(1000);
        adapter.setReopen(true);  // 로그 로테이션 대응
        adapter.setEnd(true);    // true: 파일 끝부터 tail 시작 / false: 파일 처음부터 read

        adapter.setIdleEventInterval(5000L);      // 상태 확인용 (옵션)

        return adapter;
    }

    /** 라인 처리 핸들러: 채널ID 추출 후 SSE publish */
    @Bean
    @ServiceActivator(inputChannel = "logInputChannel")
    public MessageHandler handleLogLines(SseChannelBus bus) {
        return message -> {
            String line = (String) message.getPayload();
            if (line.isEmpty()) return;

            // IDLE 이벤트 등 상태 메시지 필터 (옵션)
            if (line.startsWith("IDLE")) {
                System.out.println("[TAIL] idle event: " + line);
                return;
            }

            String channelId = ChannelIdParser.extractChannelId(line); // 예: "[0015]" → "0015" 그대로
            if (channelId != null) {
                bus.publish(channelId, line);
            } else {
                System.out.println("[TAIL] no channelId: " + line);
            }
        };
    }

    @Bean(name = "tailExecutor", destroyMethod = "shutdown")
    public ThreadPoolTaskExecutor tailExecutor() {
        ThreadPoolTaskExecutor ex = new ThreadPoolTaskExecutor();
        ex.setThreadNamePrefix("tail-");
        // tail은 '장기 실행' 작업이므로 core=max, queue는 0(또는 아주 작게) 권장
        ex.setCorePoolSize(4);    // 동시에 허용할 tail 작업 수
        ex.setMaxPoolSize(4);
        ex.setQueueCapacity(0);   // 풀 가득 찼을 때 바로 거부(실패 감지 용이)
        ex.setWaitForTasksToCompleteOnShutdown(true);
        ex.initialize();
        return ex;
    }
}
