const express = require('express');
const app = express();
const path = require('path');

require('dotenv').config();
const bodyParser = require('body-parser');
const WebSocket = require('ws');
const { v4: uuidv4 } = require('uuid');
const nodemailer = require('nodemailer');
const db = require('./db');
const cron = require('node-cron');
const moment = require('moment');

const supportEmailTransporter = nodemailer.createTransport({
  service: 'gmail', // or your email provider
  auth: {
    user: process.env.SUPPORT_EMAIL,
    pass: process.env.SUPPORT_EMAIL_PASSWORD
  }
});
const expressWs = require('express-ws')(app);
const activeUsers = new Map();
const getWss = () => {
  return expressWs.getWss('/ws');
};
// Mediasoup configuration
const mediasoup = require('mediasoup');
const os = require('os');

const mediasoupConfig = {
  // Worker settings
  worker: {
    rtcMinPort: 40000,
    rtcMaxPort: 49999,
    logLevel: 'warn'
  },
  // Router settings
  router: {
    mediaCodecs: [
      {
        kind: 'audio',
        mimeType: 'audio/opus',
        clockRate: 48000,
        channels: 2
      },
      {
        kind: 'video',
        mimeType: 'video/VP8',
        clockRate: 90000,
        parameters: {
          'x-google-start-bitrate': 1000
        }
      }
    ]
  },
  // WebRTC transport settings
  webRtcTransport: {
    listenIps: [
      {
        ip: '0.0.0.0',
        announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP || '127.0.0.1' // Replace with your public IP in production
      }
    ],
    initialAvailableOutgoingBitrate: 800000,
    minimumAvailableOutgoingBitrate: 600000,
    maxSctpMessageSize: 262144,
    // Additional transport options
    enableUdp: true,
    enableTcp: true,
    preferUdp: true
  }
};
app.set('view engine', 'ejs');
// Parse URL-encoded bodies (as sent by HTML forms)
app.use(bodyParser.urlencoded({ extended: true }));

// Parse JSON bodies (as sent by API clients)
app.use(bodyParser.json());
// MySQL connection configuration
// const connection = mysql.createConnection({
//   host: "localhost",
//   user: "dev",
//   password: "Sanjudev94$$;",
//   port: 3306,
//   database: "mydb",
//   timezone: 'UTC'
// });
const http = require('http');
const socketIo = require('socket.io');

// Create HTTP server
const server = http.createServer(app);
server.on('error', (err) => {
  if (err.code === 'EADDRINUSE') {
    console.error('Port 3000 is already in use');
    process.exit(1);
  }
});
// Initialize Socket.io
const io = socketIo(server, {
    cors: {
        origin: "http://localhost:3000", // Your frontend URL
        methods: ["GET", "POST"],
        credentials: true
    },
    cookie: {
      name: "io",
      path: "/",
      httpOnly: true,
      sameSite: "lax"
    },
    // allowRequest: async (req, callback) => {
    //   try {
    //     // Extract cookies from handshake
    //     const cookies = parseCookies(req.headers.cookie || '');
    //     const sessionCookie = cookies['connect.sid']; // Adjust to your session cookie name
        
    //     if (!sessionCookie) {
    //       return callback('No session cookie', false);
    //     }
  
    //     // Verify session using your existing session store
    //     const session = await store.get(sessionCookie);
    //     if (!session || !session.valid) {
    //       return callback('Invalid session', false);
    //     }
  
    //     // Additional verification if needed
    //     const companyId = req._query?.companyId;
    //     if (companyId && session.companyId !== companyId) {
    //       return callback('Company ID mismatch', false);
    //     }
  
    //     return callback(null, true);
    //   } catch (error) {
    //     console.error('Socket auth error:', error);
    //     return callback('Authentication error', false);
    //   }
    // },
  
    // allowEIO3: true,
    transports: ['websocket', 'polling'],
    pingTimeout: 60000,
    pingInterval: 25000,
    path: "/socket.io"
});

// io.use((socket, next) => {
//   const session = socket.request.session;
//   if (session?.user?.companyId) {
//     next();
//   } else {
//     next(new Error('Authentication error'));
//   }
// });
io.use((socket, next) => {
  sessionMiddleware(socket.request, {}, next);
});
io.use((socket, next) => {
  const session = socket.request.session;
  if (session && session.user && session.user.companyId) {
    socket.companyId = session.user.companyId;
    next();
  } else {
    next(new Error('Authentication error'));
  }
});//added on 15-05-2025
// commented on 15-05-2025io.use(async (socket, next) => {
//   try {
//     // Get session cookies directly from handshake
//     const cookies = parseCookies(socket.handshake.headers.cookie);
//     const sessionCookie = cookies['connect.sid']; // Adjust based on your session cookie name

//     if (!sessionCookie) {
//       throw new Error('No session found');
//     }

//     // Verify session using your existing session store
//     const session = await store.get(sessionCookie);
    
//     if (!session || !session.valid) {
//       throw new Error('Invalid session');
//     }

//     // Attach verified user data to socket
//     socket.companyId = session.companyId;
//     socket.userId = session.userId;
    
//     next();
//   } catch (error) {
//     console.error('WebSocket auth error:', error);
//     next(new Error('WS_AUTH_FAILED')); // Use specific error code
//   }
// });

// Helper function to parse cookies
// function parseCookies(cookieHeader) {
//   return cookieHeader?.split(';').reduce((cookies, cookie) => {
//     const [name, value] = cookie.trim().split('=');
//     cookies[name] = decodeURIComponent(value);
//     return cookies;
//   }, {}) || {};
// }
io.on('connection', (socket) => {
  console.log(`Socket connected: ${socket.id}, Company ID: ${socket.companyId}`);
    socket.on('join_webinar', (webinarId) => {
      socket.join(webinarId);
      const participant = {
        id: socket.id,
        companyId: socket.companyId,
        name: socket.request.session.user.companyName
    };
    io.to(webinarId).emit('participant_joined', participant);
  });
  socket.on('webinar_chat_message', (data) => {
        io.to(data.webinarId).emit('webinar_chat_message', {
            companyName: socket.request.session.user.companyName,
            message: data.message,
            timestamp: Date.now()
        });
    });
  socket.on('leave_webinar', (webinarId) => {
      socket.leave(webinarId);
  });
  socket.on('disconnect', () => {
    console.log(`Socket disconnected: ${socket.id}`);
  });
  
  // Add your webinar-specific socket handlers here
});
// app.use((req, res) => {
//   res.status(404).send('Page not found - <a href="/">Return to Home</a>');
// });
const session = require('express-session');
const MySQLStore = require('express-mysql-session')(session);
const sessionMiddleware = session({
  store: new MySQLStore({
    // Use the existing db connection instead of new credentials
    createDatabaseTable: true,
    schema: {
      tableName: 'sessions',
      columnNames: {
        session_id: 'session_id',
        expires: 'expires',
        data: 'data'
      }
    }
  }, db), // Pass the db connection
  secret: process.env.SESSION_SECRET || 'your-secret-key',
  resave: false,
  saveUninitialized: false,
  proxy: true,
  cookie: {
    secure: process.env.NODE_ENV === 'production',
    httpOnly: true,
    maxAge: 24 * 60 * 60 * 1000,
    sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax',
    domain: process.env.COOKIE_DOMAIN || undefined
  }
});
app.use(sessionMiddleware);
// Assign session store to app for global access
app.sessionStore = sessionMiddleware.store;
const wrap = middleware => (socket, next) => {
  // Get session ID from cookies
  const sessionId = socket.request.headers.cookie
    ?.split('; ')
    ?.find(row => row.startsWith('connect.sid='))
    ?.split('=')[1];
  
  if (!sessionId) return next(new Error('No session ID'));
  
  // Manually load session
  sessionMiddleware(socket.request, {}, async () => {
    try {
      if (!socket.request.session?.user?.companyId) {
        throw new Error('Not authenticated');
      }
      next();
    } catch (err) {
      next(err);
    }
  });
};
const cors = require('cors');
const requireAuth = (req, res, next) => {
  if (!req.session.user) {
    return res.redirect('/login');
  }
  next();
};
// Enable CORS for all routes
app.use(cors({
  origin: ['http://localhost:3000', 'http://127.0.0.1:3000'],
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));
app.use((req, res, next) => {
  //console.log('Session state:', req.sessionID, req.session);
  next();
});
// Connect to MySQL database
// Verify database connection
db.query('SELECT 1', (err) => {
  if (err) {
    console.error('Database connection failed:', err);
    process.exit(1);
  }
  console.log('Database connection verified');
});
// db.connect((err) => {
//   if (err) {
//     console.error('Error connecting to MySQL database:', err);
//     return;
//   }
//   console.log('Connected to MySQL database');
// });
db.on('error', (err) => {
  console.error('Database error:', err);
});

// Serve static files from the 'public' directory
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'views')));
app.use('/images', express.static(path.join(__dirname, 'images')));


// Define login route
app.get('/login', (req, res) => {
  // Redirect if already logged in
  if (req.session.user) {
    return res.redirect('/entrance');
  }

  const error = req.query.error || '';
  res.render('login', { error });
});
// Handle login form submission
app.post('/login', (req, res) => {
  const { username, password, companyName } = req.body;

  // Query the database to authenticate the user
  const query = `
    SELECT company_id, company_name, email, logo_url, social_media, is_admin 
    FROM companies 
    WHERE (primary_contact_name = ? OR secondary_contact_name = ?) 
      AND company_name = ? 
      AND password = ?`;
  
  db.query(query, [username, username, companyName, password], (error, results) => {
    if (error) {
      console.error('Error querying database:', error);
      return res.status(500).json({ error: 'Server error' }); // Always JSON
    }

    if (results.length > 0) {
      const user = results[0];
      
      req.session.user = {
        companyId: user.company_id,
        companyName: user.company_name,
        email: user.email,
        logoUrl: user.logo_url,
        socialMedia: user.social_media,
        isAdmin: user.is_admin
      };

      req.session.save(err => {
        if (err) {
          console.error('Session save error:', err);
          return res.status(500).json({ error: 'Session error' });
        }

        return res.json({
          success: true,
          token: req.sessionID,
          user: req.session.user,
          redirect: '/entrance'
        });
      });
    } else {
      return res.status(401).json({ error: 'Invalid credentials' });
    }
  });
});
app.get('/api/verify-session', (req, res) => {
  console.log('Verifying session:', req.sessionID, req.session.user); // Debugging
  if (req.session.user) {
    res.json({
      valid: true,
      companyId: req.session.user.companyId
    });
  } else {
    console.log('Session invalid or not found');
    res.status(401).json({ valid: false });
  }
});
// Add these endpoints to your server
app.get('/api/session-status', (req, res) => {
  if (req.session.user) {
    return res.json({
      expiresIn: req.session.cookie.maxAge,
      valid: true
    });
  }
  res.json({ valid: false });
});

