package kr.co.accura.wbx.spring.notification;

import kr.co.accura.wbx.spring.config.WbxSpringProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.util.Map;
import java.util.concurrent.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class SseNotificationService {

    private final Map<Long, SseEmitter> emitters = new ConcurrentHashMap<>();
    private final WbxSpringProperties props;
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

    /**
     * SSE 연결 생성 (브라우저 EventSource)
     */
    public SseEmitter connect(Long userId) {
        SseEmitter emitter = new SseEmitter(3600_000L); // 1 hour
        emitters.put(userId, emitter);

        emitter.onCompletion(() -> emitters.remove(userId));
        emitter.onTimeout(() -> emitters.remove(userId));
        emitter.onError(e -> emitters.remove(userId));

        // Heartbeat
        int heartbeat = props.getNotification().getHeartbeatSeconds();
        ScheduledFuture<?> heartbeatTask = scheduler.scheduleAtFixedRate(() -> {
            try {
                emitter.send(SseEmitter.event().name("heartbeat").data(""));
            } catch (Exception e) {
                emitters.remove(userId);
            }
        }, heartbeat, heartbeat, TimeUnit.SECONDS);

        emitter.onCompletion(() -> heartbeatTask.cancel(true));
        emitter.onTimeout(() -> heartbeatTask.cancel(true));

        return emitter;
    }

    /**
     * 특정 사용자에게 알림 전송
     */
    public void sendToUser(Long userId, NotificationDto notification) {
        SseEmitter emitter = emitters.get(userId);
        if (emitter != null) {
            try {
                emitter.send(SseEmitter.event()
                        .name("notification")
                        .data(notification));
            } catch (Exception e) {
                emitters.remove(userId);
                log.debug("SSE send failed for user {}: {}", userId, e.getMessage());
            }
        }
    }

    public int getActiveConnections() {
        return emitters.size();
    }
}
