← back to Dear Bubbe Nextjs

app/api/user-profile/route.ts

228 lines

import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import fs from 'fs/promises'
import path from 'path'

// Simple file-based storage for user profiles
const PROFILES_DIR = path.join(process.cwd(), 'data', 'profiles')

// Ensure profiles directory exists
async function ensureProfilesDir() {
  try {
    await fs.mkdir(PROFILES_DIR, { recursive: true })
  } catch (error) {
    console.error('Failed to create profiles directory:', error)
  }
}

export async function GET(request: NextRequest) {
  try {
    const session = await getServerSession(authOptions)
    
    if (!session?.user?.email) {
      return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
    }

    await ensureProfilesDir()
    
    // Use email as unique identifier
    const profileFile = path.join(PROFILES_DIR, `${session.user.email}.json`)
    
    try {
      const profileData = await fs.readFile(profileFile, 'utf-8')
      return NextResponse.json(JSON.parse(profileData))
    } catch (error) {
      // Profile doesn't exist yet
      return NextResponse.json({ onboardingCompleted: false })
    }
  } catch (error) {
    console.error('Error fetching profile:', error)
    return NextResponse.json({ error: 'Failed to fetch profile' }, { status: 500 })
  }
}

export async function POST(request: NextRequest) {
  try {
    const session = await getServerSession(authOptions)
    
    if (!session?.user?.email) {
      return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
    }

    const data = await request.json()
    
    await ensureProfilesDir()
    
    // Check if profile already exists
    const profileFile = path.join(PROFILES_DIR, `${session.user.email}.json`)
    let existingProfile: any = {}
    let isExistingProfile = false
    
    try {
      const profileData = await fs.readFile(profileFile, 'utf-8')
      existingProfile = JSON.parse(profileData)
      isExistingProfile = true
      console.log(`[PROFILE] Found existing profile:`, existingProfile)
    } catch (error) {
      console.log(`[PROFILE] No existing profile found, creating new one`)
    }
    
    // Smart merge: For each field, use new value if provided, otherwise keep existing
    const profileFields = [
      'preferredName', 'gender', 'relationshipStatus', 'birthYear', 
      'religiousLevel', 'hasKids', 'numberOfKids', 'incomeLevel',
      'education', 'school', 'degree', 'jobTitle', 'company', 
      'industry', 'country', 'state', 'city'
    ]
    
    const mergedData: any = {}
    
    // For each field, decide whether to use new or existing value
    for (const field of profileFields) {
      if (field in data) {
        // If the field is explicitly set in the new data
        // Keep the value even if it's empty (user might want to clear it)
        // But if it's the initial save and all fields are empty, use existing
        const allFieldsEmpty = profileFields.every(f => !data[f] || data[f] === '')
        
        if (allFieldsEmpty && isExistingProfile) {
          // This is likely the initial form load with empty data, preserve existing
          mergedData[field] = existingProfile[field] || data[field]
        } else {
          // User actually edited the form, use their value
          mergedData[field] = data[field]
        }
      } else if (existingProfile && field in existingProfile) {
        // Field not in new data, keep existing
        mergedData[field] = existingProfile[field]
      }
    }
    
    console.log(`[PROFILE] Merged data:`, mergedData)
    
    // Build the final profile
    const profile = {
      ...mergedData,
      id: (session.user as any).id || session.user.email,
      email: session.user.email,
      name: session.user.name,
      onboardingCompleted: true,
      updatedAt: new Date().toISOString(),
      createdAt: isExistingProfile ? existingProfile.createdAt : new Date().toISOString()
    }
    
    // Save profile to file (profileFile already declared above)
    await fs.writeFile(profileFile, JSON.stringify(profile, null, 2))
    
    console.log(`[PROFILE] Saved profile for ${session.user.email}:`, profile)
    
    // Return the profile directly for consistency
    return NextResponse.json(profile)
  } catch (error) {
    console.error('Error saving profile:', error)
    return NextResponse.json({ error: 'Failed to save profile' }, { status: 500 })
  }
}

export async function PUT(request: NextRequest) {
  try {
    const session = await getServerSession(authOptions)
    
    if (!session?.user?.email) {
      return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
    }

    const updates = await request.json()
    
    await ensureProfilesDir()
    
    const profileFile = path.join(PROFILES_DIR, `${session.user.email}.json`)
    
    // Read existing profile
    let existingProfile = {}
    try {
      const profileData = await fs.readFile(profileFile, 'utf-8')
      existingProfile = JSON.parse(profileData)
    } catch (error) {
      // Profile doesn't exist, create new one
    }
    
    const profile = {
      ...existingProfile,
      ...updates,
      email: session.user.email,
      name: session.user.name,
      updatedAt: new Date().toISOString()
    }
    
    await fs.writeFile(profileFile, JSON.stringify(profile, null, 2))
    
    console.log(`[PROFILE] Updated profile for ${session.user.email}:`, profile)
    
    // Return the profile directly for consistency
    return NextResponse.json(profile)
  } catch (error) {
    console.error('Error updating profile:', error)
    return NextResponse.json({ error: 'Failed to update profile' }, { status: 500 })
  }
}

export async function DELETE(request: NextRequest) {
  try {
    const session = await getServerSession(authOptions)
    
    if (!session?.user?.email) {
      return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
    }

    const { email } = await request.json()
    
    // Verify the user is deleting their own account
    if (email !== session.user.email) {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 403 })
    }
    
    await ensureProfilesDir()
    
    // Delete profile file
    const profileFile = path.join(PROFILES_DIR, `${email}.json`)
    try {
      await fs.unlink(profileFile)
      console.log(`[PROFILE] Deleted profile for ${email}`)
    } catch (error) {
      console.log(`[PROFILE] Profile file not found for ${email}`)
    }
    
    // Delete memory file
    const memoriesDir = path.join(process.cwd(), 'user-memories')
    const userId = (session.user as any).id || email.replace('@', '_').replace('.', '_')
    const memoryFile = path.join(memoriesDir, `${userId}.md`)
    
    try {
      await fs.unlink(memoryFile)
      console.log(`[PROFILE] Deleted memory file for ${userId}`)
    } catch (error) {
      console.log(`[PROFILE] Memory file not found for ${userId}`)
    }
    
    // Delete any conversation history files
    const conversationsDir = path.join(process.cwd(), 'data', 'conversations')
    const conversationFile = path.join(conversationsDir, `${email}.json`)
    
    try {
      await fs.unlink(conversationFile)
      console.log(`[PROFILE] Deleted conversation history for ${email}`)
    } catch (error) {
      console.log(`[PROFILE] Conversation file not found for ${email}`)
    }
    
    return NextResponse.json({ 
      success: true, 
      message: 'Account and all associated data deleted successfully' 
    })
  } catch (error) {
    console.error('Error deleting profile:', error)
    return NextResponse.json({ error: 'Failed to delete profile' }, { status: 500 })
  }
}