import type { Server as HttpServer } from "node:http";
import { Server } from "socket.io";
import { corsOrigins } from "./config/env.js";
import { verifyToken } from "./lib/auth.js";

type SocketUser = {
  id: string;
  role: "admin" | "user";
};

export type SupportRealtimePayload = {
  conversation: Record<string, unknown>;
  message?: Record<string, unknown>;
};

let io: Server | null = null;

function resolveSocketToken(authHeader?: string, authToken?: string) {
  if (typeof authToken === "string" && authToken.trim()) return authToken.trim();
  if (typeof authHeader === "string" && authHeader.startsWith("Bearer ")) return authHeader.slice(7);
  return null;
}

export function initRealtimeServer(server: HttpServer) {
  io = new Server(server, {
    cors: {
      origin(origin, callback) {
        if (!origin || corsOrigins.includes(origin)) {
          callback(null, true);
          return;
        }

        callback(new Error(`CORS blocked for origin: ${origin}`));
      },
      credentials: true
    }
  });

  io.use((socket, next) => {
    try {
      const token = resolveSocketToken(
        typeof socket.handshake.headers.authorization === "string" ? socket.handshake.headers.authorization : undefined,
        typeof socket.handshake.auth?.token === "string" ? socket.handshake.auth.token : undefined
      );

      if (!token) {
        next(new Error("Authentication required"));
        return;
      }

      const payload = verifyToken(token);
      socket.data.user = {
        id: payload.userId,
        role: payload.role
      } satisfies SocketUser;
      next();
    } catch {
      next(new Error("Invalid token"));
    }
  });

  io.on("connection", (socket) => {
    const user = socket.data.user as SocketUser | undefined;
    if (!user) {
      socket.disconnect();
      return;
    }

    void socket.join(`support:user:${user.id}`);
    if (user.role === "admin") {
      void socket.join("support:admins");
    }
  });

  return io;
}

export function emitSupportConversationUpdated(userId: string, payload: SupportRealtimePayload) {
  if (!io) return;
  io.to("support:admins").emit("support:conversation.updated", payload);
  io.to(`support:user:${userId}`).emit("support:conversation.updated", payload);
}

export function emitSupportMessageCreated(userId: string, payload: SupportRealtimePayload) {
  if (!io) return;
  io.to("support:admins").emit("support:message.created", payload);
  io.to(`support:user:${userId}`).emit("support:message.created", payload);
}
