import webpush from "web-push";
import { serverSettingsDb } from "./dbs";
import { ServerSettingsDocument } from "@hereconnect/types";

function isType<N extends ServerSettingsDocument["name"]>(
  doc: ServerSettingsDocument | null | undefined,
  name: N,
): doc is ServerSettingsDocument & { name: N } {
  return !!(doc && doc.name === name);
}

export const setupVapidDetails = async () => {
  const changes = serverSettingsDb.changes({
    since: "now",
    live: true,
    include_docs: true,
    doc_ids: [
      "server_settings:message_delivery_method_web_push_vapid",
      "public_settings:message_delivery_method_web_push_gcm_api_key",
    ],
  });

  const {
    rows: [vapidDetailsRow, gcmApiRow],
  } = await serverSettingsDb.allDocs({
    keys: [
      "server_settings:message_delivery_method_web_push_vapid",
      "public_settings:message_delivery_method_web_push_gcm_api_key",
    ],
    include_docs: true,
  });

  if (
    !("doc" in vapidDetailsRow) ||
    !isType(vapidDetailsRow.doc, "message_delivery_method_web_push_vapid")
  ) {
    throw new Error(
      `VAPID details ${"error" in vapidDetailsRow ? vapidDetailsRow.error : "not exists"}`,
    );
  }

  if (
    "doc" in gcmApiRow &&
    isType(gcmApiRow.doc, "message_delivery_method_web_push_gcm_api_key")
  ) {
    webpush.setGCMAPIKey(gcmApiRow.doc.value);
  }

  webpush.setVapidDetails(
    vapidDetailsRow.doc.value.subject,
    vapidDetailsRow.doc.value.keys.publicKey,
    vapidDetailsRow.doc.value.keys.privateKey,
  );

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

    if (isType(change.doc, "message_delivery_method_web_push_vapid")) {
      console.log("update vapid details");
      webpush.setVapidDetails(
        change.doc.value.subject,
        change.doc.value.keys.publicKey,
        change.doc.value.keys.privateKey,
      );
      return;
    }

    if (
      "doc" in change &&
      isType(change.doc, "message_delivery_method_web_push_gcm_api_key")
    ) {
      console.log("update gcm api key");
      webpush.setGCMAPIKey(change.doc.value);
    }
  });
};
