import { Injectable } from '@nestjs/common';
import webpush from 'web-push';
import type { NotificationPayload, NotificationPort, PushSub } from './notification.port';

type SendFn = typeof webpush.sendNotification;
export interface Vapid {
  publicKey: string;
  privateKey: string;
  subject: string;
}

/** Web Push (VAPID) delivery. A dead subscription (404/410) → 'gone' so the caller prunes it. */
@Injectable()
export class WebPushDelivery implements NotificationPort {
  private readonly vapid?: Vapid;

  constructor(
    vapid?: Vapid,
    private readonly send: SendFn = webpush.sendNotification,
  ) {
    // Store VAPID; pass it per-send (not global setVapidDetails) so construction never
    // validates keys — keeps the adapter unit-testable with a mocked transport.
    this.vapid = vapid?.publicKey ? vapid : undefined;
  }

  async deliver(sub: PushSub, payload: NotificationPayload): Promise<'sent' | 'gone' | 'failed'> {
    if (!this.vapid) return 'failed'; // push disabled (no VAPID keys)
    try {
      await this.send(
        { endpoint: sub.endpoint, keys: { p256dh: sub.p256dh, auth: sub.auth } },
        JSON.stringify(payload),
        { vapidDetails: this.vapid },
      );
      return 'sent';
    } catch (e) {
      const code = (e as { statusCode?: number }).statusCode;
      return code === 404 || code === 410 ? 'gone' : 'failed';
    }
  }
}
