import type { Server as HttpServer } from "node:http";
//import { dirname, join } from "node:path";
//import { fileURLToPath } from "node:url";
import { instrument } from "@socket.io/admin-ui";
import { Server } from "socket.io";

import { createLogger } from "../logger/logger.controller.js";
import { allowedOrigins } from "../utils/cors.utils.js";
import { registerEmitter } from "./roomEmitter.socket.js";
import {
	createRoomEmitter,
	preseedRoom,
	registerRoomService,
} from "./roomService.socket.js";

//const __filename = fileURLToPath(import.meta.url);
//const __dirname = dirname(__filename);
const log = createLogger({ module: "socket.io", subModule: "setup" });

import { auth } from "../utils/auth.utils.js";
//import type { Session, User } from "better-auth"; // adjust if needed
import { getRoomConfig } from "./roomDefinitions.socket.js";

// declare module "socket.io" {
// 	interface Socket {
// 		user?: User | any;
// 		session?: Session;
// 	}
// }

export const setupSocketIORoutes = (baseUrl: string, server: HttpServer) => {
	const io = new Server(server, {
		path: `${baseUrl}/api/socket.io`,
		cors: {
			origin: allowedOrigins,
			credentials: true,
		},
	});

	// manage members of the rooms.
	registerRoomService(io);

	// ✅ Create emitter instance
	const { addDataToRoom } = createRoomEmitter(io);
	registerEmitter(addDataToRoom);

	io.use(async (socket, next) => {
		try {
			//const cookieHeader = socket.handshake.headers.cookie;
			const headers = new Headers();

			for (const [key, value] of Object.entries(socket.request.headers)) {
				if (typeof value === "string") {
					headers.set(key, value);
				} else if (Array.isArray(value)) {
					headers.set(key, value.join(", "));
				}
			}

			const session = await auth.api.getSession({
				headers,
			});

			if (!session) {
				return next(); // allow connection, but no auth
			}

			if (session) {
				socket.user = session.user;
				socket.session = session as any;
			}

			next();
		} catch (err) {
			next();
		}
	});

	io.on("connection", (s) => {
		log.info({}, `User connected: ${s.id}`);

		s.emit("welcome", {
			serverTime: Date.now(),
			availableRooms: ["logs", "labels"],
			version: "1.0.0",
		});

		// s.on("join-room", async (rn) => {
		// 	const config = protectedRooms[rn];

		// 	if (config?.requiresAuth && !s.user) {
		// 		return s.emit("room-error", {
		// 			room: rn,
		// 			message: "Authentication required",
		// 		});
		// 	}

		// 	const roles = Array.isArray(config?.role) ? config?.role : [config?.role];

		// 	//if (config?.role && s.user?.role !== config.role) {
		// 	if (config?.role && !roles.includes(s.user?.role)) {
		// 		return s.emit("room-error", {
		// 			roomId: rn,
		// 			message: `Not authorized to be in room: ${rn}`,
		// 		});
		// 	}
		// 	s.join(rn);

		// 	// get room seeded
		// 	const history = await preseedRoom(rn);
		// 	log.info({}, `User joined ${rn}: ${s.id}`);
		// 	// send the intial data
		// 	s.emit("room-update", {
		// 		roomId: rn,
		// 		payloads: history,
		// 		initial: true,
		// 	});
		// });

		s.on("join-room", async (rn: string) => {
			const config = getRoomConfig(rn);

			if (!config) {
				return s.emit("room-error", {
					roomId: rn,
					message: `Unknown room: ${rn}`,
				});
			}

			if (config.requiresAuth && !s.user) {
				return s.emit("room-error", {
					roomId: rn,
					message: "Authentication required",
				});
			}

			const roles = Array.isArray(config.role) ? config.role : [];

			if (roles.length > 0 && !roles.includes(s.user?.role)) {
				return s.emit("room-error", {
					roomId: rn,
					message: `Not authorized to be in room: ${rn}`,
				});
			}

			s.join(rn);

			const history = await preseedRoom(rn as any);

			log.info({}, `User joined ${rn}: ${s.id}`);

			s.emit("room-update", {
				roomId: rn,
				payloads: history,
				initial: true,
			});
		});
		s.on("leave-room", (room) => {
			s.leave(room);
			log.info({}, `${s.id} left room: ${room}`);
		});
	});

	io.on("disconnect", (s) => {
		log.info({}, "User disconnected:", s.id);
	});

	// admin stuff

	const admin = io.of("/admin");
	admin.on("connection", (s) => {
		log.info({}, `User connected: ${s.id}`);
	});

	admin.on("disconnect", (s) => {
		log.info({}, "User disconnected:", s.id);
	});

	instrument(io, {
		auth: false,
		//namespaceName: "/admin",
	});
};
