import jwt from 'jsonwebtoken'
import { NextRequest } from 'next/server'

import { addClient, removeClient, type NotificationEvent } from '@/lib/realtime'

export const dynamic = 'force-dynamic'

export async function GET(req: NextRequest) {
  const { searchParams } = new URL(req.url)
  const token = searchParams.get('token')

  if (!token) {
    return new Response('Unauthorized', { status: 401 })
  }

  let orgId: string | null = null
  try {
    const jwtSecret = process.env.JWT_SECRET
    if (!jwtSecret) throw new Error('JWT_SECRET not configured')
    const decoded = jwt.verify(token, jwtSecret) as {
      userId?: string
      phone?: string
      adminId?: string
      username?: string
      type?: string
      organizationId?: string
    }

    // Only user tokens are supported for SSE for now
    if (decoded.type === 'admin') {
      return new Response('Admins not supported for SSE yet', { status: 403 })
    }

    // For user token, require organization id to route notifications
    // Clients store it, but token doesn't include; we will not hit DB here to keep things simple.
    // As a compromise, allow optionally passing orgId via query.
    orgId = searchParams.get('orgId')
    if (!orgId) {
      // Fallback: if token was minted with organizationId claim
      orgId = (decoded as any).organizationId || null
    }

    if (!orgId) {
      return new Response('Organization ID required', { status: 400 })
    }
  } catch {
    return new Response('Unauthorized', { status: 401 })
  }

  const encoder = new TextEncoder()
  const stream = new ReadableStream<Uint8Array>({
    start(controller) {
      const send = (evt: NotificationEvent) => {
        controller.enqueue(encoder.encode(`data: ${JSON.stringify(evt)}\n\n`))
      }

      const client = { orgId: orgId!, send }
      addClient(orgId!, client)

      // Initial hello
      send({ type: 'connected', payload: { now: Date.now() } })

      // Heartbeat to keep connection alive
      const intervalId = setInterval(() => {
        try {
          controller.enqueue(encoder.encode(':\n\n'))
        } catch {
          clearInterval(intervalId)
        }
      }, 15000)

      const abortHandler = () => {
        clearInterval(intervalId)
        removeClient(orgId!, client)
        controller.close()
      }

      // Close on client disconnect
      req.signal.addEventListener('abort', abortHandler)
    },
    cancel() {
      // no-op
    },
  })

  return new Response(stream, {
    headers: {
      'Content-Type': 'text/event-stream; charset=utf-8',
      'Cache-Control': 'no-cache, no-transform',
      Connection: 'keep-alive',
      'X-Accel-Buffering': 'no',
    },
  })
}

