import Database from 'better-sqlite3';
import { join } from 'node:path';
import { existsSync, mkdirSync, chmodSync } from 'node:fs';
export class NotificationService {
    db;
    constructor(workspacePath) {
        const sgDir = join(workspacePath, '.studiograph');
        if (!existsSync(sgDir))
            mkdirSync(sgDir, { recursive: true });
        const dbPath = join(sgDir, 'notifications.db');
        this.db = new Database(dbPath);
        if (process.platform !== 'win32') {
            try {
                chmodSync(dbPath, 0o600);
            }
            catch { /* non-fatal */ }
        }
        this.db.pragma('journal_mode = WAL');
        this.db.exec(`
      CREATE TABLE IF NOT EXISTS notifications (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        user_id INTEGER NOT NULL,
        source_type TEXT NOT NULL,
        source_id TEXT NOT NULL,
        mentioner_user_id INTEGER NOT NULL,
        mentioner_display_name TEXT NOT NULL,
        preview TEXT NOT NULL,
        read INTEGER NOT NULL DEFAULT 0 CHECK(read IN (0, 1)),
        created_at TEXT NOT NULL DEFAULT (datetime('now'))
      )
    `);
        this.db.exec(`
      CREATE INDEX IF NOT EXISTS idx_notifications_user
        ON notifications(user_id, read, id DESC)
    `);
    }
    /** Insert a notification and return the new id. */
    insert(input) {
        const stmt = this.db.prepare(`
      INSERT INTO notifications
        (user_id, source_type, source_id, mentioner_user_id, mentioner_display_name, preview)
      VALUES (?, ?, ?, ?, ?, ?)
    `);
        const result = stmt.run(input.userId, input.sourceType, input.sourceId, input.mentionerUserId, input.mentionerDisplayName, input.preview.length > 200 ? input.preview.slice(0, 200) : input.preview);
        return result.lastInsertRowid;
    }
    list(userId, opts = {}) {
        const limit = Math.min(opts.limit ?? 50, 200);
        const filter = opts.unreadOnly ? 'AND read = 0' : '';
        const rows = this.db.prepare(`
      SELECT id, user_id, source_type, source_id, mentioner_user_id,
             mentioner_display_name, preview, read, created_at
      FROM notifications
      WHERE user_id = ? ${filter}
      ORDER BY id DESC
      LIMIT ?
    `).all(userId, limit);
        return rows.map(this.toNotification);
    }
    unreadCount(userId) {
        const row = this.db.prepare(`
      SELECT COUNT(*) AS c FROM notifications WHERE user_id = ? AND read = 0
    `).get(userId);
        return row.c;
    }
    markRead(notificationId, userId) {
        const result = this.db.prepare(`
      UPDATE notifications SET read = 1 WHERE id = ? AND user_id = ?
    `).run(notificationId, userId);
        return result.changes > 0;
    }
    markAllRead(userId) {
        const result = this.db.prepare(`
      UPDATE notifications SET read = 1 WHERE user_id = ? AND read = 0
    `).run(userId);
        return result.changes;
    }
    /** Remove all notifications referencing a given source (used when a comment is hard-deleted). */
    deleteBySource(sourceType, sourceId) {
        const result = this.db.prepare(`
      DELETE FROM notifications WHERE source_type = ? AND source_id = ?
    `).run(sourceType, sourceId);
        return result.changes;
    }
    close() {
        this.db.close();
    }
    toNotification = (row) => ({
        id: row.id,
        userId: row.user_id,
        sourceType: row.source_type,
        sourceId: row.source_id,
        mentionerUserId: row.mentioner_user_id,
        mentionerDisplayName: row.mentioner_display_name,
        preview: row.preview,
        read: row.read === 1 ? 1 : 0,
        createdAt: row.created_at,
    });
}
//# sourceMappingURL=notification-service.js.map