"use client";
import { useEffect, useState } from "react";

function notificationUnsupported() {
	return (
		!("serviceWorker" in navigator)
		|| !("PushManager" in window)
		|| !("showNotification" in ServiceWorkerRegistration.prototype)
	)
}

async function registerAndSubscribe(
	vapidPublicKey: string,
	onSubscribe: (subs: PushSubscription | null ) => void,
) {
	try {
		await navigator.serviceWorker.register("/sw.js");
		await subscribe(vapidPublicKey, onSubscribe);
	} catch (err) {
		console.error("Failed to register service worker:", err);
	}
}

async function subscribe(
	vapidPublicKey: string,
	onSubscribe: (subs: PushSubscription | null) => void
) {
	try {
		const registration = await navigator.serviceWorker.ready;
		const subscription = await registration.pushManager.subscribe({
			userVisibleOnly: true,
			applicationServerKey: vapidPublicKey,
		});
		console.log("Got subscription object", subscription.toJSON());
		await submitSubscription(subscription);
		onSubscribe(subscription);
	} catch (err) {
		console.error("Failed to subscribe:" , err);
	}
}

async function unsubscribe(
	subscription: PushSubscription,
	onUnsubscribed: () => void,
) {
	const body = JSON.stringify({ subscription });
	await subscription.unsubscribe();
	const res = await fetch("/api/unsubscribe", {
		method: "POST",
		headers: {
			"Content-Type": "application/json",
		},
		body,
	});
	const result = await res.json();
	console.log("/api/unsubscribe returned", result);
	onUnsubscribed();
}

async function submitSubscription(subscription: PushSubscription) {
	const res = await fetch("/api/subscribe", {
		method: "POST",
		headers: {
			"Content-Type": "application/json",
		},
		body: JSON.stringify({ subscription }),
	});
	const result = await res.json();
	console.log("/api/subscribe returned", result);
}

async function getSubscription(
	onSubscribe: (subs: PushSubscription | null) => void,
) {
	const registration = await navigator.serviceWorker.ready;
	const subscription = await registration.pushManager.getSubscription();
	if (subscription) {
		onSubscribe(subscription);
	}
}

export function PushNotification(props: { vapidPublicKey: string }) {
	const [unsupported, setUnsupported] = useState<boolean | undefined>(undefined);
	const [subscription, setSubscription] = useState<PushSubscription | null>(null);
	useEffect(() => {
		const isUnsupported = notificationUnsupported();
		setUnsupported(isUnsupported);
		if (isUnsupported) {
			return;
		}

		getSubscription(setSubscription);
	}, [props.vapidPublicKey])

	return <section>
		Notifications are: <b>{subscription ? "Enabled" : "Disabled"}</b>
		<br />
		<button
			disabled={unsupported}
			onClick={() => {
				if (!subscription)
					registerAndSubscribe(props.vapidPublicKey, setSubscription)
				else
					unsubscribe(subscription, () => setSubscription(null))
			}}
		>
			{unsupported === undefined && "Checking for support"}
			{unsupported === true && "Notifications are not supported :(."}
			{unsupported === false  && subscription ? "Disable notifications" : "Enable notifications"}
		</button>
		<details>
			<summary>Debug</summary>
			<pre>
				<code>
					{JSON.stringify(subscription?.toJSON(), undefined, 4) ?? "No subscription set"}
				</code>
			</pre>
		</details>
	</section>;
}
