import { db } from '../db/client.js'; import type { AuditLogEntryRow, AuthContext, FlockNoteRow } from '../types.js'; type AuditLogInput = { workspaceId: number; auth?: AuthContext; action: string; entityType: string; entityId?: string | null; entityName?: string | null; details?: Record; }; export const createAuditLogEntry = async ({ workspaceId, auth, action, entityType, entityId = null, entityName = null, details = {}, }: AuditLogInput) => { const result = await db.query( `INSERT INTO audit_log_entries (workspace_id, user_id, actor_name, actor_email, action, entity_type, entity_id, entity_name, details) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id, workspace_id, user_id, actor_name, actor_email, action, entity_type, entity_id, entity_name, details, created_at`, [ workspaceId, auth?.user.id ?? null, auth?.user.name ?? null, auth?.user.email ?? null, action, entityType, entityId, entityName, JSON.stringify(details), ], ); return result.rows[0] ?? null; }; export const listAuditLogEntries = async (workspaceId: number, limit = 100) => { const result = await db.query( `SELECT id, workspace_id, user_id, actor_name, actor_email, action, entity_type, entity_id, entity_name, details, created_at FROM audit_log_entries WHERE workspace_id = $1 ORDER BY created_at DESC LIMIT $2`, [workspaceId, limit], ); return result.rows; }; export const listFlockNotes = async (workspaceId: number) => { const result = await db.query( `SELECT flock_notes.id, flock_notes.workspace_id, flock_notes.bird_id, birds.name AS bird_name, flock_notes.title, flock_notes.body, flock_notes.created_by_user_id, users.name AS created_by_name, flock_notes.created_at, flock_notes.updated_at FROM flock_notes LEFT JOIN birds ON birds.id = flock_notes.bird_id LEFT JOIN users ON users.id = flock_notes.created_by_user_id WHERE flock_notes.workspace_id = $1 ORDER BY flock_notes.updated_at DESC`, [workspaceId], ); return result.rows; }; export const createFlockNote = async ({ workspaceId, birdId, body, createdByUserId, }: { workspaceId: number; birdId: string | null; body: string; createdByUserId: string | null; }) => { const title = body.split(/\s+/).join(' ').slice(0, 160) || 'Note'; const result = await db.query( `WITH inserted_note AS ( INSERT INTO flock_notes (workspace_id, bird_id, title, body, created_by_user_id) SELECT $1, $2, $3, $4, $5 WHERE $2::uuid IS NULL OR EXISTS ( SELECT 1 FROM birds WHERE birds.id = $2 AND birds.workspace_id = $1 ) RETURNING id, workspace_id, bird_id, title, body, created_by_user_id, created_at, updated_at ) SELECT inserted_note.id, inserted_note.workspace_id, inserted_note.bird_id, birds.name AS bird_name, inserted_note.title, inserted_note.body, inserted_note.created_by_user_id, users.name AS created_by_name, inserted_note.created_at, inserted_note.updated_at FROM inserted_note LEFT JOIN birds ON birds.id = inserted_note.bird_id LEFT JOIN users ON users.id = inserted_note.created_by_user_id`, [workspaceId, birdId, title, body, createdByUserId], ); return result.rows[0] ?? null; }; export const deleteFlockNote = async (noteId: string, workspaceId: number) => { const result = await db.query<{ id: string; title: string }>( `DELETE FROM flock_notes WHERE id = $1 AND workspace_id = $2 RETURNING id, title`, [noteId, workspaceId], ); return result.rows[0] ?? null; };