import { Server } from 'http';
import { WebSocketServer, WebSocket } from 'ws';
import logger from '../utils/logger';

export class SimpleWebSocketService {
  private static instance: SimpleWebSocketService;
  private wss: WebSocketServer | null = null;
  private connections = new Map<string, WebSocket>();

  private constructor() {
    logger.info('🔧 SimpleWebSocketService singleton created');
  }

  public static getInstance(): SimpleWebSocketService {
    if (!SimpleWebSocketService.instance) {
      logger.info('🏭 Creating SimpleWebSocketService singleton instance');
      SimpleWebSocketService.instance = new SimpleWebSocketService();
    }
    return SimpleWebSocketService.instance;
  }

  /**
   * Initialize WebSocket server
   */
  initialize(server: Server) {
    try {
      // Import ws dynamically to avoid issues
      const { WebSocketServer } = require('ws');
      
      this.wss = new WebSocketServer({ 
        server,
        path: '/ws'
      });
      
      this.wss.on('connection', (ws: WebSocket, request: any) => {
        this.handleConnection(ws, request);
      });

      logger.info('✅ WebSocket server initialized successfully');
      logger.info('📡 WebSocket endpoint available at ws://localhost:3000/ws');
    } catch (error: any) {
      logger.error('❌ Failed to initialize WebSocket server', { error: error.message });
      logger.info('📡 WebSocket server not available - ws package not installed');
    }
  }

  /**
   * Handle new WebSocket connection
   */
  private handleConnection(ws: WebSocket, request: any) {
    const connectionId = Math.random().toString(36).substring(7);
    this.connections.set(connectionId, ws);

    logger.info('🔌 New WebSocket connection', { connectionId });

    // Send welcome message
    ws.send(JSON.stringify({
      type: 'connected',
      connectionId,
      message: 'Connected to chat server'
    }));

    ws.on('message', (data: any) => {
      this.handleMessage(connectionId, ws, data);
    });

    ws.on('close', () => {
      logger.info('🔌 WebSocket connection closed', { connectionId });
      this.connections.delete(connectionId);
    });

    ws.on('error', (error: any) => {
      logger.error('❌ WebSocket error', { connectionId, error: error.message });
      this.connections.delete(connectionId);
    });
  }

  /**
   * Handle incoming WebSocket message
   */
  private async handleMessage(connectionId: string, ws: WebSocket, data: any) {
    try {
      const message = JSON.parse(data.toString());
      logger.info('📨 WebSocket message received', { connectionId, messageType: message.type });

      if (message.type === 'message') {
        // Show typing indicator
        ws.send(JSON.stringify({ type: 'typing', isTyping: true }));
        
        // Simple echo response for now
        const response = `Echo: ${message.message}`;
        
        // Simulate processing time
        setTimeout(() => {
          ws.send(JSON.stringify({
            type: 'message',
            message: response,
            source: 'agent'
          }));
          
          // Hide typing indicator
          ws.send(JSON.stringify({ type: 'typing', isTyping: false }));
        }, 1000);

      } else if (message.type === 'ping') {
        ws.send(JSON.stringify({ type: 'pong' }));
      }

    } catch (error: any) {
      logger.error('❌ Error handling WebSocket message', { 
        connectionId, 
        error: error.message,
        data: data.toString()
      });
      
      ws.send(JSON.stringify({
        type: 'error',
        message: 'Invalid message format'
      }));
    }
  }

  /**
   * Get connection count
   */
  getConnectionCount(): number {
    return this.connections.size;
  }

  /**
   * Close all connections
   */
  closeAll() {
    this.connections.forEach((ws, connectionId) => {
      logger.info('🔌 Closing WebSocket connection', { connectionId });
      ws.close();
    });
    this.connections.clear();
  }
}

export const simpleWebSocketService = SimpleWebSocketService.getInstance(); 