/**
 * Real-Time Collaboration Service
 * Handles WebSocket-based real-time collaboration
 */

import { Server as SocketIOServer } from 'socket.io';
import { createDocumentComment, getDocumentComments } from '@the-order/database';
import { createDocumentAuditLog } from '@the-order/database';

export interface CollaborationRoom {
  document_id: string;
  users: Set<string>;
}

const rooms = new Map<string, CollaborationRoom>();

/**
 * Initialize collaboration server
 */
export function initializeCollaborationServer(io: SocketIOServer): void {
  io.on('connection', (socket) => {
    console.log('User connected:', socket.id);

    // Join document room
    socket.on('join-document', async (data: { document_id: string; user_id: string }) => {
      const { document_id, user_id } = data;

      socket.join(`document:${document_id}`);

      if (!rooms.has(document_id)) {
        rooms.set(document_id, { document_id, users: new Set() });
      }

      const room = rooms.get(document_id)!;
      room.users.add(user_id);

      // Notify others
      socket.to(`document:${document_id}`).emit('user-joined', { user_id });

      // Send current users
      socket.emit('users-in-room', Array.from(room.users));

      // Load existing comments
      const comments = await getDocumentComments(document_id);
      socket.emit('comments-loaded', { comments });
    });

    // Leave document room
    socket.on('leave-document', (data: { document_id: string; user_id: string }) => {
      const { document_id, user_id } = data;

      socket.leave(`document:${document_id}`);

      const room = rooms.get(document_id);
      if (room) {
        room.users.delete(user_id);
        socket.to(`document:${document_id}`).emit('user-left', { user_id });
      }
    });

    // Add comment
    socket.on('add-comment', async (data: {
      document_id: string;
      comment_text: string;
      user_id: string;
      version_id?: string;
    }) => {
      const { document_id, comment_text, user_id, version_id } = data;

      try {
        const comment = await createDocumentComment({
          document_id,
          version_id,
          comment_text,
          author_id: user_id,
        });

        // Broadcast to all users in room
        io.to(`document:${document_id}`).emit('comment-added', { comment });

        await createDocumentAuditLog({
          document_id,
          version_id,
          action: 'commented',
          performed_by: user_id,
        });
      } catch (error) {
        socket.emit('error', { message: 'Failed to add comment' });
      }
    });

    // Cursor position (for real-time editing)
    socket.on('cursor-move', (data: {
      document_id: string;
      user_id: string;
      position: { line: number; column: number };
    }) => {
      const { document_id, user_id, position } = data;
      socket.to(`document:${document_id}`).emit('cursor-update', { user_id, position });
    });

    // Text change (for real-time editing)
    socket.on('text-change', (data: {
      document_id: string;
      user_id: string;
      change: any; // Operational transform change
    }) => {
      const { document_id, user_id, change } = data;
      socket.to(`document:${document_id}`).emit('text-updated', { user_id, change });
    });

    // Disconnect
    socket.on('disconnect', () => {
      console.log('User disconnected:', socket.id);
      // Clean up rooms
      for (const [docId, room] of rooms.entries()) {
        // Note: In a real implementation, you'd track socket.id to user_id mapping
        // For now, this is simplified
      }
    });
  });
}

/**
 * Get users in document room
 */
export function getUsersInDocument(document_id: string): string[] {
  const room = rooms.get(document_id);
  return room ? Array.from(room.users) : [];
}

