import express from 'express';
import { Server } from 'socket.io';
import { createServer } from 'http';
import { Client, Notification } from 'pg'; 
import dotenv from 'dotenv';
dotenv.config();

const app = express();
const httpServer = createServer(app);

// Create new Socket.IO server
const io = new Server(httpServer);

const PORT = process.env.PORT || 3030;

const pgClient = new Client({
  connectionString: process.env.DATABASE_URL,
});

const handleNotification = (msg: Notification) => {
  const payload = JSON.parse(msg.payload ?? '{}');
  switch (msg.channel) {
    case 'new_message':
      handleNewMessage(payload);
      break;
    case 'countdown_update':
      handleCountdownUpdate(payload);
      break;
    case 'relationship_status_change':
      handleRelationshipStatusChange(payload);
      break;
    case 'profile_picture_update':
      handleProfilePictureUpdate(payload);
      break;
    default:
      console.log('Unhandled notification:', msg);
  }
};

const handleNewMessage = (payload: any) => {
  const {receiverId, text, id} = payload;
  io.to(`user:${receiverId}`).emit('new_message', payload);
  console.log(`Message sent to room ${receiverId} with text: "${text}"`);
};

const handleCountdownUpdate = (payload: any) => {
  const { relationshipId, countdown } = payload;
  io.to(`relationship:${relationshipId}`).emit('countdown_update', countdown);
  console.log(`Countdown update sent to room ${relationshipId}`);
};

const handleRelationshipStatusChange = (payload: any) => {
  const { relationshipId, status } = payload;
  io.to(`relationship:${relationshipId}`).emit('relationship_status_change', status);
  console.log(`Relationship status change sent to room ${relationshipId}, status: ${status}`);
};

const handleProfilePictureUpdate = (payload: any) => {
  const { userId, profilePictureUrl } = payload;
  io.to(`user:${userId}`).emit('profile_picture_update', profilePictureUrl);
  console.log(`Profile picture update sent to room ${userId}`);
};

// Connect the PostgreSQL client
pgClient.connect()
  .then(() => {
    console.log('Connected to PostgreSQL');
    // Listen for NOTIFY events on the 'new_message' channel
    pgClient.query('LISTEN new_message');
    pgClient.query('LISTEN countdown_update');
    pgClient.query('LISTEN relationship_status_change');
    pgClient.query('LISTEN profile_picture_update');

    pgClient.on('notification', handleNotification);
  })
  .catch((err: unknown) => {
    console.error('Failed to connect to PostgreSQL:', err);
  });

// Handle WebSocket connections
io.on('connection', (socket) => {
  console.log('WebSocket client connected:', socket.id);

  socket.on('join', (roomInfo) => {
    //console.log('Attempting to join room:', roomInfo);
    if (typeof roomInfo === 'object') {
      if (roomInfo.userId) {
        socket.join(`user:${roomInfo.userId}`);
        console.log(`User ${roomInfo.userId} joined room`);
      } else if (roomInfo.relationshipId) {
        socket.join(`relationship:${roomInfo.relationshipId}`);
        console.log(`Relationship ${roomInfo.relationshipId} joined room`);
      }
    }
    //console.log('Socket object at connection:', socket);
  });

  socket.on('error', (error) => {
    console.error('WebSocket error:', error);
  });

  // Handle disconnection of WebSocket clients
  socket.on('disconnect', () => {
    console.log('WebSocket client disconnected:', socket.id);
  });
});

// Start the WebSocket server
httpServer.listen(PORT, () => {
  console.log(`WebSocket server is running on port ${PORT}`);
});
