// Server-Sent Events notification hub
// In-memory map of userId → Set of writable stream controllers

type SSEClient = {
    id: string;
    controller: ReadableStreamDefaultController;
    userId: string;
};

const clients = new Map<string, Set<SSEClient>>();

export function addClient(userId: string, controller: ReadableStreamDefaultController): SSEClient {
    const client: SSEClient = {
        id: Math.random().toString(36).slice(2),
        controller,
        userId,
    };
    if (!clients.has(userId)) {
        clients.set(userId, new Set());
    }
    clients.get(userId)!.add(client);
    return client;
}

export function removeClient(client: SSEClient) {
    const userClients = clients.get(client.userId);
    if (userClients) {
        userClients.delete(client);
        if (userClients.size === 0) {
            clients.delete(client.userId);
        }
    }
}

export type SSEEventType = "task-created" | "task-updated" | "task-deleted" | "tasks-changed" | "list-changed" | "profile-changed";

export function notifyUser(userId: string, event: SSEEventType, data?: any) {
    const userClients = clients.get(userId);
    if (!userClients || userClients.size === 0) return;

    const payload = `event: ${event}\ndata: ${JSON.stringify(data || {})}\n\n`;
    const encoder = new TextEncoder();
    const encoded = encoder.encode(payload);

    for (const client of userClients) {
        try {
            client.controller.enqueue(encoded);
        } catch {
            // Client disconnected, clean up
            removeClient(client);
        }
    }
}

export function getClientCount(userId?: string): number {
    if (userId) {
        return clients.get(userId)?.size || 0;
    }
    let total = 0;
    for (const set of clients.values()) {
        total += set.size;
    }
    return total;
}
