import webpush from "web-push";
import { publicSettingsDb, serverSettingsDb } from "./dbs";
import PouchDB from "./PouchDB";

export const setupVapidDetails = async () => {
  const subject = process.env.VAPID_SUBJECT;
  if (!subject) {
    throw new Error("VAPID_SUBJECT env is empty!");
  }

  const changes = serverSettingsDb.changes({
    since: "now",
    live: true,
    include_docs: true,
    doc_ids: ["server_settings:message_delivery_method_web_push_vapid_keys"],
  });

  const vapidDetailsKeysDoc = await serverSettingsDb
    .get("server_settings:message_delivery_method_web_push_vapid_keys")
    .catch(async (error) => {
      if (error.name !== "not_found") {
        throw new Error(
          `server_settings:message_delivery_method_web_push_vapid_keys not found: ${error}`,
        );
      }

      const vapidKeys = webpush.generateVAPIDKeys();
      const doc = {
        _id: "server_settings:message_delivery_method_web_push_vapid_keys",
        type: "server_settings",
        name: "message_delivery_method_web_push_vapid_keys",
        value: vapidKeys,
        created_at: new Date().toISOString(),
      } as const;

      await Promise.all([
        serverSettingsDb.put(doc),
        publicSettingsDb.put({
          _id: "public_settings:message_delivery_method_web_push_vapid_public_key",
          type: "public_settings",
          name: "message_delivery_method_web_push_vapid_public_key",
          value: vapidKeys.publicKey,
          created_at: new Date().toISOString(),
        }),
      ]);

      console.log("created new vapid keys");
      return doc;
    });

  webpush.setVapidDetails(
    subject,
    vapidDetailsKeysDoc.value.publicKey,
    vapidDetailsKeysDoc.value.privateKey,
  );

  if (process.env.GCM_API_KEY) {
    webpush.setGCMAPIKey(process.env.GCM_API_KEY);
  }

  changes.on("change", (change) => {
    const doc = change.doc;
    if (!doc) {
      return;
    }

    console.log("update vapid details");
    webpush.setVapidDetails(subject, doc.value.publicKey, doc.value.privateKey);
    return;
  });
};
