import 'server-only'

import webpush from 'web-push'
import { prisma } from '@/lib/prisma'

export type PushPayload = {
  title: string
  body: string
  url: string
  tag?: string
}

const vapidReady =
  !!process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY &&
  !!process.env.VAPID_PRIVATE_KEY &&
  !!process.env.VAPID_SUBJECT

if (vapidReady) {
  webpush.setVapidDetails(
    process.env.VAPID_SUBJECT!,
    process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY!,
    process.env.VAPID_PRIVATE_KEY!,
  )
}

export const enabled = vapidReady

export async function sendPushToUser(userId: string, payload: PushPayload): Promise<void> {
  if (!enabled) {
    console.warn('[push-server] VAPID not configured — skipping push for user', userId)
    return
  }

  const subs = await prisma.pushSubscription.findMany({ where: { user_id: userId } })
  await Promise.allSettled(subs.map((sub) => sendOne(sub, payload)))
}

async function sendOne(
  sub: { id: string; endpoint: string; p256dh: string; auth: string },
  payload: PushPayload,
): Promise<void> {
  try {
    await webpush.sendNotification(
      { endpoint: sub.endpoint, keys: { p256dh: sub.p256dh, auth: sub.auth } },
      JSON.stringify(payload),
    )
    await prisma.pushSubscription.update({
      where: { id: sub.id },
      data: { last_used_at: new Date() },
    })
  } catch (err: unknown) {
    const status = (err as { statusCode?: number }).statusCode
    if (status === 404 || status === 410) {
      try {
        await prisma.pushSubscription.delete({ where: { id: sub.id } })
      } catch {
        // already deleted by a concurrent request — ignore
      }
    } else {
      console.error('[push-server] sendNotification error for endpoint', sub.endpoint, err)
    }
  }
}
