"use client";

import { useEffect, useRef } from "react";
import { apiBaseUrl, apiHeaders, apiPath } from "@/lib/api-url";
import { useUserAuth } from "@/lib/user-auth";

type PushPublicKeyResponse = {
  enabled: boolean;
  publicKey: string;
};

function urlBase64ToUint8Array(value: string) {
  const padding = "=".repeat((4 - (value.length % 4)) % 4);
  const base64 = `${value}${padding}`.replace(/-/g, "+").replace(/_/g, "/");
  const rawData = window.atob(base64);
  const outputArray = new Uint8Array(rawData.length);

  for (let index = 0; index < rawData.length; index += 1) {
    outputArray[index] = rawData.charCodeAt(index);
  }

  return outputArray;
}

async function postSubscription(token: string, subscription: PushSubscription) {
  await fetch(`${apiBaseUrl}${apiPath("/api/push/subscriptions")}`, {
    method: "POST",
    headers: apiHeaders({
      "Content-Type": "application/json",
      Authorization: `Bearer ${token}`,
    }),
    body: JSON.stringify(subscription.toJSON()),
  });
}

export function PwaPushManager() {
  const { token, user } = useUserAuth();
  const attemptedForToken = useRef("");

  useEffect(() => {
    if (!token || !user || attemptedForToken.current === token) {
      return;
    }

    if (
      typeof window === "undefined" ||
      !("serviceWorker" in navigator) ||
      !("PushManager" in window) ||
      !("Notification" in window)
    ) {
      return;
    }

    let isCancelled = false;
    attemptedForToken.current = token;

    async function registerPush() {
      const registration = await navigator.serviceWorker.register("/sw.js");
      const keyResponse = await fetch(`${apiBaseUrl}${apiPath("/api/push/public-key")}`, {
        headers: apiHeaders(),
      });
      const keyData = (await keyResponse.json().catch(() => ({}))) as PushPublicKeyResponse;

      if (!keyData.enabled || !keyData.publicKey || isCancelled) {
        return;
      }

      if (Notification.permission === "denied") {
        return;
      }

      if (Notification.permission === "default") {
        const permission = await Notification.requestPermission();

        if (permission !== "granted") {
          return;
        }
      }

      let subscription = await registration.pushManager.getSubscription();

      if (!subscription) {
        subscription = await registration.pushManager.subscribe({
          userVisibleOnly: true,
          applicationServerKey: urlBase64ToUint8Array(keyData.publicKey),
        });
      }

      if (!isCancelled) {
        await postSubscription(token, subscription);
      }
    }

    registerPush().catch((error) => {
      console.warn("Push notification setup failed", error);
    });

    return () => {
      isCancelled = true;
    };
  }, [token, user]);

  return null;
}
