import { env } from "@/lib/env";
import { router } from "./router";
import type { Server } from "bun";
import { AuroraClient } from "@/lib/BotClient";

export class WebServer {
    private static server: Server<unknown> | null = null;
    private static heartbeatInterval: ReturnType<typeof setInterval> | null = null;

    public static start(port?: number) {
        this.server = Bun.serve({
            port: port ?? env.PORT,
            hostname: env.HOST,
            fetch: (req, server) => {
                const url = new URL(req.url);
                if (url.pathname === "/ws") {
                    // Upgrade the request to a WebSocket
                    // We pass dummy data for now
                    if (server.upgrade(req, { data: undefined })) {
                        return undefined;
                    }
                    return new Response("WebSocket upgrade failed", { status: 500 });
                }
                return router(req);
            },
            websocket: {
                open(ws) {
                    // console.log("ws: client connected");
                    ws.subscribe("status-updates");
                    ws.send(JSON.stringify({ type: "WELCOME", message: "Connected to Aurora WebSocket" }));
                },
                message(ws, message) {
                    // Handle incoming messages if needed
                },
                close(ws) {
                    // console.log("ws: client disconnected");
                    ws.unsubscribe("status-updates");
                },
            },
        });

        console.log(`🌐 Web server listening on http://${this.server.hostname}:${this.server.port} (Restricted to Local Interface)`);

        // Start a heartbeat loop
        this.heartbeatInterval = setInterval(() => {
            if (this.server) {
                const memoryUsage = process.memoryUsage();
                this.server.publish("status-updates", JSON.stringify({
                    type: "HEARTBEAT",
                    data: {
                        guildCount: AuroraClient.guilds.cache.size,
                        userCount: AuroraClient.guilds.cache.reduce((acc, guild) => acc + guild.memberCount, 0),
                        commandCount: AuroraClient.commands.size,
                        ping: AuroraClient.ws.ping,
                        memory: (memoryUsage.heapUsed / 1024 / 1024).toFixed(2),
                        memoryTotal: (memoryUsage.rss / 1024 / 1024).toFixed(2),
                        uptime: process.uptime(),
                        timestamp: Date.now()
                    }
                }));
            }
        }, 3000); // Update every 3 seconds for better responsiveness
    }

    public static stop() {
        if (this.heartbeatInterval) {
            clearInterval(this.heartbeatInterval);
            this.heartbeatInterval = null;
        }
        if (this.server) {
            this.server.stop();
            console.log("🛑 Web server stopped");
            this.server = null;
        }
    }

    public static get port(): number | undefined {
        return this.server?.port;
    }

    public static broadcastLog(type: string, message: string) {
        if (this.server) {
            this.server.publish("status-updates", JSON.stringify({
                type: "LOG",
                data: {
                    timestamp: new Date().toLocaleTimeString(),
                    type,
                    message
                }
            }));
        }
    }
}
