'use server' import { revalidatePath } from 'next/cache' import prisma from '@/lib/prisma' import { auth } from '@/auth' // Add a collaborator to a note (delegates to the share request system) export async function addCollaborator(noteId: string, userEmail: string) { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { const result = await createShareRequest(noteId, userEmail, 'view') const targetUser = await prisma.user.findUnique({ where: { email: userEmail }, select: { id: true, name: true, email: true, image: true } }) if (!targetUser) throw new Error('User not found') return { success: true, user: targetUser } } catch (error: unknown) { console.error('Error adding collaborator:', error) throw error } } export async function removeCollaborator(noteId: string, userId: string) { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { const note = await prisma.note.findUnique({ where: { id: noteId } }) if (!note) throw new Error('Note not found') if (note.userId !== session.user.id) throw new Error('You can only manage collaborators on your own notes') await prisma.noteShare.deleteMany({ where: { noteId, userId } }) return { success: true } } catch (error: unknown) { console.error('Error removing collaborator:', error) throw new Error(error instanceof Error ? error.message : 'Failed to remove collaborator') } } export async function getNoteCollaborators(noteId: string) { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { const note = await prisma.note.findUnique({ where: { id: noteId }, select: { userId: true } }) if (!note) throw new Error('Note not found') if (note.userId !== session.user.id) { const share = await prisma.noteShare.findUnique({ where: { noteId_userId: { noteId, userId: session.user.id } } }) if (!share || share.status !== 'accepted') throw new Error('You do not have access to this note') } const shares = await prisma.noteShare.findMany({ where: { noteId }, include: { user: { select: { id: true, name: true, email: true, image: true } } } }) return shares.map(share => share.user) } catch (error: unknown) { console.error('Error fetching collaborators:', error) throw new Error(error instanceof Error ? error.message : 'Failed to fetch collaborators') } } export async function getNoteAllUsers(noteId: string) { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { const note = await prisma.note.findUnique({ where: { id: noteId }, select: { userId: true } }) if (!note) throw new Error('Note not found') const share = await prisma.noteShare.findUnique({ where: { noteId_userId: { noteId, userId: session.user.id } } }) const hasAccess = note.userId === session.user.id || (share && share.status === 'accepted') if (!hasAccess) throw new Error('You do not have access to this note') const owner = await prisma.user.findUnique({ where: { id: note.userId! }, select: { id: true, name: true, email: true, image: true } }) if (!owner) throw new Error('Owner not found') const shares = await prisma.noteShare.findMany({ where: { noteId, status: 'accepted' }, include: { user: { select: { id: true, name: true, email: true, image: true } } } }) return [owner, ...shares.map(s => s.user)] } catch (error: unknown) { console.error('Error fetching note users:', error) throw new Error(error instanceof Error ? error.message : 'Failed to fetch note users') } } export async function createShareRequest( noteId: string, recipientEmail: string, permission: 'view' | 'comment' | 'edit' = 'view' ) { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { const note = await prisma.note.findUnique({ where: { id: noteId } }) if (!note) throw new Error('Note not found') if (note.userId !== session.user.id) throw new Error('Only the owner can share notes') const recipient = await prisma.user.findUnique({ where: { email: recipientEmail } }) if (!recipient) throw new Error('User not found') if (recipient.id === session.user.id) throw new Error('You cannot share with yourself') const existingShare = await prisma.noteShare.findUnique({ where: { noteId_userId: { noteId, userId: recipient.id } } }) if (existingShare) { if (existingShare.status === 'declined' || existingShare.status === 'removed') { await prisma.noteShare.update({ where: { id: existingShare.id }, data: { status: 'pending', notifiedAt: new Date(), permission } }) } else { throw new Error('Note already shared with this user') } } else { await prisma.noteShare.create({ data: { noteId, userId: recipient.id, sharedBy: session.user.id, status: 'pending', permission, notifiedAt: new Date() } }) } return { success: true } } catch (error: unknown) { console.error('Error creating share request:', error) throw error } } export async function getPendingShareRequests() { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { return await prisma.noteShare.findMany({ where: { userId: session.user.id, status: 'pending' }, include: { note: { select: { id: true, title: true, content: true, color: true, createdAt: true } }, sharer: { select: { id: true, name: true, email: true, image: true } } }, orderBy: { createdAt: 'desc' } }) } catch (error: unknown) { console.error('Error fetching pending share requests:', error) throw error } } export async function respondToShareRequest(shareId: string, action: 'accept' | 'decline') { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { const share = await prisma.noteShare.findUnique({ where: { id: shareId }, include: { note: true, sharer: true } }) if (!share) throw new Error('Share request not found') if (share.userId !== session.user.id) throw new Error('Unauthorized') const updatedShare = await prisma.noteShare.update({ where: { id: shareId }, data: { status: action === 'accept' ? 'accepted' : 'declined', respondedAt: new Date() }, include: { note: { select: { title: true } } } }) revalidatePath('/home') return { success: true, share: updatedShare } } catch (error: unknown) { console.error('Error responding to share request:', error) throw error } } export async function getAcceptedSharedNotes() { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { const acceptedShares = await prisma.noteShare.findMany({ where: { userId: session.user.id, status: 'accepted' }, include: { note: true }, orderBy: { createdAt: 'desc' } }) return acceptedShares.map(share => share.note) } catch (error: unknown) { console.error('Error fetching accepted shared notes:', error) throw error } } export async function removeSharedNoteFromView(shareId: string) { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { const share = await prisma.noteShare.findUnique({ where: { id: shareId } }) if (!share) throw new Error('Share not found') if (share.userId !== session.user.id) throw new Error('Unauthorized') await prisma.noteShare.update({ where: { id: shareId }, data: { status: 'removed' } }) revalidatePath('/home') return { success: true } } catch (error: unknown) { console.error('Error removing shared note from view:', error) throw error } } export async function getPendingShareCount() { const session = await auth() if (!session?.user?.id) return 0 try { return await prisma.noteShare.count({ where: { userId: session.user.id, status: 'pending' } }) } catch (error) { console.error('Error getting pending share count:', error) return 0 } } export async function leaveSharedNote(noteId: string) { const session = await auth() if (!session?.user?.id) throw new Error('Unauthorized') try { const share = await prisma.noteShare.findUnique({ where: { noteId_userId: { noteId, userId: session.user.id } } }) if (!share) throw new Error('Share not found') if (share.userId !== session.user.id) throw new Error('Unauthorized') await prisma.noteShare.update({ where: { id: share.id }, data: { status: 'removed' } }) revalidatePath('/home') return { success: true } } catch (error: unknown) { console.error('Error leaving shared note:', error) throw error } }