/**
 * User and Audit Log Operations for DatabaseService
 *
 * Provides CRUD operations for users and audit_log tables.
 * Users represent identity for multi-user collaboration.
 * Audit log tracks user actions for compliance and accountability.
 *
 * CRITICAL: NEVER use console.log() - stdout is reserved for JSON-RPC protocol.
 *
 * @module database/user-operations
 */
// ═══════════════════════════════════════════════════════════════════════════════
// USER AUTO-PROVISIONING
// ═══════════════════════════════════════════════════════════════════════════════
/**
 * Ensure a user exists in the users table, auto-provisioning if necessary.
 *
 * When an operation references a user_id via FK, we must ensure the user row
 * exists. If not found, we create a minimal user record with 'viewer' role.
 * This is proper user lifecycle management - users are created on first
 * reference rather than requiring explicit pre-registration.
 *
 * @param db - Database connection
 * @param userId - The user ID to ensure exists
 */
export function ensureUserExists(db, userId) {
    const exists = db.prepare('SELECT id FROM users WHERE id = ?').get(userId);
    if (!exists) {
        const now = new Date().toISOString();
        db.prepare(`INSERT INTO users (id, display_name, role, metadata_json, last_active_at, created_at)
       VALUES (?, ?, 'viewer', '{}', ?, ?)`).run(userId, userId, now, now);
    }
}
// ═══════════════════════════════════════════════════════════════════════════════
// USER CRUD
// ═══════════════════════════════════════════════════════════════════════════════
/**
 * Create a new user.
 * ID is auto-generated by SQLite (lower(hex(randomblob(16)))).
 *
 * @returns The created user record
 * @throws Error if external_id already exists (UNIQUE constraint)
 */
export function createUser(db, params) {
    const now = new Date().toISOString();
    try {
        const stmt = db.prepare(`
      INSERT INTO users (display_name, external_id, email, role, metadata_json, last_active_at)
      VALUES (?, ?, ?, ?, ?, ?)
    `);
        const result = stmt.run(params.display_name, params.external_id ?? null, params.email ?? null, params.role ?? 'viewer', params.metadata_json ?? '{}', now);
        // Retrieve the just-inserted user by rowid (safe under concurrent inserts)
        const user = db.prepare('SELECT * FROM users WHERE rowid = ?').get(result.lastInsertRowid);
        if (!user) {
            throw new Error('Failed to retrieve created user');
        }
        return user;
    }
    catch (error) {
        if (error instanceof Error && error.message.includes('UNIQUE constraint failed')) {
            throw new Error(`User with external_id "${params.external_id}" already exists`);
        }
        throw error;
    }
}
/**
 * Get a user by internal ID
 */
export function getUser(db, userId) {
    const row = db.prepare('SELECT * FROM users WHERE id = ?').get(userId);
    return row ?? null;
}
/**
 * Get a user by external ID
 */
export function getUserByExternalId(db, externalId) {
    const row = db.prepare('SELECT * FROM users WHERE external_id = ?').get(externalId);
    return row ?? null;
}
/**
 * Update the last_active_at timestamp for a user
 */
export function updateUserActivity(db, userId) {
    const now = new Date().toISOString();
    db.prepare('UPDATE users SET last_active_at = ? WHERE id = ?').run(now, userId);
}
/**
 * List users with optional filters
 */
export function listUsers(db, options) {
    const conditions = [];
    const params = [];
    if (options?.role) {
        conditions.push('role = ?');
        params.push(options.role);
    }
    const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
    const limit = options?.limit ?? 100;
    const offset = options?.offset ?? 0;
    params.push(limit, offset);
    return db
        .prepare(`SELECT * FROM users ${whereClause} ORDER BY created_at DESC LIMIT ? OFFSET ?`)
        .all(...params);
}
// ═══════════════════════════════════════════════════════════════════════════════
// AUDIT LOG
// ═══════════════════════════════════════════════════════════════════════════════
/**
 * Insert an entry into the audit log
 */
export function insertAuditLog(db, params) {
    const result = db
        .prepare(`INSERT INTO audit_log (user_id, session_id, action, entity_type, entity_id, details_json, ip_address)
       VALUES (?, ?, ?, ?, ?, ?, ?)`)
        .run(params.user_id, params.session_id, params.action, params.entity_type ?? null, params.entity_id ?? null, params.details_json ?? '{}', params.ip_address ?? null);
    return Number(result.lastInsertRowid);
}
/**
 * Query audit log with filters
 *
 * @returns Array of matching audit log entries, ordered by created_at DESC
 */
export function queryAuditLog(db, filters) {
    const conditions = [];
    const params = [];
    if (filters.user_id) {
        conditions.push('a.user_id = ?');
        params.push(filters.user_id);
    }
    if (filters.action) {
        conditions.push('a.action = ?');
        params.push(filters.action);
    }
    if (filters.entity_type) {
        conditions.push('a.entity_type = ?');
        params.push(filters.entity_type);
    }
    if (filters.entity_id) {
        conditions.push('a.entity_id = ?');
        params.push(filters.entity_id);
    }
    if (filters.date_from) {
        conditions.push('a.created_at >= ?');
        params.push(filters.date_from);
    }
    if (filters.date_to) {
        conditions.push('a.created_at <= ?');
        params.push(filters.date_to);
    }
    const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
    // Get total count
    const countRow = db
        .prepare(`SELECT COUNT(*) as cnt FROM audit_log a ${whereClause}`)
        .get(...params);
    const total = countRow.cnt;
    // Get paginated results with user display_name joined
    const limit = filters.limit ?? 50;
    const offset = filters.offset ?? 0;
    const entries = db
        .prepare(`SELECT a.*, u.display_name as user_display_name
       FROM audit_log a
       LEFT JOIN users u ON a.user_id = u.id
       ${whereClause}
       ORDER BY a.created_at DESC
       LIMIT ? OFFSET ?`)
        .all(...params, limit, offset);
    return { entries, total };
}
//# sourceMappingURL=user-operations.js.map