import webPush from "web-push";
import { eq, and, isNotNull } from "drizzle-orm";
import type { Db } from "@paperclipai/db";
import { pushSubscriptions } from "@paperclipai/db";
import { logger } from "../middleware/logger.js";

export function initVapid(): void {
  const publicKey = process.env.VAPID_PUBLIC_KEY;
  const privateKey = process.env.VAPID_PRIVATE_KEY;
  if (!publicKey || !privateKey) {
    logger.warn("VAPID keys not configured — push notifications disabled");
    return;
  }
  try {
    webPush.setVapidDetails(
      process.env.VAPID_SUBJECT ?? "mailto:admin@nexus.local",
      publicKey,
      privateKey,
    );
  } catch (err) {
    logger.warn({ err }, "Failed to initialize VAPID — push notifications disabled");
  }
}

export function getVapidPublicKey(): string | null {
  return process.env.VAPID_PUBLIC_KEY ?? null;
}

export async function saveSubscription(
  db: Db,
  params: {
    endpoint: string;
    p256dh: string;
    auth: string;
    userId?: string;
    companyId?: string;
    deviceLabel?: string;
  },
): Promise<string> {
  const id = crypto.randomUUID();
  await db.insert(pushSubscriptions).values({
    id,
    endpoint: params.endpoint,
    p256dh: params.p256dh,
    auth: params.auth,
    userId: params.userId ?? null,
    companyId: params.companyId ?? null,
    deviceLabel: params.deviceLabel ?? null,
  }).onConflictDoNothing();
  return id;
}

export async function removeSubscription(db: Db, endpoint: string): Promise<void> {
  await db.delete(pushSubscriptions).where(eq(pushSubscriptions.endpoint, endpoint));
}

export async function sendPushToAll(
  db: Db,
  companyId: string | null,
  payload: { title: string; body: string; icon?: string; data?: Record<string, string> },
): Promise<void> {
  const rows = await db
    .select()
    .from(pushSubscriptions)
    .where(
      companyId
        ? and(eq(pushSubscriptions.companyId, companyId), isNotNull(pushSubscriptions.endpoint))
        : isNotNull(pushSubscriptions.endpoint),
    );

  const payloadStr = JSON.stringify(payload);

  await Promise.allSettled(
    rows.map(async (row) => {
      try {
        await webPush.sendNotification(
          { endpoint: row.endpoint, keys: { p256dh: row.p256dh, auth: row.auth } },
          payloadStr,
        );
      } catch (err: unknown) {
        const status = (err as { statusCode?: number }).statusCode;
        if (status === 410 || status === 404) {
          // Stale subscription — remove it
          await removeSubscription(db, row.endpoint).catch(() => {});
        } else {
          logger.warn({ err, endpoint: row.endpoint }, "Push notification send failed");
        }
      }
    }),
  );
}
