import { z } from 'zod'

import { prisma } from '@/lib/db'
import { apiRoute } from '@/lib/api/handler'

export const dynamic = 'force-dynamic'

/**
 * Notifications routed to the signed-in operator.
 *
 * Scoped by identity *and* by role: an alert escalated to "control_operator" reaches
 * whoever holds that role, which is how a control room actually works — the shift matters,
 * not the individual. The query is deliberately built from the session rather than from
 * any client-supplied id, so one user can never read another's queue.
 */
function scopeFor(userId: string, roles: string[]) {
  return { OR: [{ userId }, { roleKey: { in: roles } }] }
}

export const GET = apiRoute({ permission: 'alerts.read' }, async ({ user, searchParams }) => {
  const take = Math.min(30, Math.max(1, Number(searchParams.get('limit')) || 12))
  const where = scopeFor(user.id, user.roles)

  const [items, unread] = await Promise.all([
    prisma.notification.findMany({
      where,
      orderBy: { createdAt: 'desc' },
      take,
      include: { alert: { select: { code: true, level: true, status: true } } },
    }),
    prisma.notification.count({ where: { ...where, readAt: null } }),
  ])

  return {
    unread,
    items: items.map((item) => ({
      id: item.id,
      level: item.level,
      title: item.title,
      titleAr: item.titleAr,
      body: item.body,
      bodyAr: item.bodyAr,
      link: item.link,
      createdAt: item.createdAt.getTime(),
      readAt: item.readAt?.getTime() ?? null,
      alertCode: item.alert?.code ?? null,
    })),
  }
})

const markReadSchema = z.object({
  /** Omit to mark everything in the caller's queue as read. */
  id: z.string().trim().max(40).optional(),
})

export const PATCH = apiRoute<Record<string, string>, z.infer<typeof markReadSchema>>(
  { permission: 'alerts.read', bodySchema: markReadSchema },
  async ({ body, user }) => {
    const where = body.id
      ? { id: body.id, ...scopeFor(user.id, user.roles) }
      : { ...scopeFor(user.id, user.roles), readAt: null }

    const result = await prisma.notification.updateMany({
      where,
      data: { readAt: new Date(), status: 'read' },
    })

    return { markedRead: result.count }
  },
)
