'use server' import { revalidatePath } from 'next/cache' import prisma from '@/lib/prisma' import { auth } from '@/auth' import { parseNote } from '@/lib/utils' import { parseImageUrls, cleanupNoteImages, deleteImageFileSafely } from '@/lib/image-cleanup' import { NOTE_LIST_SELECT } from '@/lib/note-select' // Soft-delete a note (move to trash) export async function deleteNote(id: string, options?: { skipRevalidation?: boolean }) { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { await prisma.note.update({ where: { id, userId: session.user.id }, data: { trashedAt: new Date() } }) if (!options?.skipRevalidation) { revalidatePath('/home') } return { success: true } } catch (error) { console.error('Error deleting note:', error) throw new Error('Failed to delete note') } } export async function trashNote(id: string, options?: { skipRevalidation?: boolean }) { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { await prisma.note.update({ where: { id, userId: session.user.id }, data: { trashedAt: new Date() } }) if (!options?.skipRevalidation) { revalidatePath('/home') } return { success: true } } catch (error) { console.error('Error trashing note:', error) throw new Error('Failed to trash note') } } export async function restoreNote(id: string) { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { await prisma.note.update({ where: { id, userId: session.user.id }, data: { trashedAt: null } }) revalidatePath('/home') revalidatePath('/trash') return { success: true } } catch (error) { console.error('Error restoring note:', error) throw new Error('Failed to restore note') } } export async function getTrashedNotes() { const session = await auth() if (!session?.user?.id) return [] try { const notes = await prisma.note.findMany({ where: { userId: session.user.id, trashedAt: { not: null } }, select: NOTE_LIST_SELECT, orderBy: { trashedAt: 'desc' } }) return notes.map(parseNote) } catch (error) { console.error('Error fetching trashed notes:', error) return [] } } export async function permanentDeleteNote(id: string) { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { const note = await prisma.note.findUnique({ where: { id, userId: session.user.id }, select: { images: true } }) const imageUrls = parseImageUrls(note?.images ?? null) await prisma.note.delete({ where: { id, userId: session.user.id } }) if (imageUrls.length > 0) { await cleanupNoteImages(id, imageUrls) } revalidatePath('/trash') revalidatePath('/home') return { success: true } } catch (error) { console.error('Error permanently deleting note:', error) throw new Error('Failed to permanently delete note') } } export async function emptyTrash() { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { const trashedNotes = await prisma.note.findMany({ where: { userId: session.user.id, trashedAt: { not: null } }, select: { id: true, images: true } }) await prisma.note.deleteMany({ where: { userId: session.user.id, trashedAt: { not: null } } }) for (const note of trashedNotes) { const imageUrls = parseImageUrls(note.images) if (imageUrls.length > 0) { await cleanupNoteImages(note.id, imageUrls) } } await prisma.notebook.deleteMany({ where: { userId: session.user.id, trashedAt: { not: null } } }) revalidatePath('/trash') revalidatePath('/home') return { success: true } } catch (error) { console.error('Error emptying trash:', error) throw new Error('Failed to empty trash') } } export async function removeImageFromNote(noteId: string, imageIndex: number) { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { const note = await prisma.note.findUnique({ where: { id: noteId, userId: session.user.id }, select: { images: true }, }) if (!note) throw new Error('Note not found') const imageUrls = parseImageUrls(note.images) if (imageIndex < 0 || imageIndex >= imageUrls.length) throw new Error('Invalid image index') const removedUrl = imageUrls[imageIndex] const newImages = imageUrls.filter((_, i) => i !== imageIndex) await prisma.note.update({ where: { id: noteId }, data: { images: newImages.length > 0 ? JSON.stringify(newImages) : null }, }) await deleteImageFileSafely(removedUrl, noteId) return { success: true } } catch (error) { console.error('Error removing image:', error) throw new Error('Failed to remove image') } } export async function cleanupOrphanedImages(imageUrls: string[], noteId: string) { const session = await auth() if (!session?.user?.id) return try { for (const url of imageUrls) { await deleteImageFileSafely(url, noteId) } } catch { // Silent — best-effort cleanup } } export async function getTrashCount() { const session = await auth() if (!session?.user?.id) return 0 try { const [noteCount, notebookCount] = await Promise.all([ prisma.note.count({ where: { userId: session.user.id, trashedAt: { not: null } } }), prisma.notebook.count({ where: { userId: session.user.id, trashedAt: { not: null } } }) ]) return noteCount + notebookCount } catch { return 0 } } export async function getTrashedNotebooks() { const session = await auth() if (!session?.user?.id) return [] try { return await prisma.notebook.findMany({ where: { userId: session.user.id, trashedAt: { not: null } }, include: { _count: { select: { notes: true } } }, orderBy: { trashedAt: 'desc' } }) } catch (error) { console.error('Error fetching trashed notebooks:', error) return [] } }