app.post('/api/touch-session', (req, res) => {
  if (req.session.user) {
    req.session.touch();
    console.log('Session touched:', req.sessionID); // Debugging
    res.json({ success: true });
  } else {
    console.log('No valid session to touch');
    res.status(401).json({ success: false });
  }
});
app.get('/api/check-session', (req, res) => {
  console.log('Session valid in check-session:', req.session.user);
  if (req.session.user) {
    console.log('Session valid in check-session1:', req.session.user);
    res.json({
      authenticated: true,
      token: req.sessionID,
      user: req.session.user
    });
    console.log('Token in check-session2:', req.sessionID);

  } else {
    res.status(401).json({ authenticated: false });
  }
});
app.get('/', (req, res) => {
  res.redirect('/login');
});

// Define route to serve entrance.html
// app.get('/entrance', (req, res) => {
//   res.sendFile(path.join(__dirname, 'views', 'entrance.html'));
// });
// Change this route in server.js
app.get('/entrance',requireAuth, (req, res) => {
  console.log('Successful entrance access:', req.session.user);
  const user = req.session.user;
  if (!user) {
    return res.redirect('/login');
  }
  res.sendFile(path.join(__dirname, 'views', 'entrance.html')); // Serve HTML file directly
});
// Logout route
app.get('/logout', (req, res) => {
  // Destroy session and redirect to login page
  req.session.destroy((err) => {
    if (err) {
      console.error('Error destroying session:', err);
    }
    res.redirect('/login');
  });
});
// Fetch image URLs based on selected_booth values
app.get('/thumbnails', requireAuth,(req, res) => {
  // Query the database to fetch selected_booth and company name values
  db.query('SELECT selected_booth, company_name, company_id FROM companies WHERE row_state = -1', (error, results, fields) => {
      if (error) {
          console.error('Error fetching data from database:', error);
          res.status(500).json({ error: 'Internal Server Error' });
      } else {
          // Map selected_booth values to image URLs and company names
          const thumbnails = results.map(result => ({
              imageUrl: `newthumbs/image${result.selected_booth}.png`,
              boothUrl: `booths/image${result.selected_booth}.png`,
              companyName: result.company_name,
              companyId: result.company_id
          }));
          res.json({ thumbnails });
      }
  });
});
app.get('/media', (req, res) => {
  const mediaType = req.query.mediaType;
  const companyId = req.query.companyId; // Assuming company ID is passed as a query parameter

  // Fetch media URLs based on the media type and company ID
  const query = 'SELECT media_url FROM media WHERE media_type = ? AND company_id = ?';
  db.query(query, [mediaType, companyId], (error, results) => {
    if (error) {
      console.error('Error fetching media URLs:', error);
      res.status(500).json({ error: 'Internal Server Error' });
    } else {
      // Extract media URLs from the query results
      const mediaUrls = results.map(result => result.media_url);
      console.log('mediaUrls:', mediaUrls);
      res.json({ mediaUrls });
    }
  });
});
// Mediasoup workers and rooms
let mediasoupWorkers = [];
let webinarRooms = new Map(); // webinarId -> room data

// Initialize mediasoup workers
async function initializeMediasoupWorkers() {
  const numWorkers = Object.keys(os.cpus()).length;
  
  for (let i = 0; i < numWorkers; i++) {
    const worker = await mediasoup.createWorker(mediasoupConfig.worker);
    worker.on('died', () => {
      console.error('Mediasoup worker died, exiting...');
      process.exit(1);
    });
    
    mediasoupWorkers.push(worker);
  }
  
  console.log(`Initialized ${mediasoupWorkers.length} mediasoup workers`);
}

initializeMediasoupWorkers().catch(err => console.error('Mediasoup worker init error:', err));
// Webinar room management
async function createWebinarRoom(webinarId, options = {}) {
  const worker = mediasoupWorkers[webinarRooms.size % mediasoupWorkers.length];
  const router = await worker.createRouter(mediasoupConfig.router);
  
  const room = {
    id: webinarId,
    router,
    transports: new Map(),
    producers: new Map(),
    consumers: new Map(),
    participants: new Map(),
    options: {
      isRecording: options.isRecording || false,
      maxParticipants: options.maxParticipants || 100,
      isActive: true
    },
    createdAt: new Date()
  };
  
  webinarRooms.set(webinarId, room);
  return room;
}

function getWebinarRoom(webinarId) {
  return webinarRooms.get(webinarId);
}

function closeWebinarRoom(webinarId) {
  const room = webinarRooms.get(webinarId);
  if (!room) return;
  
  // Close all transports
  room.transports.forEach(transport => transport.close());
  room.router.close();
  
  webinarRooms.delete(webinarId);
}

// Clean up inactive rooms periodically
setInterval(() => {
  const now = new Date();
  webinarRooms.forEach((room, webinarId) => {
    // Close rooms that have been inactive for over 24 hours
    if (now - room.lastActivity > 24 * 60 * 60 * 1000) {
      closeWebinarRoom(webinarId);
    }
  });
}, 60 * 60 * 1000); // Check hourly

app.get('/api/webinars/:webinarId/participants', (req, res) => {
  const webinarId = req.params.webinarId;
  
  db.query(`
      SELECT p.company_id as id, c.company_name as name, p.is_presenter
      FROM webinar_participants p
      JOIN companies c ON p.company_id = c.company_id
      WHERE p.webinar_id = ? AND p.left_at IS NULL
  `, [webinarId], (err, results) => {
      if (err) return res.status(500).json({ error: err.message });
      res.json(results);
  });
});

app.post('/api/update-presence', (req, res) => {
  const companyId = req.session.user?.companyId; // Get companyId from session

  if (!companyId) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  const query = `
    INSERT INTO presence (company_id, last_active) 
    VALUES (?, NOW()) 
    ON DUPLICATE KEY UPDATE last_active = NOW()`;

  db.query(query, [companyId], (err) => {
    if (err) {
      return res.status(500).json({ error: err.message });
    }
    res.json({ success: true });
  });
});
// server.js
app.get('/webinar-room', requireAuth,(req, res) => {
  if (!req.session.user?.companyId) {
    return res.redirect('/login');
  }
  res.sendFile(path.join(__dirname, 'views/webinar-room.html'));
});
// Webinar status update function
function updateWebinarStatus(webinarId, status) {
  const query = `
      UPDATE webinars SET status = ?
      WHERE webinar_id = ?
  `;
  
  db.query(query, [status, webinarId], (err) => {
      if (err) return console.error('Status update error:', err);
      
      io.to(webinarId).emit('webinar_status', {
          webinarId,
          status,
          timestamp: new Date()
      });
  });
}
// Current user endpoint
app.get('/api/current-user', (req, res) => {
  if (!req.session.user) {
    console.log('No user in session');
    return res.status(401).json({ error: 'Unauthorized' });
  }
  res.json({
    companyId: req.session.user.companyId,
    companyName: req.session.user.companyName,
    isAdmin: req.session.user.isAdmin || false
  });
});
// Add these routes and functions to your existing server.js

// Schedule a meeting
app.post('/api/schedule-meeting', (req, res) => {
  const { title, scheduledTime, duration, participantIds } = req.body;
  const organizerId = req.session.user?.companyId;
  const roomId = uuidv4();

  if (!organizerId) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  db.beginTransaction(err => {
    if (err) return res.status(500).json({ error: err.message });

    // Insert the meeting
    db.query(
      'INSERT INTO scheduled_meetings (title, organizer_id, scheduled_time, duration_minutes, room_id) VALUES (?, ?, ?, ?, ?)',
      [title, organizerId, scheduledTime, duration, roomId],
      (err, results) => {
        if (err) {
          return db.rollback(() => {
            res.status(500).json({ error: err.message });
          });
        }

        const meetingId = results.insertId;
        const participants = participantIds.map(pid => [meetingId, pid]);

        // Add participants
        db.query(
          'INSERT INTO meeting_participants (meeting_id, company_id) VALUES ?',
          [participants],
          (err) => {
            if (err) {
              return db.rollback(() => {
                res.status(500).json({ error: err.message });
              });
            }

            db.commit(err => {
              if (err) {
                return db.rollback(() => {
                  res.status(500).json({ error: err.message });
                });
              }

              // Notify participants
              participantIds.forEach(pid => {
                if (activeUsers.has(pid)) {
                  activeUsers.get(pid).send(JSON.stringify({
                    type: 'meeting_scheduled',
                    meetingId,
                    title,
                    scheduledTime,
                    organizerId,
                    organizerName: req.session.user.companyName,
                    roomId
                  }));
                }
              });

              res.json({ success: true, meetingId, roomId });
            });
          }
        );
      }
    );
  });
});

// Get scheduled meetings
app.get('/api/scheduled-meetings', (req, res) => {
  const companyId = req.session.user?.companyId;
  if (!companyId) return res.status(401).json({ error: 'Unauthorized' });

  db.query(`
    SELECT sm.*, c.company_name as organizer_name 
    FROM scheduled_meetings sm
    JOIN companies c ON sm.organizer_id = c.company_id
    JOIN meeting_participants mp ON sm.id = mp.meeting_id
    WHERE mp.company_id = ? AND sm.status = 'scheduled'
    ORDER BY sm.scheduled_time ASC
  `, [companyId], (err, results) => {
    if (err) return res.status(500).json({ error: err.message });
    res.json(results);
  });
});

