import { Injectable, Logger } from "@nestjs/common";
import { Subject } from "rxjs";
import { NotificationCard } from "./notification.types";

@Injectable()
export class NotificationsService {
    private readonly logger = new Logger(NotificationsService.name);

    //Server-Sent Events FLUX and a buffer per user
    private streams = new Map<string, Subject<NotificationCard>>();
    private buffers = new Map<string, NotificationCard[]>();
    private readonly BUFFER_MAX = Number(process.env.NOTIF_BUFFER_MAX ?? 50);

    private getOrCreateStream(user_id: string): Subject<NotificationCard> {
        let stream = this.streams.get(user_id);
        if (!stream){
            stream = new Subject<NotificationCard>();
             this.streams.set(user_id, stream);
        }
        return stream;
    }
    private getOrCreateBuffer(user_id: string){
        let buffer = this.buffers.get(user_id);
        if(!buffer) { 
            buffer = [];
            this.buffers.set(user_id, buffer);
        }
        return buffer;  
    }

    //in-app pushes and keep a small history
    notify(user_id: string, card: NotificationCard) {
        const buffer = this.getOrCreateBuffer(user_id);
        buffer.unshift(card);
        if (buffer.length > this.BUFFER_MAX) {
            buffer.length = this.BUFFER_MAX;
        }
        this.getOrCreateStream(user_id).next(card);
        this.logger.debug(`Notification in-app => user: ${user_id} (${card.type})`);
    }

    //SSE flux for current user
    stream(user_id: string) {
        return this.getOrCreateStream(user_id).asObservable();
    }

    //return a summary of notifications kept in memory
    async summary(user_id: string): Promise<NotificationCard[]> {
        return this.getOrCreateBuffer(user_id);
    }

    //clear buffers from memory
    clear(user_id: string) {
        this.buffers.set(user_id, []);
    }

    onModuleDestroy() {
        for (const stream of this.streams.values()) stream.complete();
        this.streams.clear();
        this.buffers.clear();
    }
}