// Package handlers provides HTTP handlers for the rdev API.
package handlers

import (
	"encoding/json"
	"fmt"
	"net/http"
	"sync"
)

// streamManager manages SSE event streams.
type streamManager struct {
	mu      sync.RWMutex
	streams map[string][]chan streamEvent
}

type streamEvent struct {
	Type string
	Data map[string]any
}

func newStreamManager() *streamManager {
	return &streamManager{
		streams: make(map[string][]chan streamEvent),
	}
}

func (sm *streamManager) Subscribe(streamID string) chan streamEvent {
	sm.mu.Lock()
	defer sm.mu.Unlock()

	ch := make(chan streamEvent, 100)
	sm.streams[streamID] = append(sm.streams[streamID], ch)
	return ch
}

func (sm *streamManager) Unsubscribe(streamID string, ch chan streamEvent) {
	sm.mu.Lock()
	defer sm.mu.Unlock()

	channels := sm.streams[streamID]
	for i, c := range channels {
		if c == ch {
			sm.streams[streamID] = append(channels[:i], channels[i+1:]...)
			close(ch)
			break
		}
	}
}

func (sm *streamManager) Send(streamID, eventType string, data map[string]any) {
	sm.mu.RLock()
	defer sm.mu.RUnlock()

	for _, ch := range sm.streams[streamID] {
		select {
		case ch <- streamEvent{Type: eventType, Data: data}:
		default:
			// Channel full, skip
		}
	}
}

func (sm *streamManager) Close(streamID string) {
	sm.mu.Lock()
	defer sm.mu.Unlock()

	for _, ch := range sm.streams[streamID] {
		close(ch)
	}
	delete(sm.streams, streamID)
}

// writeSSE writes a Server-Sent Event.
func writeSSE(w http.ResponseWriter, flusher http.Flusher, event string, data map[string]any) {
	writeSSEWithID(w, flusher, "", event, data)
}

// writeSSEWithID writes a Server-Sent Event with an optional event ID.
func writeSSEWithID(w http.ResponseWriter, flusher http.Flusher, id, event string, data map[string]any) {
	dataBytes, _ := json.Marshal(data)
	if id != "" {
		_, _ = fmt.Fprintf(w, "id: %s\n", id)
	}
	_, _ = fmt.Fprintf(w, "event: %s\n", event)
	_, _ = fmt.Fprintf(w, "data: %s\n\n", dataBytes)
	flusher.Flush()
}
