/**
 * Web Push helpers for article notifications (VAPID + backend API).
 */

/** Fired after any article/category push subscribe or unsubscribe so all UIs re-query status. */
export const PUSH_SUBSCRIPTIONS_CHANGED_EVENT = "growheads-push-subscriptions-changed";

export function emitPushSubscriptionsChanged() {
  if (typeof window !== "undefined") {
    window.dispatchEvent(new CustomEvent(PUSH_SUBSCRIPTIONS_CHANGED_EVENT));
  }
}

export const ARTICLE_PUSH_SW_PATH = "/api/check/push/service-worker";
export const ARTICLE_PUSH_VAPID_URL = "/api/check/push/vapid-public-key";

export function urlBase64ToUint8Array(base64String) {
  const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
  const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");
  const rawData = window.atob(base64);
  const outputArray = new Uint8Array(rawData.length);
  for (let i = 0; i < rawData.length; ++i) {
    outputArray[i] = rawData.charCodeAt(i);
  }
  return outputArray;
}

export async function fetchPushConfiguration() {
  const res = await fetch(ARTICLE_PUSH_VAPID_URL);
  if (!res.ok) {
    throw new Error(`VAPID config HTTP ${res.status}`);
  }
  return res.json();
}

export function isPushApiSupported() {
  return (
    typeof window !== "undefined" &&
    "serviceWorker" in navigator &&
    "PushManager" in window &&
    "Notification" in window
  );
}

export async function registerPushServiceWorker() {
  return navigator.serviceWorker.register(ARTICLE_PUSH_SW_PATH, {
    scope: "/",
  });
}

/**
 * @param {string} vapidPublicKey
 * @returns {Promise<PushSubscription>}
 */
export async function ensurePushSubscription(vapidPublicKey) {
  const registration = await navigator.serviceWorker.ready;
  let subscription = await registration.pushManager.getSubscription();
  if (subscription) {
    return subscription;
  }
  const applicationServerKey = urlBase64ToUint8Array(vapidPublicKey);
  return registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey,
  });
}

/**
 * @param {number} kArtikel
 * @param {string} endpoint
 */
export async function articlePushStatus(kArtikel, endpoint) {
  const res = await fetch("/api/article/push/status", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ kArtikel, endpoint }),
  });
  const data = await res.json().catch(() => ({}));
  return { ...data, httpOk: res.ok };
}

/**
 * @param {number} kArtikel
 * @param {PushSubscription} subscription
 */
export async function articlePushSubscribe(kArtikel, subscription) {
  const subJson = subscription.toJSON();
  const res = await fetch("/api/article/push/subscribe", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      kArtikel,
      subscription: subJson,
    }),
  });
  const data = await res.json().catch(() => ({}));
  return { ...data, httpOk: res.ok };
}

/** POST /api/article/push/unsubscribe — body is always `{ endpoint, kArtikel }` (scoped row only). */
export async function articlePushUnsubscribe(endpoint, kArtikel) {
  const parsed =
    kArtikel != null && kArtikel !== ""
      ? typeof kArtikel === "number"
        ? kArtikel
        : parseInt(String(kArtikel), 10)
      : NaN;
  if (!Number.isFinite(parsed) || parsed <= 0) {
    return { success: false, httpOk: false, error: "missing_kArtikel" };
  }
  const body = { endpoint, kArtikel: parsed };
  const res = await fetch("/api/article/push/unsubscribe", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  const data = await res.json().catch(() => ({}));
  return { ...data, httpOk: res.ok };
}

/**
 * POST /api/article/push/status — backend returns:
 * `{ "success": true, "registered": true | false }`
 */
export function parseSubscribedStatus(data) {
  if (!data || typeof data !== "object") return false;
  if (typeof data.registered === "boolean") {
    return data.registered;
  }
  if (data.subscribed === true || data.isSubscribed === true) return true;
  if (data.success === true && data.subscribed === true) return true;
  if (data.status === "subscribed" || data.status === "active") return true;
  return false;
}

/**
 * POST /api/article/push/subscribe and .../unsubscribe — backend returns:
 * `{ "success": true }`
 */
export function parseSuccess(data) {
  if (!data || typeof data !== "object") return false;
  if (data.success === true) return true;
  if (data.success === false) return false;
  if (data.httpOk === true) return true;
  return false;
}