// Start a meeting (1:1 or group)
app.post('/api/start-meeting', (req, res) => {
  const { meetingId, participantIds } = req.body;
  const callerId = req.session.user?.companyId;

  if (!callerId) return res.status(401).json({ error: 'Unauthorized' });

  const roomId = meetingId ? uuidv4() : null;

  if (meetingId) {
    // Group meeting
    db.query(
      'UPDATE scheduled_meetings SET status = "ongoing", room_id = ? WHERE id = ?',
      [roomId, meetingId],
      (err) => {
        if (err) return res.status(500).json({ error: err.message });

        // Notify participants
        db.query(
          'SELECT company_id FROM meeting_participants WHERE meeting_id = ?',
          [meetingId],
          (err, results) => {
            if (err) return res.status(500).json({ error: err.message });

            const participants = results.map(r => r.company_id);
            participants.forEach(pid => {
              if (pid !== callerId && activeUsers.has(pid)) {
                activeUsers.get(pid).send(JSON.stringify({
                  type: 'meeting_started',
                  meetingId,
                  roomId,
                  callerId,
                  callerName: req.session.user.companyName
                }));
              }
            });

            res.json({ success: true, roomId });
          }
        );
      }
    );
  } else {
    // 1:1 call
    if (!participantIds || participantIds.length !== 1) {
      return res.status(400).json({ error: 'Exactly one participant required for 1:1 call' });
    }

    const receiverId = participantIds[0];
    if (activeUsers.has(receiverId)) {
      activeUsers.get(receiverId).send(JSON.stringify({
        type: 'call_request',
        callerId,
        callerName: req.session.user.companyName,
        roomId: uuidv4()
      }));
    }

    res.json({ success: true });
  }
});


// Helper functions
function handleCallRequest(data) {
  const receiverWs = activeUsers.get(data.receiverId);
  if (receiverWs) {
    receiverWs.send(JSON.stringify({
      type: 'call_request',
      callerId: data.callerId,
      callerName: data.callerName,
      roomId: data.roomId
    }));
  }
}
function handleIncomingCall(data) {
  const receiverWs = activeUsers.get(data.receiverId);
  if (receiverWs) {
    receiverWs.send(JSON.stringify({
      type: 'incoming_call',
      callerId: data.callerId,
      callerName: data.callerName,
      roomId: data.roomId
    }));
  }
}
function handleCallResponse(data) {
  const callerWs = activeUsers.get(data.callerId);
  if (callerWs) {
    callerWs.send(JSON.stringify({
      type: 'call_response',
      accepted: data.accepted,
      receiverId: data.receiverId,
      receiverName: data.receiverName,
      roomId: data.roomId
    }));
  }
}

function forwardICECandidate(data) {
  const targetWs = activeUsers.get(data.targetId);
  if (targetWs) {
    targetWs.send(JSON.stringify({
      type: 'ice_candidate',
      candidate: data.candidate,
      roomId: data.roomId
    }));
  }
}

function handleJoinMeeting(data) {
  // Broadcast to all participants that someone joined
  db.query(
    'SELECT company_id FROM meeting_participants WHERE meeting_id = ?',
    [data.meetingId],
    (err, results) => {
      if (err) return console.error(err);

      results.forEach(participant => {
        if (activeUsers.has(participant.company_id) && participant.company_id !== data.userId) {
          activeUsers.get(participant.company_id).send(JSON.stringify({
            type: 'participant_joined',
            meetingId: data.meetingId,
            userId: data.userId,
            userName: data.userName
          }));
        }
      });
    }
  );
}
function broadcastDiscussion(discussion) {
  const wss = expressWs.getWss('/ws');// Get the WebSocket server instance
  
  wss.clients.forEach(client => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(JSON.stringify({
        type: 'new_discussion',
        discussion: {
          id: discussion.id,
          title: discussion.title,
          content: discussion.content,
          created_at: discussion.created_at,
          creatorName: discussion.creatorName,
          participantCount: discussion.participantCount || 0
        }
      }));
    }
  });
}

function broadcastComment(comment) {
  const wss = expressWs.getWss('/ws'); // Get the WebSocket server instance
  
  wss.clients.forEach(client => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(JSON.stringify({
        type: 'new_comment',
        comment: {
          id: comment.id,
          discussion_id: comment.discussion_id,
          content: comment.content,
          created_at: comment.created_at,
          authorName: comment.authorName,
          company_id: comment.company_id
        }
      }));
    }
  });
}
//webrtc code ended

// Add after HTTP server creation
//const wss = new WebSocket.Server({ server: app.listen(3001) });


// WebSocket route
app.ws('/ws', wrap(sessionMiddleware), (ws, req) => {
  const user = req.session.user;
  
  if (!user?.companyId) {
    console.log('WebSocket connection rejected - no session user');
    ws.close();
    return;
  }

  console.log('WebSocket connection established for company:', user.companyId); // Fixed variable name

  // Add user to active users
  activeUsers.set(user.companyId, ws);
  console.log('Current active users:', Array.from(activeUsers.keys()));

  // Handle messages
  ws.on('message', (message) => {
    console.log('Received WebSocket message:', message); // Debug
    const data = JSON.parse(message);
    if (data.type && data.type.startsWith('webinar_')) {
      handleWebinarWebSocketMessages(ws, message);
      return;
    }
    switch (data.type) {
      
      case 'direct_message':
        console.log('Direct message data:', data);
        handleDirectMessage(data, ws);
        break;
      case 'meeting_invite':
        handleMeetingInvite(data);
        break;
      case 'call_request':
        handleCallRequest(data);
        break;
      case 'incoming_call':
        handleIncomingCall(data);
        break;
      case 'call_response':
        handleCallResponse(data);
        break;
      case 'ice_candidate':
        forwardICECandidate(data);
        break;
      case 'join_meeting':
        handleJoinMeeting(data);
        break;
      case 'leave_meeting':
        handleLeaveMeeting(data);
        break;
      case 'new_discussion':
        broadcastDiscussion(data.discussion);
        break;
      case 'new_comment':
        broadcastComment(data.comment);
        break;
    }
  });

  // Remove user on disconnect
  ws.on('close', () => {
    if (user?.companyId) { // Use the user from session
      console.log('WebSocket closed for:', user.companyId);
      activeUsers.delete(user.companyId);
      console.log('Remaining active users:', Array.from(activeUsers.keys()));
      broadcastPresenceUpdate();
    }
  });
});
// server.js (backend)
app.get('/api/chat-history', (req, res) => {
  const { senderId, receiverId } = req.query;

  if (!senderId || !receiverId) {
    return res.status(400).json({ error: 'senderId and receiverId are required' });
  }

  db.query(
      `SELECT 
      m.sender_id, 
      m.receiver_id, 
      m.content, 
      m.sent_at,
      sender.company_name as sender_name,
      receiver.company_name as receiver_name
    FROM direct_messages m
    LEFT JOIN companies sender ON m.sender_id = sender.company_id
    LEFT JOIN companies receiver ON m.receiver_id = receiver.company_id
    WHERE (m.sender_id = ? AND m.receiver_id = ?) 
      OR (m.sender_id = ? AND m.receiver_id = ?)
    ORDER BY m.sent_at ASC`,
    [senderId, receiverId, receiverId, senderId],
    (err, results) => {
      if (err) return res.status(500).json({ error: err.message });
      res.json(results);
    }
  );
});
// server.js (backend)
function handleDirectMessage(data, ws) {
  const { senderId, receiverId, content } = data;

  // Debug: Check if senderId is valid
  if (!senderId) {
    console.error('Sender ID is missing:', data);
    return;
  }

  // Fetch sender's company name
  db.query(
    'SELECT company_name FROM companies WHERE company_id = ?',
    [senderId],
    (err, results) => {
      if (err) {
        console.error('Error fetching sender name:', err);
        return;
      }

      const senderName = results[0].company_name;

      // Save message to database
      db.query(
        'INSERT INTO direct_messages (sender_id, receiver_id, content) VALUES (?, ?, ?)',
        [senderId, receiverId, content],
        (err) => {
          if (err) {
            console.error('Error saving message:', err);
            return;
          }

          // Forward message to recipient if online
          if (activeUsers.has(receiverId)) {
            activeUsers.get(receiverId).send(JSON.stringify({
              type: 'direct_message',
              senderId,
              senderName, // Include sender's name
              content
            }));
          }
        }
      );
    }
  );
}
// Handle meeting invites
function handleMeetingInvite(data) {
  const { senderId, receiverId } = data;
  const roomId = uuidv4();

  // Fetch sender's company name
  db.query(
    'SELECT company_name FROM companies WHERE company_id = ?',
    [senderId],
    (err, results) => {
      if (err) {
        console.error('Error fetching sender name:', err);
        return;
      }

      const senderName = results[0].company_name;

      // Save the meeting to the database
      db.query(
        'INSERT INTO scheduled_meetings (company_id, title, meeting_time, room_id, participants) VALUES (?, ?, NOW(), ?, ?)',
        [senderId, `Meeting between ${senderName} and ${receiverId}`, roomId, JSON.stringify([receiverId])],
        (err) => {
          if (err) return console.error('Error saving meeting:', err);

          // Send invite to recipient
          if (activeUsers.has(receiverId)) {
            activeUsers.get(receiverId).send(JSON.stringify({
              type: 'meeting_invite',
              senderId,
              senderName, // Include sender's name
              roomId,
              message: `You have been invited to a meeting by ${senderName}. Click to join.`
            }));
          }
        }
      );
    }
  );
}
// Presence checker every 30 seconds
setInterval(() => {
  const activeIds = [...activeUsers.keys()];
  console.log('Active users:', activeIds); // Log active users

  if (activeIds.length === 0) return;

  db.query(
    'UPDATE presence SET last_active = NOW() WHERE company_id IN (?)',
    [activeIds],
    (err) => {
      if (err) console.error('Error updating presence:', err);
    }
  );
}, 30000);
function broadcastPresenceUpdate() {
  const activeIds = [...activeUsers.keys()];
  const wss = expressWs.getWss('/ws');
  wss.clients.forEach(client => {
    if (client.readyState === client.OPEN) {
      client.send(JSON.stringify({
        type: 'presence_update',
        companies: activeIds
      }));
    }
  });
}

