const { createServer } = require("node:http");
const next = require("next");
const { Server } = require("socket.io");

const dev = process.env.NODE_ENV !== "production";
const hostname = process.env.HOSTNAME || "0.0.0.0";
const port = Number(process.env.PORT || 3000);

const app = next({ dev, hostname, port });
const handle = app.getRequestHandler();

const roomStates = new Map();

app.prepare().then(() => {
  const httpServer = createServer((req, res) => handle(req, res));
  const io = new Server(httpServer, {
    path: "/api/socket",
    cors: {
      origin: process.env.NEXTAUTH_URL || "http://localhost:3000"
    }
  });

  io.on("connection", (socket) => {
    socket.on("room:join", ({ roomSlug, user }) => {
      if (!roomSlug) return;
      socket.join(roomSlug);
      socket.data.roomSlug = roomSlug;
      socket.data.user = user || "Guest";
      socket.emit("room:state", roomStates.get(roomSlug) || null);
      socket.to(roomSlug).emit("presence:join", { user: socket.data.user });
    });

    socket.on("media:set", (payload) => updateRoom(socket, "media:set", payload));
    socket.on("playback:play", (payload) => updateRoom(socket, "playback:play", payload));
    socket.on("playback:pause", (payload) => updateRoom(socket, "playback:pause", payload));
    socket.on("playback:seek", (payload) => updateRoom(socket, "playback:seek", payload));
    socket.on("chat:message", (payload) => relayRoom(socket, "chat:message", payload));

    socket.on("disconnect", () => {
      if (socket.data.roomSlug) {
        socket.to(socket.data.roomSlug).emit("presence:leave", { user: socket.data.user || "Guest" });
      }
    });
  });

  function relayRoom(socket, event, payload) {
    const roomSlug = socket.data.roomSlug;
    if (!roomSlug) return;
    io.to(roomSlug).emit(event, { ...payload, user: socket.data.user || "Guest", at: Date.now() });
  }

  function updateRoom(socket, event, payload) {
    const roomSlug = socket.data.roomSlug;
    if (!roomSlug) return;
    const previous = roomStates.get(roomSlug) || {};
    const nextState = {
      ...previous,
      ...payload,
      lastEvent: event,
      updatedBy: socket.data.user || "Guest",
      updatedAt: Date.now()
    };
    roomStates.set(roomSlug, nextState);
    io.to(roomSlug).emit(event, nextState);
  }

  httpServer.listen(port, hostname, () => {
    console.log(`WatchLink ready on http://${hostname}:${port}`);
  });
});
