package com.example.sse.core;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

@Component
public class SseChannelBus {

    // 채널ID -> 구독자 리스트
    private final Map<String, CopyOnWriteArrayList<SseEmitter>> subscribers = new ConcurrentHashMap<>();

    public SseEmitter subscribe(String channelId, Long timeoutMs) {
        SseEmitter emitter = new SseEmitter(timeoutMs);

        //channelId가 없으면 새 리스트를 만들어 넣고, 있으면 기존 리스트를 반환
        CopyOnWriteArrayList<SseEmitter> list =
                subscribers.computeIfAbsent(channelId, k -> new CopyOnWriteArrayList<SseEmitter>());

        list.add(emitter);

        // 연결 종료/에러 시 구독 해제
        emitter.onCompletion(() -> list.remove(emitter));
        emitter.onTimeout(() -> {
            emitter.complete();
            list.remove(emitter);
        });
        emitter.onError(ex -> {
            emitter.complete();
            list.remove(emitter);
        });

        // 연결 직후 더미 메시지
        try {
            emitter.send(SseEmitter.event()
                    .name("connected")
                    .data("subscribed channel=" + channelId));
        } catch (IOException ignored) {}

        return emitter;
    }

    public void publish(String channelId, String line) {
        CopyOnWriteArrayList<SseEmitter> list = subscribers.get(channelId);
        if (list == null || list.isEmpty()) return;

        for (SseEmitter emitter : list) {
            try {
                emitter.send(SseEmitter.event()
                        .name("channel-log")
                        .data(line)); // data는 문자열 한 줄
            } catch (IOException e) {
                emitter.complete();
                list.remove(emitter);
            }
        }
    }

}
