All files / web/src/app/api/admin/notifications/test route.ts

0% Statements 0/98
0% Branches 0/1
0% Functions 0/1
0% Lines 0/98

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99                                                                                                                                                                                                     
import { NextResponse, type NextRequest } from 'next/server'
import { withAuth } from '@/lib/auth/withAuth'
import { sendWebPush } from '@/lib/notifications/web-push'
import { sendEmail } from '@/lib/notifications/email'
import { getSocketIO } from '@/lib/socket-io'

/**
 * POST /api/admin/notifications/test
 *
 * Send a test notification through a specified channel.
 * Body: { channel: 'webPush' | 'email' | 'inApp', targetEmail?: string, pushSubscription?: object }
 */
export const POST = withAuth(
  async (request: NextRequest, { userId }) => {
    try {
      const body = await request.json()
      const { channel, targetEmail, pushSubscription } = body as {
        channel: 'webPush' | 'email' | 'inApp'
        targetEmail?: string
        pushSubscription?: { endpoint: string; keys: { p256dh: string; auth: string } }
      }

      if (!channel) {
        return NextResponse.json({ error: 'channel is required' }, { status: 400 })
      }

      switch (channel) {
        case 'webPush': {
          if (!pushSubscription) {
            return NextResponse.json(
              { error: 'pushSubscription is required for webPush test' },
              { status: 400 }
            )
          }
          const result = await sendWebPush(pushSubscription, {
            title: 'Test Notification',
            body: 'Web Push is working!',
            icon: '/icon-192x192.png',
            data: { url: '/' },
          })
          return NextResponse.json({ success: result.success, statusCode: result.statusCode })
        }

        case 'email': {
          if (!targetEmail) {
            return NextResponse.json(
              { error: 'targetEmail is required for email test' },
              { status: 400 }
            )
          }
          await sendEmail({
            to: targetEmail,
            subject: 'Abaci One - Test Notification',
            html: `<div style="font-family:sans-serif;padding:20px;">
              <h2>Test Notification</h2>
              <p>Email notifications are working correctly.</p>
              <p style="color:#888;">Sent from Abaci One admin panel.</p>
            </div>`,
          })
          return NextResponse.json({ success: true })
        }

        case 'inApp': {
          const io = await getSocketIO()
          if (!io) {
            return NextResponse.json(
              { success: false, error: 'Socket.IO server not available' },
              { status: 503 }
            )
          }
          io.to(`user:${userId}`).emit('notification', {
            type: 'session-started',
            title: '🧪 Test Student started practicing!',
            body: 'Tap to watch live',
            icon: '/icon-192x192.png',
            url: '/',
            data: {
              sessionId: 'test',
              playerId: 'test',
              playerName: 'Test Student',
              playerEmoji: '🧪',
              observeUrl: '/',
            },
          })
          return NextResponse.json({ success: true })
        }

        default:
          return NextResponse.json({ error: `Unknown channel: ${channel}` }, { status: 400 })
      }
    } catch (error) {
      const message = error instanceof Error ? error.message : String(error)
      console.error('[admin/notifications/test] Error:', message)
      return NextResponse.json({ success: false, error: message }, { status: 500 })
    }
  },
  { role: 'admin' }
)