import logger from "lib/logger";
import { streamerId } from "main";
import User from "user";
import alerts from "web/alerts/www/index.html";
import {
	getBadges,
	getExternalEmotes,
} from "web/chatWidget/widgetServerFunctions";
import chatWidget from "web/chatWidget/www/index.html";
import type {
	serverInstruction,
	serverNotificationEvent,
} from "web/serverTypes";

const port = Number(process.env.WEB_PORT);
if (Number.isNaN(port)) {
	logger.enverr("WEB_PORT");
	process.exit(1);
}

export default Bun.serve({
	port,
	routes: {
		"/chat": chatWidget,
		"/chat/getBadges": getBadges,
		"/chat/getEmotes": getExternalEmotes,

		"/alerts": alerts,
		"/alerts/assets/*": async (req) => {
			const url = new URL(req.url);
			const path = url.pathname.slice("/alerts/assets/".length);
			const file = Bun.file(`${import.meta.dir}/alerts/www/assets/${path}`);
			if (!(await file.exists()))
				return new Response(`404: ${url.pathname} not found`, {
					status: 404,
				});
			return new Response(file);
		},
		"/": async (req, srv) => {
			if (req.headers.get("Upgrade") === "websocket") {
				srv.upgrade(req);
				return;
			}
			const streamer = await User.initUserId(streamerId);
			return Response.redirect(`https://twitch.tv/${streamer?.username}`);
		},
	},
	websocket: {
		async message(ws, omessage) {
			try {
				const message = JSON.parse(omessage.toString()) as serverInstruction;
				if (!message.type) return;
				switch (message.type) {
					case "subscribe": {
						if (!message.target) return;
						const target = message.target.toLowerCase();
						ws.subscribe(message.target);
						ws.send(
							JSON.stringify({
								function: "serverNotification",
								message: `Successfully subscribed to ${target} events`,
							} as serverNotificationEvent),
						); // Both alerts and chatwidget subscriptions have the notification field
						break;
					}
				}
			} catch (_err) {
				ws.send("Incorrect instruction. Closing websocket connection");
				ws.close();
			}
		},
		close(ws) {
			ws.close();
		},
	},
	development: process.env.NODE_ENV === "development",
	error(error) {
		logger.err(`Error at fullstack web server: ${error}`);
		return new Response("Internal Server Error", { status: 500 });
	},
});