// Update every 30 seconds
setInterval(broadcastPresenceUpdate, 30000);
app.get('/api/companies', (req, res) => {
  if (!req.session.user) return res.status(401).send('Unauthorized');
  
  db.query(`
    SELECT c.company_id, c.company_name, c.logo_url, 
           c.primary_contact_name, c.email, c.website_url,
           p.last_active
    FROM companies c
    LEFT JOIN presence p ON c.company_id = p.company_id
    WHERE c.status = 'paid' AND c.company_id != ?
  `, [req.session.user.companyId], (err, results) => {
    if (err) return res.status(500).json({ error: err.message });

    const companies = results.map(company => ({
      ...company,
      status: activeUsers.has(company.company_id) ? 'available' : 'offline'
    }));

    res.json(companies);
  });
});
app.get('/api/company/:id', (req, res) => {
  db.query(`
    SELECT company_name, primary_contact_name, email, website_url, social_media
    FROM companies
    WHERE company_id = ?
  `, [req.params.id], (err, results) => {
    if (err || results.length === 0) {
      return res.status(404).json({ error: 'Company not found' });
    }
    res.json(results[0]);
  });
});
app.get('/api/meeting-history', (req, res) => {
  const companyId = req.session.user?.companyId;
  if (!companyId) return res.status(401).json({ error: 'Unauthorized' });

  db.query(
    `SELECT id, title, meeting_time, room_id 
     FROM scheduled_meetings 
     WHERE company_id = ? 
     ORDER BY meeting_time DESC`,
    [companyId],
    (err, results) => {
      if (err) return res.status(500).json({ error: err.message });
      res.json(results);
    }
  );
});


// Schedule a cron job to check for upcoming meetings every minute
// cron.schedule('* * * * *', () => {
//   const reminderTime = new Date(Date.now() + 15 * 60000); // 15 minutes from now

//   db.query(
//     `SELECT company_id, title, meeting_time, room_id 
//      FROM scheduled_meetings 
//      WHERE meeting_time BETWEEN NOW() AND ?`,
//     [reminderTime],
//     (err, results) => {
//       if (err) return console.error('Error fetching upcoming meetings:', err);

//       results.forEach(meeting => {
//         if (activeUsers.has(meeting.company_id)) {
//           activeUsers.get(meeting.company_id).send(JSON.stringify({
//             type: 'meeting_reminder',
//             title: meeting.title,
//             meetingTime: meeting.meeting_time,
//             roomId: meeting.room_id,
//             message: `Reminder: Your meeting "${meeting.title}" is scheduled at ${new Date(meeting.meeting_time).toLocaleString()}.`
//           }));
//         }
//       });
//     }
//   );
// });
// Discussion API Endpoints
// Update the discussions endpoint
app.get('/api/discussions', (req, res) => {
  const page = parseInt(req.query.page) || 1;
  const limit = parseInt(req.query.limit) || 10;
  const offset = (page - 1) * limit;

  db.query(`
      SELECT d.id, d.title, d.content, 
           d.created_at as created_at,
           d.creator_id,
           c.company_name as creatorName,
           (SELECT COUNT(*) FROM discussion_participants 
            WHERE discussion_id = d.id) as participantCount
    FROM discussions d
    JOIN companies c ON d.creator_id = c.company_id
    WHERE d.is_deleted = FALSE
    ORDER BY d.created_at DESC
    LIMIT ? OFFSET ?
  `, [limit, offset], (err, results) => {
      if (err) {
          console.error('Database error:', err);
          return res.status(500).json({ 
              error: 'Failed to fetch discussions',
              details: err.message 
          });
      }
      
      db.query('SELECT COUNT(*) as total FROM discussions', (err, countResult) => {
          if (err) {
              console.error('Count error:', err);
              return res.status(500).json({ 
                  error: 'Failed to count discussions',
                  details: err.message 
              });
          }
          
          res.json({
              discussions: results.map(r => ({
                  id: r.id,
                  title: r.title,
                  content: r.content,
                  created_at: r.created_at * 1000, // Convert to milliseconds
                  creatorName: r.creatorName,
                  participantCount: r.participantCount || 0,
                  creator_id: r.creator_id
              })),
              total: countResult[0].total,
              page,
              totalPages: Math.ceil(countResult[0].total / limit)
          });
      });
  });
});

app.post('/api/discussions', (req, res) => {
  const { title, content, creatorId } = req.body;

  if (!title || !content || !creatorId) {
    return res.status(400).json({ 
      error: 'Missing required fields (title, content, creatorId)' 
    });
  }

  db.beginTransaction(err => {
    if (err) {
      return res.status(500).json({ 
        error: 'Failed to start transaction',
        details: err.message 
      });
    }

    // 1. Insert discussion
    db.query(
      `INSERT INTO discussions (title, content, creator_id, created_at, updated_at)
       VALUES (?, ?, ?, NOW(), NOW())`,
      [title, content, creatorId],
      (err, result) => {
        if (err) {
          return db.rollback(() => {
            res.status(500).json({ 
              error: 'Failed to create discussion',
              details: err.message 
            });
          });
        }

        const discussionId = result.insertId;

        // 2. Add creator as participant
        db.query(
          `INSERT INTO discussion_participants (discussion_id, company_id)
           VALUES (?, ?)`,
          [discussionId, creatorId],
          (err) => {
            if (err) {
              return db.rollback(() => {
                res.status(500).json({ 
                  error: 'Failed to add participant',
                  details: err.message 
                });
              });
            }

            // 3. Get full discussion details
            db.query(
              `SELECT 
                d.*, 
                c.company_name as creatorName,
                UNIX_TIMESTAMP(d.created_at) as created_at_timestamp,
                (SELECT COUNT(*) FROM discussion_participants 
                 WHERE discussion_id = d.id) as participantCount
               FROM discussions d
               JOIN companies c ON d.creator_id = c.company_id
               WHERE d.id = ?`,
              [discussionId],
              (err, results) => {
                if (err || results.length === 0) {
                  return db.rollback(() => {
                    res.status(500).json({ 
                      error: 'Failed to fetch new discussion' 
                    });
                  });
                }

                db.commit(err => {
                  if (err) {
                    return db.rollback(() => {
                      res.status(500).json({ 
                        error: 'Failed to commit transaction',
                        details: err.message 
                      });
                    });
                  }

                  const discussion = results[0];
                  discussion.created_at = discussion.created_at_timestamp * 1000;
                  delete discussion.created_at_timestamp;

                  broadcastDiscussion(discussion);
                  res.json(discussion);
                });
              }
            );
          }
        );
      }
    );
  });
});
// Get Comments Endpoint
app.get('/api/comments', (req, res) => {
  const discussionId = req.query.discussionId;
  
  db.query(`
      SELECT c.*, comp.company_name as authorName
      FROM discussion_comments c
      JOIN companies comp ON c.company_id = comp.company_id
      WHERE c.discussion_id = ?
      ORDER BY c.created_at DESC
  `, [discussionId], (err, results) => {
      if (err) return res.status(500).json({ error: err.message });
      
      res.json(results.map(r => ({
          id: r.id,
          content: r.content,
          created_at: r.created_at,
          authorName: r.authorName
      })));
  });
});

