/**
 * Web Push subscription routes — system-communications-notifications (Task 10).
 *
 * GET  /api/push/vapid-public-key  → { publicKey } (no auth required)
 * POST /api/push/subscribe         → 201 (session auth)
 * DELETE /api/push/subscribe       → 204 (session auth)
 */
import { Hono } from 'hono'
import { HTTPException } from 'hono/http-exception'
import { z } from 'zod'
import type { AppEnv } from '../types'
import { authMiddleware } from '../middleware/auth'
import { createDb, upsertPushSubscription, deletePushSubscription } from '@zync/db/queries'
import { assertSafePushEndpointUrl, UnsafeOutboundUrlError } from '@zync/utils'

const pushRouter = new Hono<AppEnv>()

// GET /api/push/vapid-public-key — no auth required
pushRouter.get('/vapid-public-key', (c) => {
  return c.json({ publicKey: c.env.VAPID_PUBLIC_KEY })
})

const subscribeSchema = z.object({
  endpoint: z.string().url(),
  keys: z.object({
    p256dh: z.string().min(1),
    auth: z.string().min(1),
  }),
  userAgent: z.string().optional(),
})

const unsubscribeSchema = z.object({
  endpoint: z.string().url(),
})

// POST /api/push/subscribe — session auth required
pushRouter.post('/subscribe', authMiddleware, async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const parsed = subscribeSchema.safeParse(await c.req.json())
  if (!parsed.success) {
    return c.json({ error: 'Invalid request', issues: parsed.error.issues }, 400)
  }

  const { endpoint, keys, userAgent } = parsed.data

  try {
    assertSafePushEndpointUrl(endpoint)
  } catch (err) {
    if (err instanceof UnsafeOutboundUrlError) {
      throw new HTTPException(400, { message: err.message })
    }
    throw err
  }

  const db = createDb(c.env)

  await upsertPushSubscription(db, {
    userId: session.sub,
    tenantId: session.tid,
    endpoint,
    p256dh: keys.p256dh,
    auth: keys.auth,
    userAgent,
  })

  return c.json({ status: 'subscribed' }, 201)
})

// DELETE /api/push/subscribe — session auth required
pushRouter.delete('/subscribe', authMiddleware, async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const parsed = unsubscribeSchema.safeParse(await c.req.json())
  if (!parsed.success) {
    return c.json({ error: 'Invalid request', issues: parsed.error.issues }, 400)
  }

  const db = createDb(c.env)
  await deletePushSubscription(db, session.sub, session.tid, parsed.data.endpoint)

  return new Response(null, { status: 204 })
})

export { pushRouter }
