import { createServer } from "node:http";
import { Server as SocketIOServer } from "socket.io";
import fs from "fs";

export const startServer = (port = Number(Bun.env.PORT ?? 3000)) => {
  const requiredPsk = Bun.env.PSK;
  if (!requiredPsk) {
    throw new Error("PSK is not set.");
  }

  const httpServer = createServer((_, response) => {
    response.writeHead(200, { "content-type": "text/plain" });
    response.end("Socket.IO server is running");
  });

  const io = new SocketIOServer(httpServer, {
    cors: {
      origin: "*",
    },
  });

  io.use((socket, next) => {
    const headerPsk = socket.handshake.headers["x-psk"];
    const queryPsk = socket.handshake.query.psk;
    const authPsk = socket.handshake.auth?.psk;

    const providedPsk =
      (typeof authPsk === "string" && authPsk) ||
      (Array.isArray(headerPsk) ? headerPsk[0] : headerPsk) ||
      (Array.isArray(queryPsk) ? queryPsk[0] : queryPsk);

    if (providedPsk !== requiredPsk) {
      return next(new Error("Unauthorized"));
    }

    next();
  });

  io.on("connection", (socket) => {
    console.log(`Socket connected: ${socket.id}`);

    fs.readdirSync("./src/collectors").forEach((file) => {
      if (file.endsWith(".ts")) {
        const collectorName = file.replace(".ts", "");
        socket.on(collectorName, async (opts, callback) => {
          try {
            const collector = (await import(`../collectors/${file}`)).default;
            const data = await collector(opts);
            callback({ success: true, data });
          } catch (error: Error | unknown) {
            const err = error as any;
            console.error(`❌ Error in ${collectorName}:\n${err.stack}`);
            callback({ success: false, error: err.message });
          }
        });
      }
    });

    socket.on("disconnect", () => {
      console.log(`Socket disconnected: ${socket.id}`);
    });
  });

  httpServer.listen(port, () => {
    console.log(`Socket.IO server listening on port ${port}`);
  });

  return { io, httpServer };
};