// Post Comment Endpoint
// server.js - Complete Comment POST Endpoint with Real-Time Broadcasting
app.post('/api/comments', (req, res) => {
  const { discussionId, content, companyId } = req.body;

  // Validate input
  if (!discussionId || !content || !companyId) {
    return res.status(400).json({ 
      error: 'Missing required fields (discussionId, content, companyId)' 
    });
  }

  // Start transaction for atomic operations
  db.beginTransaction(err => {
    if (err) {
      return res.status(500).json({ 
        error: 'Failed to start transaction',
        details: err.message 
      });
    }

    // 1. Insert the new comment
    db.query(
      `INSERT INTO discussion_comments 
       (discussion_id, company_id, content) 
       VALUES (?, ?, ?)`,
      [discussionId, companyId, content],
      (err, result) => {
        if (err) {
          return db.rollback(() => {
            res.status(500).json({ 
              error: 'Failed to insert comment',
              details: err.message 
            });
          });
        }

        // 2. Get the full comment with author info
        db.query(
          `SELECT c.id, c.discussion_id, c.company_id, c.content, 
                  c.created_at, comp.company_name as authorName
           FROM discussion_comments c
           JOIN companies comp ON c.company_id = comp.company_id
           WHERE c.id = ?`,
          [result.insertId],
          (err, results) => {
            if (err || results.length === 0) {
              return db.rollback(() => {
                res.status(500).json({ 
                  error: 'Failed to fetch new comment',
                  details: err?.message || 'Comment not found after insert' 
                });
              });
            }

            const newComment = results[0];

            // 3. Add participant if not already participating
            db.query(
              `INSERT IGNORE INTO discussion_participants
               (discussion_id, company_id)
               VALUES (?, ?)`,
              [discussionId, companyId],
              (err) => {
                if (err) {
                  return db.rollback(() => {
                    res.status(500).json({ 
                      error: 'Failed to add participant',
                      details: err.message 
                    });
                  });
                }

                // Commit the transaction
                db.commit(err => {
                  if (err) {
                    return db.rollback(() => {
                      res.status(500).json({ 
                        error: 'Failed to commit transaction',
                        details: err.message 
                      });
                    });
                  }
                  newComment.created_at = new Date(newComment.created_at).getTime();

                  // Broadcast the new comment to all connected clients
                  broadcastComment(newComment);

                  // Send response to the client that made the request
                  res.json({
                    id: newComment.id,
                    content: newComment.content,
                    created_at: newComment.created_at,
                    authorName: newComment.authorName,
                    discussionId: newComment.discussion_id
                  });
                });
              }
            );
          }
        );
      }
    );
  });
});
// Add this new route
app.delete('/api/discussions/:id', (req, res) => {
  const discussionId = req.params.id;
  const userId = req.session.user?.companyId;
  const { reason } = req.body;

  if (!userId) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  db.beginTransaction(err => {
    // 1. First verify discussion exists and get creator_id
    db.query(
      `SELECT creator_id FROM discussions WHERE id = ? AND is_deleted = FALSE`,
      [discussionId],
      (err, results) => {
        if (err) {
          return db.rollback(() => {
            res.status(500).json({ error: 'Database error' });
          });
        }

        if (results.length === 0) {
          return db.rollback(() => {
            res.status(404).json({ error: 'Discussion not found' });
          });
        }

        const isCreator = results[0].creator_id == userId;
        const isAdmin = req.session.user?.isAdmin;

        if (!isCreator && !isAdmin) {
          return db.rollback(() => {
            res.status(403).json({ error: 'Not authorized' });
          });
        }

        // 2. Archive discussion
        db.query(
          `INSERT INTO archived_discussions 
           (original_id, title, content, creator_id, created_at, deleted_by, deletion_reason)
           SELECT id, title, content, creator_id, created_at, ?, ?
           FROM discussions WHERE id = ?`,
          [userId, reason || null, discussionId],
          (err) => {
            if (err) {
              console.error('Archive error:', err);
              return db.rollback(() => {
                res.status(500).json({ 
                  error: 'Failed to archive discussion',
                  details: err.message 
                });
              });
            }

            // 3. Mark as deleted
            db.query(
              `UPDATE discussions SET is_deleted = TRUE WHERE id = ?`,
              [discussionId],
              (err) => {
                if (err) {
                  return db.rollback(() => {
                    res.status(500).json({ error: 'Failed to delete' });
                  });
                }

                db.commit(err => {
                  if (err) {
                    return db.rollback(() => {
                      res.status(500).json({ error: 'Commit failed' });
                    });
                  }

                  // Broadcast deletion
                  const wss = expressWs.getWss('/ws');
                  wss.clients.forEach(client => {
                    if (client.readyState === WebSocket.OPEN) {
                      client.send(JSON.stringify({
                        type: 'discussion_deleted',
                        discussionId: discussionId
                      }));
                    }
                  });

                  res.json({ success: true });
                });
              }
            );
          }
        );
      }
    );
  });
});
app.post('/api/discussions/:id/restore', (req, res) => {
  const discussionId = req.params.id;
  const userId = req.session.user?.companyId;

  if (!userId || !req.session.user?.isAdmin) {
    return res.status(403).json({ error: 'Admin access required' });
  }

  db.beginTransaction(err => {
    // 1. Get archived discussion
    db.query(
      `SELECT * FROM archived_discussions WHERE original_id = ?`,
      [discussionId],
      (err, results) => {
        if (err || !results.length) {
          return db.rollback(() => {
            res.status(404).json({ error: 'Archived discussion not found' });
          });
        }

        const archived = results[0];

        // 2. Restore to discussions table
        db.query(
          `UPDATE discussions SET 
           title = ?, content = ?, is_deleted = FALSE
           WHERE id = ?`,
          [archived.title, archived.content, discussionId],
          (err) => {
            if (err) {
              return db.rollback(() => {
                res.status(500).json({ error: 'Failed to restore discussion' });
              });
            }

            // 3. Delete from archive
            db.query(
              `DELETE FROM archived_discussions WHERE original_id = ?`,
              [discussionId],
              (err) => {
                if (err) {
                  return db.rollback(() => {
                    res.status(500).json({ error: 'Failed to clean archive' });
                  });
                }

                db.commit(err => {
                  if (err) {
                    return db.rollback(() => {
                      res.status(500).json({ error: 'Failed to commit transaction' });
                    });
                  }

                  res.json({ success: true });
                });
              }
            );
          }
        );
      }
    );
  });
});
app.get('/api/admin/archived-discussions', (req, res) => {
  if (!req.session.user?.isAdmin) {
    return res.status(403).json({ error: 'Admin access required' });
  }

  db.query(`
    SELECT a.*, c.company_name as creator_name, 
           d.company_name as deleter_name
    FROM archived_discussions a
    JOIN companies c ON a.creator_id = c.company_id
    JOIN companies d ON a.deleted_by = d.company_id
    ORDER BY a.deleted_at DESC
  `, (err, results) => {
    if (err) return res.status(500).json({ error: err.message });
    res.json(results);
  });
});
// Support endpoint
app.post('/api/support', (req, res) => {
  const { name, email, phone, message } = req.body;
  
  if (!email || !message) {
    return res.status(400).json({ error: 'Email and message are required' });
  }

  db.beginTransaction(err => {
    // 1. Store in database
    db.query(
      `INSERT INTO support_requests (name, email, phone, message)
       VALUES (?, ?, ?, ?)`,
      [name || null, email, phone || null, message],
      (err, result) => {
        if (err) {
          return db.rollback(() => {
            console.error('Database error:', err);
            res.status(500).json({ error: 'Failed to save request' });
          });
        }

        // 2. Send email notification
        const mailOptions = {
          from: process.env.SUPPORT_EMAIL,
          to: process.env.SUPPORT_TEAM_EMAIL,
          subject: 'New Support Request',
          html: `
            <h3>New Support Request</h3>
            <p><strong>Name:</strong> ${name || 'Not provided'}</p>
            <p><strong>Email:</strong> ${email}</p>
            <p><strong>Phone:</strong> ${phone || 'Not provided'}</p>
            <p><strong>Message:</strong></p>
            <p>${message}</p>
            <p>Request ID: ${result.insertId}</p>
          `
        };

        supportEmailTransporter.sendMail(mailOptions, (err) => {
          if (err) {
            return db.rollback(() => {
              console.error('Email error:', err);
              res.status(500).json({ error: 'Failed to send notification' });
            });
          }

          db.commit(err => {
            if (err) {
              return db.rollback(() => {
                res.status(500).json({ error: 'Failed to commit transaction' });
              });
            }

            res.json({ success: true });
          });
        });
      }
    );
  });
});
//webinar code started
// Webinar API endpoints
// Add this before your API routes
app.use('/api/*', (req, res, next) => {
  if (!req.session.user) {
      return res.status(401).json({ error: 'Session expired' });
  }
  res.header('Content-Type', 'application/json');
  next();
});

