// app/api/sync/status/route.ts import { syncService } from "@/lib/vendor-document-list/sync-service" import { NextRequest, NextResponse } from "next/server" import { getServerSession } from "next-auth" import { authOptions } from "@/app/api/auth/[...nextauth]/route" // JSON 직렬화 가능한 형태로 변환하는 헬퍼 함수 function serializeForJSON(obj: any): any { if (obj === null || obj === undefined) { return null } if (obj instanceof Date) { return obj.toISOString() } if (typeof obj === 'bigint') { return obj.toString() } if (Array.isArray(obj)) { return obj.map(serializeForJSON) } if (typeof obj === 'object') { const serialized: any = {} for (const [key, value] of Object.entries(obj)) { serialized[key] = serializeForJSON(value) } return serialized } return obj } export async function GET(request: NextRequest) { try { const session = await getServerSession(authOptions) if (!session?.user?.id) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }) } const { searchParams } = new URL(request.url) const projectId = searchParams.get('projectId') const targetSystem = searchParams.get('targetSystem') || 'DOLCE' // 기본값 DOLCE로 변경 const realtime = searchParams.get('realtime') === 'true' if (!projectId) { return NextResponse.json( { error: 'Project ID is required' }, { status: 400 } ) } let status try { // 실제 데이터베이스에서 조회 status = await syncService.getSyncStatus( parseInt(projectId), targetSystem ) } catch (error) { console.error('Database query failed:', error) // 개발 환경에서만 목업 데이터 반환 if (process.env.NODE_ENV === 'development') { console.log('Using mock data for development') status = { projectId: parseInt(projectId), vendorId: 1, // 임시 vendorId targetSystem, totalChanges: 15, pendingChanges: 3, syncedChanges: 12, failedChanges: 0, // entityType별 상세 통계 추가 entityTypeDetails: { document: { pending: 1, synced: 4, failed: 0, total: 5 }, revision: { pending: 2, synced: 6, failed: 0, total: 8 }, attachment: { pending: 0, synced: 2, failed: 0, total: 2 } }, lastSyncAt: new Date(Date.now() - 30 * 60 * 1000).toISOString(), nextSyncAt: new Date(Date.now() + 30 * 60 * 1000).toISOString(), syncEnabled: true, hasPendingChanges: true, hasFailedChanges: false, syncHealthy: true, requiresSync:false } } else { // 프로덕션에서는 에러 반환 return NextResponse.json( { error: 'Failed to get sync status', message: error instanceof Error ? error.message : 'Unknown error' }, { status: 500 } ) } } // JSON 직렬화 가능한 형태로 변환 const serializedStatus = serializeForJSON(status) // 실시간 모드일 경우 캐시 비활성화 if (realtime) { return NextResponse.json(serializedStatus, { headers: { 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' } }) } // 일반 모드: 캐시 헤더 설정 (30초) return NextResponse.json(serializedStatus, { headers: { 'Cache-Control': 'public, max-age=30, s-maxage=30, stale-while-revalidate=60' } }) } catch (error) { console.error('Failed to get sync status:', error) return NextResponse.json( { error: 'Failed to get sync status', message: error instanceof Error ? error.message : 'Unknown error' }, { status: 500 } ) } }