import { Response } from 'express';
import { prisma } from '../config/database';
import { AuthRequest } from '../middleware/auth';
import { getVapidPublicKey } from '../lib/webPush';

// Public VAPID key fetch — the web client needs it to call
// PushManager.subscribe(). Open endpoint (no auth) since the key is meant
// to be public; the private half stays server-side.
export async function getPublicKey(_req: AuthRequest, res: Response): Promise<void> {
  const key = getVapidPublicKey();
  if (!key) {
    res.status(503).json({ error: 'Web Push not configured on this server' });
    return;
  }
  res.json({ publicKey: key });
}

// Upsert a PushSubscription for the current session. The browser hands us
// the full PushSubscription JSON; we explode it into endpoint + keys and
// scope to whichever principal is signed in. Idempotent — the unique index
// on `endpoint` means re-subscribing from the same browser updates the
// existing row instead of duplicating.
export async function subscribe(req: AuthRequest, res: Response): Promise<void> {
  try {
    const { subscription, userAgent } = req.body || {};
    if (!subscription?.endpoint || !subscription?.keys?.p256dh || !subscription?.keys?.auth) {
      res.status(400).json({ error: 'Invalid subscription payload' });
      return;
    }
    if (!req.ownerId) {
      res.status(401).json({ error: 'Not authenticated' });
      return;
    }
    const row = await prisma.pushSubscription.upsert({
      where: { endpoint: subscription.endpoint },
      create: {
        ownerId: req.ownerId,
        adminId: req.adminId || null,
        endpoint: subscription.endpoint,
        p256dh: subscription.keys.p256dh,
        auth: subscription.keys.auth,
        userAgent: typeof userAgent === 'string' ? userAgent.slice(0, 500) : null,
      },
      // Re-binding an existing endpoint to a different principal can happen
      // when two users share a browser; we trust the active session.
      update: {
        ownerId: req.ownerId,
        adminId: req.adminId || null,
        p256dh: subscription.keys.p256dh,
        auth: subscription.keys.auth,
        userAgent: typeof userAgent === 'string' ? userAgent.slice(0, 500) : null,
      },
    });
    res.json({ id: row.id });
  } catch (e) {
    console.error('subscribe', e);
    res.status(500).json({ error: 'Failed to save subscription' });
  }
}

// Removes the current subscription. Called from the browser when the user
// disables notifications or unsubscribes from PushManager.
export async function unsubscribe(req: AuthRequest, res: Response): Promise<void> {
  try {
    const { endpoint } = req.body || {};
    if (!endpoint) { res.status(400).json({ error: 'endpoint is required' }); return; }
    await prisma.pushSubscription.deleteMany({ where: { endpoint } });
    res.json({ ok: true });
  } catch (e) {
    console.error('unsubscribe', e);
    res.status(500).json({ error: 'Failed to unsubscribe' });
  }
}