app.post('/api/webinars', async (req, res) => {
  try {
    const { title, description, scheduledTime, duration, isPublic, maxParticipants } = req.body;
    const organizerId = req.session.user?.companyId;
    
    if (!organizerId) {
      return res.status(401).json({ error: 'Unauthorized' });
    }
    
    const webinarId = uuidv4();
    // Convert scheduledTime to UTC
    const scheduledTimeUTC = new Date(scheduledTime).toISOString().slice(0, 19).replace('T', ' ');
    // Create database record
    db.query(
      `INSERT INTO webinars 
       (webinar_id, title, description, organizer_id, scheduled_time, duration, is_public, max_participants, status)
       VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'scheduled')`,
      [webinarId, title, description, organizerId, scheduledTime, duration, isPublic ? 1 : 0, maxParticipants],
      async (err) => {
        if (err) {
          console.error('Error creating webinar:', err);
          return res.status(500).json({ error: 'Failed to create webinar' });
        }
        
        // Create mediasoup room (we'll create it when the webinar starts)
        res.json({ 
          success: true, 
          webinarId,
          message: 'Webinar created successfully' 
        });
      }
    );
  } catch (error) {
    console.error('Webinar creation error:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// Get upcoming webinars
app.get('/api/webinars', (req, res) => {
  const companyId = req.session.user?.companyId;
  if (!companyId) {
    console.log('Unauthorized access to /api/webinars');
    return res.status(401).json({ error: 'Unauthorized' });
  }
  db.query(`
    SELECT w.*, c.company_name as organizer_name, 
           (SELECT COUNT(*) FROM webinar_participants WHERE webinar_id = w.webinar_id) as participant_count
    FROM webinars w
    JOIN companies c ON w.organizer_id = c.company_id
    WHERE w.status = 'scheduled' AND (w.is_public = 1 OR w.organizer_id = ?)
    ORDER BY w.scheduled_time ASC
  `, [companyId], (err, results) => {
    if (err) {
      console.error('Error fetching webinars:', err);
      return res.status(500).json({ error: 'Failed to fetch webinars' });
    }
    
    res.json(results);
  });
});

// Join webinar
app.post('/api/webinars/:webinarId/join', async (req, res) => {
  try {
    const webinarId = req.params.webinarId;
    const companyId = req.session.user?.companyId;
    const { isPresenter } = req.body;

    if (!companyId) return res.status(401).json({ error: 'Unauthorized' });

    // Validate webinar exists using Promise
    const [webinar] = await new Promise((resolve, reject) => {
      db.query(
        `SELECT w.*, c.company_name as organizer_name 
         FROM webinars w
         JOIN companies c ON w.organizer_id = c.company_id
         WHERE w.webinar_id = ?`,
        [webinarId],
        (err, results) => err ? reject(err) : resolve(results)
      );
    });

    if (!webinar) return res.status(404).json({ error: 'Webinar not found' });
    if (webinar.status !== 'live') return res.status(400).json({ error: 'Webinar is not active' });

    // Upsert participant record using ON DUPLICATE KEY
    await new Promise((resolve, reject) => {
      db.query(
        `INSERT INTO webinar_participants 
         (webinar_id, company_id, is_presenter, joined_at)
         VALUES (?, ?, ?, NOW())
         ON DUPLICATE KEY UPDATE 
           left_at = NULL,
           is_presenter = VALUES(is_presenter)`,
        [webinarId, companyId, isPresenter ? 1 : 0],
        (err) => err ? reject(err) : resolve()
      );
    });

    // Get or create room
    let room = getWebinarRoom(webinarId);
    if (!room) {
      room = await createWebinarRoom(webinarId, {
        isRecording: false,
        maxParticipants: webinar.max_participants
      });
    }

    res.json({
      success: true,
      routerRtpCapabilities: room.router.rtpCapabilities,
      webinarInfo: {
        title: webinar.title,
        description: webinar.description,
        organizerName: webinar.organizer_name,
        isPresenter: !!isPresenter
      }
    });

  } catch (error) {
    console.error('Webinar join error:', error);
    const status = error.code === 'ER_DUP_ENTRY' ? 409 : 500;
    res.status(status).json({ 
      error: error.message,
      details: status === 500 ? 'Server error' : 'Participant already exists'
    });
  }
});
app.get('/api/webinars/:webinarId/verify-registration', (req, res) => {
  const webinarId = req.params.webinarId;
  const companyId = req.session.user?.companyId;

  db.query(
      `SELECT 1 FROM webinar_registrations 
       WHERE webinar_id = ? AND company_id = ?`,
      [webinarId, companyId],
      (err, results) => {
          if (err || results.length === 0) {
              return res.status(403).json({ error: 'Not registered' });
          }
          res.json({ valid: true });
      }
  );
});
// Start webinar (for organizers)
app.post('/api/webinars/:webinarId/start', async (req, res) => {
  try {
    const webinarId = req.params.webinarId;
    const companyId = req.session.user?.companyId;
    
    if (!companyId) {
      return res.status(401).json({ error: 'Unauthorized' });
    }

    // Verify user is the organizer using Promise wrapper
    const [webinar] = await new Promise((resolve, reject) => {
      db.query(
        `SELECT * FROM webinars WHERE webinar_id = ? AND organizer_id = ?`,
        [webinarId, companyId],
        (err, results) => err ? reject(err) : resolve(results)
      );
    });

    if (!webinar) {
      return res.status(403).json({ error: 'Not authorized to start this webinar' });
    }

    // Update webinar status
    const [webinarStatus]=await new Promise((resolve, reject) => {
      db.query(
        `UPDATE webinars SET status = 'live', started_at = NOW() WHERE webinar_id = ?`,
        [webinarId],
        (err) => {
          if (err) return reject(err);
          resolve();
        }
      );
    });
    if (webinar) {
      console.log(`Webinar ${webinarId} started by organizer ${companyId}`);
    }
    // Create mediasoup room
    const room = await createWebinarRoom(webinarId, {
      isRecording: false,
      maxParticipants: webinar.max_participants
    });

    // Notify participants
    const [participants] = await new Promise((resolve, reject) => {
      db.query(
        `SELECT company_id FROM webinar_registrations WHERE webinar_id = ?`,
        [webinarId],
        (err, results) => {
          if (err) return reject(err);
          resolve(results || []);
        }
      );
    });
    if (Array.isArray(participants)) {
      participants.forEach(participant => {
        if (activeUsers.has(participant.company_id)) {
          activeUsers.get(participant.company_id).send(JSON.stringify({
            type: 'webinar_started',
            webinarId,
            title: webinar.title,
            organizerId: companyId,
            organizerName: req.session.user.companyName
          }));
        }
      });
    }

    // Broadcast status update
    io.emit('webinar_status', {
      webinarId,
      status: 'live',
      message: 'Webinar has started'
    });

    res.json({ 
      success: true,
      message: 'Webinar started successfully',
      routerRtpCapabilities: room.router.rtpCapabilities // Important for client
    });

  } catch (error) {
    console.error('Webinar start error:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

app.post('/api/webinars/:webinarId/attend', requireAuth, (req, res) => {
  const companyId = req.session.user.companyId;
  const webinarId = req.params.webinarId;

  const query = `
    INSERT INTO webinar_attendance (webinar_id, company_id, join_time)
    VALUES (?, ?, NOW())
    ON DUPLICATE KEY UPDATE join_time = NOW()
  `;
  db.query(query, [webinarId, companyId], (err) => {
    if (err) {
      console.error('Error logging attendance:', err);
      return res.status(500).json({ error: 'Failed to log attendance' });
    }
    res.json({ success: true });
  });
});

// Single cron job for all webinar duration checks
cron.schedule('* * * * *', () => {
  db.query(`
    UPDATE webinars 
    SET status = 'ended' 
    WHERE status = 'live' 
    AND scheduled_time + INTERVAL duration MINUTE < NOW()
  `);
});

// End webinar (for organizers)
app.post('/api/webinars/:webinarId/end', async (req, res) => {
  try {
    const webinarId = req.params.webinarId;
    const companyId = req.session.user?.companyId;
    
    if (!companyId) {
      return res.status(401).json({ error: 'Unauthorized' });
    }
    
    // Verify user is the organizer
    db.query(
      `SELECT * FROM webinars WHERE webinar_id = ? AND organizer_id = ?`,
      [webinarId, companyId],
      async (err, results) => {
        if (err || results.length === 0) {
          return res.status(403).json({ error: 'Not authorized to end this webinar' });
        }
        
        // Update webinar status
        db.query(
          `UPDATE webinars SET status = 'ended', ended_at = NOW() WHERE webinar_id = ?`,
          [webinarId],
          (err) => {
            if (err) {
              return res.status(500).json({ error: 'Failed to update webinar status' });
            }
            
            // Close mediasoup room
            closeWebinarRoom(webinarId);
            
            res.json({ 
              success: true,
              message: 'Webinar ended successfully'
            });
          }
        );
      }
    );
  } catch (error) {
    console.error('Webinar end error:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});
app.get('/organizer-dashboard', requireAuth, (req, res) => {
  res.sendFile(path.join(__dirname, 'views', 'organizer-dashboard.html'));
});
// WebRTC transport creation
app.post('/api/webinars/:webinarId/create-transport', async (req, res) => {
  try {
    const webinarId = req.params.webinarId;
    const { isProducer } = req.body;
    const companyId = req.session.user?.companyId;
    
    if (!companyId) {
      return res.status(401).json({ error: 'Unauthorized' });
    }
    
    const room = getWebinarRoom(webinarId);
    if (!room) {
      return res.status(404).json({ error: 'Webinar room not found' });
    }
    
    // Create WebRTC transport
    const transport = await room.router.createWebRtcTransport({
      ...mediasoupConfig.webRtcTransport,
      enableSctp: true,
      appData: { companyId, isProducer }
    });
    
    room.transports.set(transport.id, transport);
    
    res.json({
      id: transport.id,
      iceParameters: transport.iceParameters,
      iceCandidates: transport.iceCandidates,
      dtlsParameters: transport.dtlsParameters,
      sctpParameters: transport.sctpParameters
    });
  } catch (error) {
    console.error('Transport creation error:', error);
    res.status(500).json({ error: 'Failed to create transport' });
  }
});

// Connect transport
app.post('/api/webinars/:webinarId/connect-transport', async (req, res) => {
  try {
    const webinarId = req.params.webinarId;
    const { transportId, dtlsParameters } = req.body;
    const companyId = req.session.user?.companyId;
    
    if (!companyId) {
      return res.status(401).json({ error: 'Unauthorized' });
    }
    
    const room = getWebinarRoom(webinarId);
    if (!room) {
      return res.status(404).json({ error: 'Webinar room not found' });
    }
    
    const transport = room.transports.get(transportId);
    if (!transport) {
      return res.status(404).json({ error: 'Transport not found' });
    }
    
    await transport.connect({ dtlsParameters });
    
    res.json({ success: true });
  } catch (error) {
    console.error('Transport connect error:', error);
    res.status(500).json({ error: 'Failed to connect transport' });
  }
});

// Produce media (for presenters)
app.post('/api/webinars/:webinarId/produce', async (req, res) => {
  try {
    const webinarId = req.params.webinarId;
    const { transportId, kind, rtpParameters } = req.body;
    const companyId = req.session.user?.companyId;
    
    if (!companyId) {
      return res.status(401).json({ error: 'Unauthorized' });
    }
    
    const room = getWebinarRoom(webinarId);
    if (!room) {
      return res.status(404).json({ error: 'Webinar room not found' });
    }
    
    // Verify user is a presenter
    db.query(
      `SELECT is_presenter FROM webinar_participants 
       WHERE webinar_id = ? AND company_id = ?`,
      [webinarId, companyId],
      async (err, results) => {
        if (err || results.length === 0 || !results[0].is_presenter) {
          return res.status(403).json({ error: 'Not authorized to produce media' });
        }
        
        const transport = room.transports.get(transportId);
        if (!transport) {
          return res.status(404).json({ error: 'Transport not found' });
        }
        
        const producer = await transport.produce({
          kind,
          rtpParameters,
          appData: { companyId, transportId }
        });
        
        room.producers.set(producer.id, producer);
        
        // Store producer in participant data
        if (!room.participants.has(companyId)) {
          room.participants.set(companyId, { producers: [], consumers: [] });
        }
        
        room.participants.get(companyId).producers.push(producer.id);
        
        // Notify other participants about new producer
        room.participants.forEach((data, participantId) => {
          if (participantId !== companyId && activeUsers.has(participantId)) {
            activeUsers.get(participantId).send(JSON.stringify({
              type: 'new_producer',
              webinarId,
              producerId: producer.id,
              kind
            }));
          }
        });
        
        res.json({ id: producer.id });
      }
    );
  } catch (error) {
    console.error('Produce error:', error);
    res.status(500).json({ error: 'Failed to produce media' });
  }
});

// Consume media (for attendees)
app.post('/api/webinars/:webinarId/consume', async (req, res) => {
  try {
    const webinarId = req.params.webinarId;
    const { transportId, producerId, rtpCapabilities } = req.body;
    const companyId = req.session.user?.companyId;
    
    if (!companyId) {
      return res.status(401).json({ error: 'Unauthorized' });
    }
    
    const room = getWebinarRoom(webinarId);
    if (!room) {
      return res.status(404).json({ error: 'Webinar room not found' });
    }
    
    const transport = room.transports.get(transportId);
    if (!transport) {
      return res.status(404).json({ error: 'Transport not found' });
    }
    
    const producer = room.producers.get(producerId);
    if (!producer) {
      return res.status(404).json({ error: 'Producer not found' });
    }
    
    // Check if the router can consume the specified producer
    if (!room.router.canConsume({
      producerId,
      rtpCapabilities
    })) {
      return res.status(400).json({ error: 'Cannot consume this producer' });
    }
    
    const consumer = await transport.consume({
      producerId,
      rtpCapabilities,
      paused: true,
      appData: { companyId },
    });
    
    room.consumers.set(consumer.id, consumer);
    consumer.on('transportclose', () => {
      room.consumers.delete(consumer.id);
      consumer.close();
    });

    consumer.on('close', () => {
      room.consumers.delete(consumer.id);
    });
    
    // Store consumer in participant data
    if (!room.participants.has(companyId)) {
      room.participants.set(companyId, { producers: [], consumers: [] });
    }
    
    room.participants.get(companyId).consumers.push(consumer.id);
    
    res.json({
      id: consumer.id,
      producerId,
      kind: consumer.kind,
      rtpParameters: consumer.rtpParameters,
      type: consumer.type,
      producerPaused: consumer.producerPaused,
    });
  } catch (error) {
    console.error('Consume error:', error);
    res.status(500).json({ error: 'Failed to consume media' });
  }
});
// Get all producers for a webinar
app.get('/api/webinars/:webinarId/producers', async (req, res) => {
  try {
    const webinarId = req.params.webinarId;
    const companyId = req.session.user?.companyId;

    if (!companyId) {
      return res.status(401).json({ error: 'Unauthorized' });
    }

    const room = getWebinarRoom(webinarId);
    if (!room) {
      return res.status(404).json({ error: 'Webinar room not found' });
    }

    // Collect all producers
    const producers = Array.from(room.producers.values()).map(producer => ({
      id: producer.id,
      kind: producer.kind,
      companyId: room.transports.get(producer.appData.transportId)?.appData.companyId
    }));

    res.json(producers);
  } catch (error) {
    console.error('Error fetching producers:', error);
    res.status(500).json({ error: 'Failed to fetch producers' });
  }
});
// WebSocket handlers for webinar notifications
function handleWebinarWebSocketMessages(ws, message) {
  const data = JSON.parse(message);
  const companyId = ws.companyId;
  
  switch (data.type) {
    case 'webinar_join':
      handleWebinarJoin(ws, data);
      break;
    case 'webinar_leave':
      handleWebinarLeave(ws, data);
      break;
    case 'webinar_chat_message':
      handleWebinarChatMessage(ws, data);
      break;
    case 'webinar_raise_hand':
      handleRaiseHand(ws, data);
      break;
    case 'webinar_mute_participant':
      handleMuteParticipant(ws, data);
      break;
    case 'webinar_presentation_start':
      handlePresentationStart(ws, data);
      break;
    case 'webinar_presentation_end':
      handlePresentationEnd(ws, data);
      break;
  }
}

function handleWebinarJoin(ws, data) {
  const { webinarId } = data;
  const room = getWebinarRoom(webinarId);
  
  if (!room) {
    ws.send(JSON.stringify({
      type: 'error',
      message: 'Webinar room not found'
    }));
    return;
  }
  
  // Store webinar ID in WebSocket connection
  ws.webinarId = webinarId;
  
  // Send list of active producers to the new participant
  const producers = Array.from(room.producers.values()).map(producer => ({
    id: producer.id,
    kind: producer.kind,
    companyId: room.transports.get(producer.transportId).appData.companyId
  }));
  
  ws.send(JSON.stringify({
    type: 'webinar_producers',
    producers
  }));
}

function handleWebinarLeave(ws, data) {
  const { webinarId } = data;
  const room = getWebinarRoom(webinarId);
  
  if (room) {
    // Clean up participant's transports, producers, and consumers
    const companyId = ws.companyId;
    const participant = room.participants.get(companyId);
    
    if (participant) {
      // Close all transports for this participant
      room.transports.forEach(transport => {
        if (transport.appData.companyId === companyId) {
          transport.close();
          room.transports.delete(transport.id);
        }
      });
      
      // Remove all producers for this participant
      participant.producers.forEach(producerId => {
        const producer = room.producers.get(producerId);
        if (producer) {
          producer.close();
          room.producers.delete(producerId);
          
          // Notify other participants
          room.participants.forEach((data, pid) => {
            if (pid !== companyId && activeUsers.has(pid)) {
              activeUsers.get(pid).send(JSON.stringify({
                type: 'producer_closed',
                producerId
              }));
            }
          });
        }
      });
      
      // Remove all consumers for this participant
      participant.consumers.forEach(consumerId => {
        const consumer = room.consumers.get(consumerId);
        if (consumer) {
          consumer.close();
          room.consumers.delete(consumerId);
        }
      });
      
      // Remove participant from room
      room.participants.delete(companyId);
    }
  }
  
  // Remove webinar ID from WebSocket connection
  ws.webinarId = null;
}

function handleWebinarChatMessage(ws, data) {
  const { webinarId, message } = data;
  const companyId = ws.companyId;
  
  // Save chat message to database
  db.query(
    `INSERT INTO webinar_chat_messages 
     (webinar_id, company_id, message, sent_at)
     VALUES (?, ?, ?, NOW())`,
    [webinarId, companyId, message],
    (err) => {
      if (err) {
        console.error('Error saving chat message:', err);
        return;
      }
      
      // Broadcast message to all participants in the webinar
      const room = getWebinarRoom(webinarId);
      if (room) {
        room.participants.forEach((_, pid) => {
          if (activeUsers.has(pid)) {
            activeUsers.get(pid).send(JSON.stringify({
              type: 'webinar_chat_message',
              webinarId,
              companyId,
              message,
              timestamp: new Date().toISOString()
            }));
          }
        });
      }
    }
  );
}

function handleRaiseHand(ws, data) {
  const { webinarId } = data;
  const companyId = ws.companyId;
  
  // Notify organizers
  db.query(
    `SELECT organizer_id FROM webinars WHERE webinar_id = ?`,
    [webinarId],
    (err, results) => {
      if (err || results.length === 0) return;
      
      const organizerId = results[0].organizer_id;
      if (activeUsers.has(organizerId)) {
        activeUsers.get(organizerId).send(JSON.stringify({
          type: 'webinar_raise_hand',
          webinarId,
          companyId
        }));
      }
    }
  );
}
// Handle muting a participant (moderator action)
function handleMuteParticipant(ws, data) {
  const { webinarId, participantId, mute } = data;
  const moderatorId = ws.companyId;
  
  // Verify moderator is the organizer
  db.query(
      `SELECT organizer_id FROM webinars WHERE webinar_id = ?`,
      [webinarId],
      (err, results) => {
          if (err || results.length === 0 || results[0].organizer_id !== moderatorId) {
              ws.send(JSON.stringify({
                  type: 'error',
                  message: 'Not authorized to mute participants'
              }));
              return;
          }
          
          // Notify the participant to mute/unmute
          if (activeUsers.has(participantId)) {
              activeUsers.get(participantId).send(JSON.stringify({
                  type: 'mute_request',
                  mute,
                  moderatorId,
                  moderatorName: ws.companyName
              }));
          }
          
          // Update participant mute status in database
          db.query(
              `UPDATE webinar_participants SET is_muted = ? 
               WHERE webinar_id = ? AND company_id = ?`,
              [mute ? 1 : 0, webinarId, participantId],
              (err) => {
                  if (err) console.error('Error updating mute status:', err);
              }
          );
          
          // Broadcast to all participants about the mute action
          broadcastToWebinar(webinarId, {
              type: 'participant_muted',
              participantId,
              mute,
              moderatorId
          });
      }
  );
}

// Handle presentation start (moderator action)
function handlePresentationStart(ws, data) {
  const { webinarId, presentationType, resourceUrl } = data;
  const presenterId = ws.companyId;
  
  // Verify presenter is authorized (organizer or designated presenter)
  db.query(
      `SELECT organizer_id FROM webinars WHERE webinar_id = ?`,
      [webinarId],
      (err, results) => {
          if (err || results.length === 0) {
              ws.send(JSON.stringify({
                  type: 'error',
                  message: 'Webinar not found'
              }));
              return;
          }
          
          const isOrganizer = results[0].organizer_id === presenterId;
          
          if (!isOrganizer) {
              // Check if user is a designated presenter
              db.query(
                  `SELECT is_presenter FROM webinar_participants 
                   WHERE webinar_id = ? AND company_id = ?`,
                  [webinarId, presenterId],
                  (err, results) => {
                      if (err || results.length === 0 || !results[0].is_presenter) {
                          ws.send(JSON.stringify({
                              type: 'error',
                              message: 'Not authorized to start presentations'
                          }));
                          return;
                      }
                      
                      startPresentation();
                  }
              );
          } else {
              startPresentation();
          }
      }
  );
  
  function startPresentation() {
      // Update webinar state
      db.query(
          `UPDATE webinars SET 
           current_presentation_type = ?,
           current_presentation_url = ?,
           current_presenter_id = ?
           WHERE webinar_id = ?`,
          [presentationType, resourceUrl, presenterId, webinarId],
          (err) => {
              if (err) {
                  console.error('Error starting presentation:', err);
                  return;
              }
              
              // Broadcast to all participants
              broadcastToWebinar(webinarId, {
                  type: 'presentation_started',
                  presentationType,
                  resourceUrl,
                  presenterId,
                  presenterName: ws.companyName
              });
          }
      );
  }
}

// Handle presentation end (moderator action)
function handlePresentationEnd(ws, data) {
  const { webinarId } = data;
  const presenterId = ws.companyId;
  
  // Verify presenter is the current presenter or organizer
  db.query(
      `SELECT organizer_id, current_presenter_id FROM webinars 
       WHERE webinar_id = ?`,
      [webinarId],
      (err, results) => {
          if (err || results.length === 0) {
              ws.send(JSON.stringify({
                  type: 'error',
                  message: 'Webinar not found'
              }));
              return;
          }
          
          const isOrganizer = results[0].organizer_id === presenterId;
          const isCurrentPresenter = results[0].current_presenter_id === presenterId;
          
          if (!isOrganizer && !isCurrentPresenter) {
              ws.send(JSON.stringify({
                  type: 'error',
                  message: 'Not authorized to end this presentation'
              }));
              return;
          }
          
          // Update webinar state
          db.query(
              `UPDATE webinars SET 
               current_presentation_type = NULL,
               current_presentation_url = NULL,
               current_presenter_id = NULL
               WHERE webinar_id = ?`,
              [webinarId],
              (err) => {
                  if (err) {
                      console.error('Error ending presentation:', err);
                      return;
                  }
                  
                  // Broadcast to all participants
                  broadcastToWebinar(webinarId, {
                      type: 'presentation_ended',
                      presenterId
                  });
              }
          );
      }
  );
}

// Helper function to broadcast to all webinar participants
function broadcastToWebinar(webinarId, message) {
  db.query(
      `SELECT company_id FROM webinar_participants 
       WHERE webinar_id = ? AND left_at IS NULL`,
      [webinarId],
      (err, participants) => {
          if (err) {
              console.error('Error getting webinar participants:', err);
              return;
          }
          
          participants.forEach(participant => {
              if (activeUsers.has(participant.company_id)) {
                  activeUsers.get(participant.company_id).send(JSON.stringify(message));
              }
          });
      }
  );
}
// Webinar API endpoints
app.get('/api/webinars/live', (req, res) => {
  const query = `
      SELECT w.*, c.company_name as organizer_name, 
             (SELECT COUNT(*) FROM webinar_participants 
              WHERE webinar_id = w.webinar_id) as participants
      FROM webinars w
      JOIN companies c ON w.organizer_id = c.company_id
      WHERE w.status = 'live'
      ORDER BY w.started_at DESC
  `;
  
  db.query(query, (err, results) => {
      if (err) return res.status(500).json({ error: err.message });
      res.json(results);
  });
});

app.get('/api/webinars/upcoming', (req, res) => {
  const companyId = req.session.user?.companyId || null;

  const query = `
    SELECT 
            w.*,
            w.organizer_id AS organizer_id, 
            c.company_name AS organizer_name,
            (SELECT EXISTS(
                SELECT 1 
                FROM webinar_registrations 
                WHERE webinar_id = w.webinar_id 
                AND company_id = ?
            )) AS is_registered,
            (SELECT COUNT(*) 
             FROM webinar_registrations 
             WHERE webinar_id = w.webinar_id
            ) AS registrations
        FROM webinars w
        JOIN companies c ON w.organizer_id = c.company_id
        WHERE w.status = 'scheduled'
        AND w.scheduled_time > UTC_TIMESTAMP()
        ORDER BY w.scheduled_time ASC
  `;

  db.query(query, [companyId], (err, results) => {
    if (err) {
      console.error('Database error:', err);
      return res.status(500).json({ 
        error: 'Internal server error',
        details: err.message 
      });
    }
    
    // Convert raw data to proper JavaScript types
    const webinars = results.map(webinar => ({
      ...webinar,
      scheduled_time: new Date(webinar.scheduled_time).toISOString(),
      duration: Number(webinar.duration)
    }));
    
    res.json(webinars);
  });
});

app.get('/api/webinars/past', (req, res) => {
  const query = `
      SELECT w.*, c.company_name as organizer_name,
             (SELECT COUNT(*) FROM webinar_recordings 
              WHERE webinar_id = w.webinar_id) as recordings
      FROM webinars w
      JOIN companies c ON w.organizer_id = c.company_id
      WHERE w.status = 'ended'
      ORDER BY w.ended_at DESC
  `;
  
  db.query(query, (err, results) => {
      if (err) return res.status(500).json({ error: err.message });
      res.json(results);
  });
});
// server.js - Add this with your other webinar endpoints
app.get('/api/webinars/recordings', (req, res) => {
  const query = `
      SELECT w.*, c.company_name as organizer_name,
             (SELECT COUNT(*) FROM webinar_recordings 
              WHERE webinar_id = w.webinar_id) as views
      FROM webinars w
      JOIN companies c ON w.organizer_id = c.company_id
      WHERE w.status = 'ended'
      ORDER BY w.ended_at DESC
  `;
  
  db.query(query, (err, results) => {
      if (err) return res.status(500).json({ error: err.message });
      
      const webinars = results.map(webinar => ({
          ...webinar,
          thumbnail_url: webinar.thumbnail_url || '/images/default-recording.jpg'
      }));
      
      res.json(webinars);
  });
});
// function requireAuth(req, res, next) {
//   if (!req.session.user?.companyId) {
//     return res.status(401).json({ error: 'Authentication required' });
//   }
//   next();
// }
// server.js (Fix in webinar registration endpoint)
app.post('/api/webinars/:webinarId/register', requireAuth, (req, res) => {
  const companyId = req.session.user.companyId;
  const webinarId = req.params.webinarId;
  console.log('Company ID:', companyId);
  console.log('Webinar ID:', webinarId);
  
  if (!companyId) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  const query = `
    INSERT INTO webinar_registrations (webinar_id, company_id)
    VALUES (?, ?)
    ON DUPLICATE KEY UPDATE registered_at = NOW()
  `;

  // Fixed result reference
  db.query(query, [webinarId, companyId], (err, results) => {
    if (err) return res.status(500).json({ error: err.message });
    
    // Emit to all clients
    io.emit('registration_update', {
      webinarId,
      registrations: results.affectedRows
    });
    
    res.json({ success: true });
  });
  console.log('Registration query executed:', query, [webinarId, companyId]);
 
  console.log('res',res.json);
});


// Run every hour to check for missed webinars
cron.schedule('0 * * * *', () => {
  const now = new Date().toISOString().slice(0, 19).replace('T', ' ');
  
  db.query(
    `UPDATE webinars 
     SET status = 'missed'
     WHERE status = 'scheduled'
     AND scheduled_time < ?`,
    [now],
    (err) => {
      if (err) {
        console.error('Error updating missed webinars:', err);
      } else {
        console.log('Marked overdue webinars as missed');
      }
    }
  );
});
// Add process exception handling
process.on('uncaughtException', (err) => {
  console.error('Uncaught Exception:', err);
  process.exit(1);
});

process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});

// Middleware for admin check
function requireAdmin(req, res, next) {
  if (!req.session.user?.companyId || !req.session.user?.isAdmin) {
    return res.status(403).json({ error: 'Admin access required' });
  }
  next();
}

// Exhibition settings routes
app.get('/admin-settings', (req, res) => {
  res.render('admin-settings');
});

app.get('/api/exhibition-settings', requireAdmin, (req, res) => {
  db.query('SELECT start_datetime, end_datetime FROM exhibition_settings ORDER BY id DESC LIMIT 1', (err, results) => {
    if (err) {
      console.error('Error fetching settings:', err);
      return res.status(500).json({ error: 'Database error' });
    }
    res.json(results[0] || {});
  });
});

app.post('/api/exhibition-settings', requireAdmin, (req, res) => {
  const { start_datetime, end_datetime } = req.body;
  if (!start_datetime || !end_datetime) {
    return res.status(400).json({ error: 'Missing start or end datetime' });
  }

  const query = `
    INSERT INTO exhibition_settings (start_datetime, end_datetime)
    VALUES (?, ?)
    ON DUPLICATE KEY UPDATE start_datetime = ?, end_datetime = ?, updated_at = NOW()
  `;
  db.query(query, [start_datetime, end_datetime, start_datetime, end_datetime], (err) => {
    if (err) {
      console.error('Error saving settings:', err);
      return res.status(500).json({ error: 'Database error' });
    }
    // Reschedule end task
    scheduleExhibitionEnd(end_datetime);
    res.json({ success: true });
  });
});

// Global flag for exhibition status
let exhibitionEnded = false;

// Function to end the exhibition
async function endExhibition() {
  exhibitionEnded = true;
  console.log('Exhibition ended at:', new Date());

  // Broadcast to Socket.io clients (for webinar.js)
  io.emit('exhibition_ended');

  // Broadcast to WebSocket clients (for networkingjs.js, booth.js)
  const wss = expressWs.getWss('/ws');
  wss.clients.forEach(client => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(JSON.stringify({ type: 'exhibition_ended' }));
    }
  });

// Clear all sessions
if (app.sessionStore && typeof app.sessionStore.clear === 'function') {
  app.sessionStore.clear((err) => {
    if (err) {
      console.error('Error clearing sessions:', err);
    } else {
      console.log('All sessions cleared successfully.');
    }
  });
} else {
  console.warn('Session store is not initialized or does not support .clear().');
}

  generateAndSendReports()
    .then(() => {
      console.log('Report generation completed successfully');
    })
    .catch(err => {
      console.error('Error during report generation:', err);
    });
}

// Function to generate and send reports
async function generateAndSendReports() {
  return new Promise((resolve, reject) => {
    const companiesQuery = 'SELECT company_id, company_name, email FROM companies';
    db.query(companiesQuery, async (err, companies) => {
      if (err) {
        console.error('Error fetching companies:', err);
        return reject(err);
      }

      for (const company of companies) {
        try {
          const boothVisitsQuery = `
            SELECT DISTINCT c.company_name AS visitor_name
            FROM booth_visits bv
            JOIN companies c ON bv.visitor_company_id = c.company_id
            WHERE bv.booth_company_id = ?
          `;
          const [boothVisitors] = await new Promise((res, rej) => {
            db.query(boothVisitsQuery, [company.company_id], (e, r) => e ? rej(e) : res(r));
          });

          const webinarAttendeesQuery = `
            SELECT DISTINCT w.webinar_id, w.title, c.company_name AS attendee_name
            FROM webinar_registrations wr
            JOIN webinars w ON wr.webinar_id = w.webinar_id
            JOIN companies c ON wr.company_id = c.company_id
            WHERE w.organizer_id = ?
          `;
          const [webinarAttendees] = await new Promise((res, rej) => {
            db.query(webinarAttendeesQuery, [company.company_id], (e, r) => e ? rej(e) : res(r));
          });

          let reportHtml = `<h2>Exhibition Report for ${company.company_name}</h2>`;
          reportHtml += '<h3>Booth Visitors:</h3><ul>';
          if (boothVisitors.length) {
            reportHtml += boothVisitors.map(v => `<li>${v.visitor_name}</li>`).join('');
          } else {
            reportHtml += '<li>None</li>';
          }
          reportHtml += '</ul><h3>Webinar Attendees:</h3><ul>';
          if (webinarAttendees.length) {
            reportHtml += webinarAttendees.map(a => `<li>${a.title}: ${a.attendee_name}</li>`).join('');
          } else {
            reportHtml += '<li>None</li>';
          }
          reportHtml += '</ul>';

          const mailOptions = {
            from: process.env.SUPPORT_EMAIL,
            to: company.email,
            subject: 'Virtual Exhibition Report',
            html: reportHtml
          };

          let sent = false;
          let attempts = 0;
          let lastError = null;
          while (!sent && attempts < 3) {
            try {
              await supportEmailTransporter.sendMail(mailOptions);
              sent = true;
              console.log(`Report sent to ${company.email}`);
            } catch (err) {
              attempts++;
              lastError = err;
              console.error(`Attempt ${attempts} failed to send report to ${company.email}:`, err);
              await new Promise(res => setTimeout(res, 1000 * attempts)); // Exponential backoff
            }
          }
          if (!sent) {
            // Log failed email for later review
            console.error(`Failed to send report to ${company.email} after 3 attempts:`, lastError);
            // Optionally, save to a file or database for later retry
          }
        } catch (error) {
          console.error(`Error generating report for ${company.company_id}:`, error);
        }
      }
      resolve();
    });
  });
}

// Function to schedule end task
let currentEndJob = null;
function scheduleExhibitionEnd(endDatetime) {
  if (currentEndJob) {
    currentEndJob.destroy(); // Cancel previous job
  }

  const endMoment = moment(endDatetime);
  if (endMoment.isBefore(moment())) {
    console.log('End time is in the past, ending immediately');
    endExhibition();
    return;
  }

  currentEndJob = cron.schedule(endMoment.format('m H D M *'), endExhibition, {
    scheduled: true,
    timezone: 'UTC'
  });
  console.log('Exhibition end scheduled for:', endDatetime);
}
app.use((req, res) => {
  res.status(404).send('Page not found');
});

const PORT = process.env.PORT || 3000;
// const YOUR_LOCAL_IP='192.168.0.6';
// app.listen(PORT, () => {
//   console.log(`Server is running on port ${PORT}`);
// });
server.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});