import { Express, Request } from "express";
import { createServer, type Server } from "http";
import { setupAuth, hashPassword } from "./auth";
import { storage } from "./storage";
import express from "express";
import cors from 'cors';
import { sendInvitationEmail, validateActivationToken } from "./email";
import { handleChatbotQuery } from "./ai";
import {
  startTranscriptionService,
  stopTranscriptionService,
  transcriptionIntervals,
} from "./transcription-service";
import {
  startRTMPServer,
  isRTMPServerRunning,
  getRTMPUrl,
  isStreamActive,
  stopRTMPServer,
} from "./rtmp-server";
import Pusher from "pusher";
import admin from "firebase-admin";
import {
  insertUserSchema,
  insertEventSchema,
  insertSessionSchema,
  insertSpeakerSchema,
  insertNewsSchema,
  insertMediaSchema,
  insertQuestionSchema,
  insertSettingsSchema,
} from "@shared/schema";
import { seedDummyData } from "./dummy-data";
import { z } from "zod";
import path from "path";
import fs from "fs";
import { processAudioFile } from "./audio-processor";
import multer from "multer";
import { eq, desc } from 'drizzle-orm';
import jwt from 'jsonwebtoken';

// Declare multer types
declare module "multer" {
  interface File {
    fieldname: string;
    originalname: string;
    encoding: string;
    mimetype: string;
    size: number;
    destination: string;
    filename: string;
    path: string;
    buffer: Buffer;
  }
}

declare global {
  namespace Express {
    interface Request {
      file?: multer.File;
    }
  }
}

// Ensure uploads directory exists
const uploadsDir = path.join(process.cwd(), 'uploads');
if (!fs.existsSync(uploadsDir)) {
  fs.mkdirSync(uploadsDir, { recursive: true });
}

// Types for multer callbacks
type DoneCallback = (error: Error | null, value: any) => void;

// Configure multer storage
const multerStorage = multer.diskStorage({
  destination: function (_req: Request, _file: multer.File, cb: (error: Error | null, destination: string) => void): void {
    cb(null, uploadsDir);
  },
  filename: function (_req: Request, file: multer.File, cb: (error: Error | null, filename: string) => void): void {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    cb(null, uniqueSuffix + path.extname(file.originalname));
  }
});

// File filter function
const fileFilter = (_req: Request, file: multer.File, cb: (error: Error | null, acceptFile: boolean) => void): void => {
  const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
  if (allowedTypes.includes(file.mimetype)) {
    cb(null, true);
  } else {
    cb(new Error('Invalid file type. Only JPEG, PNG, GIF and WebP files are allowed.'), false);
  }
};

const upload = multer({
  storage: multerStorage,
  fileFilter: fileFilter,
  limits: {
    fileSize: 5 * 1024 * 1024 // 5MB limit
  }
});

// Update JWT_SECRET to use environment variable
const JWT_SECRET = process.env.JWT_SECRET || "your-secret-key";

// Declare multer types
declare global {
  namespace Express {
    interface Request {
      file?: {
        fieldname: string;
        originalname: string;
        encoding: string;
        mimetype: string;
        size: number;
        destination: string;
        filename: string;
        path: string;
        buffer: Buffer;
      }
    }
  }
}

interface SelectUser {
  role: string;
  id: number;
  username: string;
  [key: string]: any; // Add other properties as needed
}

// Initialize Pusher
const pusher = new Pusher({
  appId: process.env.PUSHER_APP_ID!,
  key: process.env.PUSHER_KEY!,
  secret: process.env.PUSHER_SECRET!,
  cluster: process.env.PUSHER_CLUSTER!,
  useTLS: true,
});

// Async initialization of optional services
async function initializeOptionalServices() {
  console.log("Starting optional services initialization...");

  // Initialize RTMP server
  try {
    if (!isRTMPServerRunning()) {
      console.log("Starting RTMP server...");
      const success = startRTMPServer();
      if (success) {
        console.log("✅ RTMP server started successfully");
      } else {
        console.warn("⚠️ Failed to start RTMP server");
      }
    }
  } catch (error) {
    console.error("❌ Error starting RTMP server:", error);
  }

  // Initialize Firebase Admin
  if (!admin.apps.length) {
    try {
      const requiredSecrets = [
        "FIREBASE_PROJECT_ID",
        "FIREBASE_ADMIN_PRIVATE_KEY_ID",
        "FIREBASE_ADMIN_PRIVATE_KEY",
      ];

      const missingSecrets = requiredSecrets.filter(
        (secret) => !process.env[secret],
      );

      if (missingSecrets.length > 0) {
        console.warn(
          "⚠️ Missing Firebase Admin credentials:",
          missingSecrets.join(", "),
        );
        console.warn("Firebase functionality will be disabled");
      } else {
        const serviceAccount = {
          type: "service_account",
          project_id: process.env.FIREBASE_PROJECT_ID,
          private_key_id: process.env.FIREBASE_ADMIN_PRIVATE_KEY_ID,
          private_key: process.env.FIREBASE_ADMIN_PRIVATE_KEY?.replace(
            /\\n/g,
            "\n",
          ),
          client_email: `firebase-adminsdk-${process.env.FIREBASE_PROJECT_ID}@${process.env.FIREBASE_PROJECT_ID}.iam.gserviceaccount.com`,
        };

        await admin.initializeApp({
          credential: admin.credential.cert(
            serviceAccount as admin.ServiceAccount,
          ),
        });
        console.log("✅ Firebase Admin initialized successfully");
      }
    } catch (error) {
      console.error("❌ Error initializing Firebase Admin:", error);
      console.warn("Firebase functionality will be disabled");
    }
  }

  console.log("Optional services initialization completed");
}

export async function registerRoutes(app: Express): Promise<Server> {
  console.log("Starting routes registration...");

  // 1. Basic middleware setup with increased limits
  app.use(express.json({ limit: '50mb' }));
  app.use(express.urlencoded({ limit: '50mb', extended: true }));

  // 2. Global CORS configuration - must be before any routes
  app.use(function(req, res, next) {
    // Allow all origins 
    res.setHeader('Access-Control-Allow-Origin', '*');
    
    // Allow all HTTP methods
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
    
    // Allow all headers
    res.setHeader('Access-Control-Allow-Headers', '*');
    
    // Allow credentials
    res.setHeader('Access-Control-Allow-Credentials', 'true');
    
    // Cache preflight for 24 hours
    res.setHeader('Access-Control-Max-Age', '86400');
    
    // Handle preflight
    if (req.method === 'OPTIONS') {
      return res.status(200).end();
    }
    
    next();
  });

  try {
    // Serve uploaded files
    app.use('/uploads', express.static(path.join(process.cwd(), 'uploads')));

    // Add upload endpoint 
    app.post('/api/upload', upload.single('file'), (req, res) => {
      try {
        if (!req.file) {
          return res.status(400).json({ error: 'No file uploaded' });
        }

        // Create URL for the uploaded file
        const fileUrl = `/uploads/${req.file.filename}`;
        
        res.json({
          url: fileUrl,
          filename: req.file.filename,
          originalname: req.file.originalname,
          mimetype: req.file.mimetype,
          size: req.file.size
        });
      } catch (error) {
        console.error('File upload error:', error);
        res.status(500).json({ 
          error: 'Failed to upload file',
          details: error instanceof Error ? error.message : 'Unknown error' 
        });
      }
    });

    setupAuth(app);
    console.log("✅ Auth setup completed");

    // Register new user
    app.post("/api/auth/register", async (req, res) => {
      try {
        console.log("Received registration request with body:", req.body);

        const existingUser = await storage.getUserByUsername(req.body.username);
        console.log("Existing user check result:", !!existingUser);

        if (existingUser) {
          console.log("Registration failed: Username already exists");
          return res.status(400).json({ message: "Username already exists" });
        }

        console.log("Validating user data...");
        const validated = insertUserSchema.parse(req.body);
        console.log("Data validation successful");

        console.log("Creating new user in database...");
        const user = await storage.createUser({
          ...validated,
          password: await hashPassword(validated.password),
        });
        console.log("User created successfully:", { id: user.id, username: user.username });

        req.login(user, (err) => {
          if (err) {
            console.error("Login after registration failed:", err);
            return res.status(500).json({ message: "Login failed after registration" });
          }
          console.log("User logged in successfully after registration");
          res.status(201).json(user);
        });
      } catch (error) {
        console.error("Registration error:", error);
        const message = error instanceof Error ? error.message : "Registration failed";
        res.status(400).json({ message });
      }
    });

    // Add route to get user data by token
    app.get("/api/users/current/:token", async (req, res) => {
      try {
        const { token } = req.params;
        console.log("Fetching user data for token:", token);

        // Validate the token and get the associated user ID
        const userId = validateActivationToken(token);
        console.log("Validated token, got user ID:", userId);

        if (!userId) {
          console.log("Invalid or expired token");
          return res
            .status(400)
            .json({ message: "Invalid or expired activation token" });
        }

        // Get the user
        const user = await storage.getUser(userId);
        console.log("Found user:", user);

        if (!user) {
          console.log("User not found");
          return res.status(404).json({ message: "User not found" });
        }

        // Return user data without sensitive information
        const { password, ...userData } = user;
        console.log("Returning user data:", userData);
        res.json(userData);
      } catch (error) {
        console.error("Error fetching user data:", error);
        res.status(500).json({
          error: "Failed to fetch user data",
          details: error instanceof Error ? error.message : "Unknown error",
        });
      }
    });

    app.post("/api/activate-account/:token", async (req, res) => {
      try {
        const { token } = req.params;
        const {
          password,
          profileImage,
          name,
          email,
          organization,
          position,
          phoneNumber,
        } = req.body;

        // Validate the token and get the associated user ID
        const userId = validateActivationToken(token);
        if (!userId) {
          return res
            .status(400)
            .json({ message: "Invalid or expired activation token" });
        }

        // Get the user
        const user = await storage.getUser(userId);
        if (!user) {
          return res.status(404).json({ message: "User not found" });
        }

        // Check if user is already activated
        if (user.isActive) {
          return res
            .status(400)
            .json({ message: "Account is already activated" });
        }

        // Hash the password
        const hashedPassword = await hashPassword(password);

        // Update the user with all the provided information
        const updatedUser = await storage.updateUser(userId, {
          password: hashedPassword,
          profileImage,
          name,
          email,
          organization,
          position,
          phoneNumber,
          isActive: true,
        });

        // Mark the token as used after successful activation
        await markTokenAsUsed(token);

        res.json({ success: true });
      } catch (error) {
        console.error("Error activating account:", error);
        res.status(500).json({
          error: "Failed to activate account",
          details: error instanceof Error ? error.message : "Unknown error",
        });
      }
    });

    // Seed endpoint
    app.post("/api/seed", async (_req, res) => {
      try {
        await seedDummyData();
        res.json({ message: "Dummy data seeded successfully" });
      } catch (error) {
        console.error("Error seeding data:", error);
        res.status(500).json({ error: "Failed to seed dummy data" });
      }
    });

    // Add active transcriptions endpoint with no auth requirement
    app.get("/api/transcriptions/active", async (_req, res) => {
      try {
        const activeSessionIds = Array.from(transcriptionIntervals.keys());
        console.log('Active transcription sessions:', activeSessionIds);
        res.json({ 
          success: true,
          activeSessionIds 
        });
      } catch (error) {
        console.error("Error fetching active transcriptions:", error);
        res.status(500).json({ 
          success: false,
          message: "Failed to fetch active transcriptions", 
          error: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Events routes
    app.get("/api/events", async (_req, res) => {
      const events = await storage.getEvents();
      res.json(events);
    });

    app.get("/api/events/:id", async (req, res) => {
      const event = await storage.getEvent(Number(req.params.id));
      if (!event) return res.status(404).json({ message: "Event not found" });
      res.json(event);
    });

    app.post("/api/events", async (req, res) => {
      if (!req.isAuthenticated()) return res.sendStatus(401);
      const validated = insertEventSchema.parse(req.body);
      const event = await storage.createEvent(validated);
      res.status(201).json(event);
    });

    app.patch("/api/events/:id", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const eventId = Number(req.params.id);
        const validated = insertEventSchema.parse(req.body);
        const updatedEvent = await storage.updateEvent(eventId, validated);
        if (!updatedEvent) {
          return res.status(404).json({ message: "Event not found" });
        }
        res.json(updatedEvent);
      } catch (error) {
        console.error("Error updating event:", error);
        res.status(500).json({ error: "Failed to update event" });
      }
    });

    app.delete("/api/events/:id", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const eventId = Number(req.params.id);
        await storage.deleteEvent(eventId);
        res.sendStatus(200);
      } catch (error) {
        console.error("Error deleting event:", error);
        res.status(500).json({ error: "Failed to delete event" });
      }
    });

    // Sessions routes
    app.get("/api/sessions", async (req, res) => {
      try {
        const eventId = req.query.eventId
          ? Number(req.query.eventId)
          : undefined;
        const sessions = await storage.getSessionsWithSpeakers(eventId);
        res.json(sessions);
      } catch (error) {
        console.error("Error fetching sessions:", error);
        res.status(500).json({ error: "Failed to fetch sessions" });
      }
    });

    // Live stream sessions route - place this BEFORE the :id route
    app.get("/api/sessions/live-streams", async (_req, res) => {
      try {
        console.log('Fetching live stream sessions');
        const liveSessions = await storage.getLiveStreamSessions();
        
        // Format response according to spec
        const formattedSessions = liveSessions.map(session => ({
          id: session.id,
          sessionTitle: session.sessionTitle,
          sessionTitleAr: session.sessionTitleAr,
          liveStreamUrl: session.liveStreamUrl,
          sessionDate: session.sessionDate,
          sessionTime: session.sessionTime,
          venue: session.venue,
          venueAr: session.venueAr
        }));

        console.log('Formatted live sessions:', formattedSessions);
        res.json({ sessions: formattedSessions });
      } catch (error) {
        console.error("Error fetching live stream sessions:", error);
        res.status(500).json({ 
          message: "Failed to fetch live stream sessions",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Session detail route - keep this AFTER the live-streams route
    app.get("/api/sessions/:id", async (req, res) => {
      try {
        const sessionId = Number(req.params.id);
        console.log('Fetching session details for ID:', sessionId);
        
        if (isNaN(sessionId)) {
          console.log('Invalid session ID provided:', req.params.id);
          return res.status(400).json({ 
            message: "Invalid session ID format",
            details: "Session ID must be a number"
          });
        }

        const session = await storage.getSessionWithSpeakers(sessionId);
        if (!session) {
          console.log('Session not found for ID:', sessionId);
          return res.status(404).json({ message: "Session not found" });
        }

        console.log('Found session:', session);
        res.json(session);
      } catch (error) {
        console.error("Error fetching session:", error);
        res.status(500).json({
          message: "Failed to fetch session",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Add session transcriptions route with comprehensive error handling and logging
    app.get("/api/sessions/:sessionId/transcriptions", async (req, res) => {
      // Set CORS headers first, before any possible return
      res.header('Access-Control-Allow-Origin', '*');
      res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
      res.header('Access-Control-Allow-Headers', '*');
      res.header('Access-Control-Allow-Credentials', 'true');

      try {
        // Log complete request details for debugging
        console.log('=== Transcriptions Request Debug Info ===');
        console.log('Full URL:', `${req.protocol}://${req.get('host')}${req.originalUrl}`);
        console.log('Method:', req.method);
        console.log('Session ID from params:', req.params.sessionId);
        console.log('Query params:', req.query);
        console.log('Headers:', {
          origin: req.headers.origin,
          host: req.headers.host,
          referer: req.headers.referer,
          'user-agent': req.headers['user-agent']
        });
        
        let sessionId: number;
        
        try {
          // Handle both string and number formats
          sessionId = typeof req.params.sessionId === 'number' 
            ? req.params.sessionId 
            : parseInt(req.params.sessionId.toString(), 10);
            
          console.log('Parsed sessionId:', sessionId);
          
          if (isNaN(sessionId)) {
            throw new Error('Invalid session ID format');
          }
        } catch (parseError) {
          console.error('Session ID parsing error:', parseError);
          return res.status(400).json({
            success: false,
            message: "Invalid session ID format",
            details: "The session ID must be a valid number",
            received: req.params.sessionId
          });
        }

        // Fetch transcriptions
        console.log('Attempting to fetch transcriptions for session:', sessionId);
        const transcriptions = await storage.getTranscriptions(sessionId);
        console.log(`Found ${transcriptions.length} transcriptions`);

        // Format and send response
        const response = {
          success: true,
          sessionId,
          transcriptions: transcriptions.map(t => ({
            id: t.id,
            originalText: t.originalText,
            translatedText: t.translatedText,
            clipStartTime: t.clipStartTime,
            clipEndTime: t.clipEndTime,
            sourceLanguage: t.sourceLanguage,
            status: t.status,
            createdAt: t.createdAt
          }))
        };

        return res.json(response);

      } catch (error) {
        console.error('=== Transcriptions Error ===');
        console.error('Error:', error);
        console.error('Stack:', error instanceof Error ? error.stack : 'No stack trace');
        console.error('Request URL:', req.url);
        console.error('Session ID attempted:', req.params.sessionId);

        return res.status(500).json({
          success: false,
          message: "Failed to fetch transcriptions",
          error: error instanceof Error ? error.message : "Unknown error",
          timestamp: new Date().toISOString()
        });
      }
    });

    // Add endpoint to update transcription status
    app.post("/api/transcriptions/:id/status", async (req, res) => {
      try {
        const transcriptionId = Number(req.params.id);
        const { status } = req.body;

        if (!['pending', 'accepted', 'rejected'].includes(status)) {
          return res.status(400).json({
            message: "Invalid status",
            details: "Status must be one of: pending, accepted, rejected"
          });
        }

        const updatedTranscription = await storage.updateTranscription(transcriptionId, { status });
        if (!updatedTranscription) {
          return res.status(404).json({
            message: "Transcription not found"
          });
        }

        res.json(updatedTranscription);
      } catch (error) {
        console.error("Error updating transcription status:", error);
        res.status(500).json({
          message: "Failed to update transcription status",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Add session approved transcriptions route
    app.get("/api/sessions/:sessionId/transcriptions/approved", async (req, res) => {
      try {
        const sessionId = parseInt(req.params.sessionId, 10);
        
        if (isNaN(sessionId)) {
          return res.status(400).json({
            success: false,
            message: "Invalid session ID format",
            details: "The session ID must be a valid number"
          });
        }

        // Get approved transcriptions for the session
        const transcriptions = await storage.getTranscriptions(sessionId, "accepted");
        
        return res.json({
          success: true,
          sessionId,
          transcriptions: transcriptions.map(t => ({
            id: t.id,
            originalText: t.originalText,
            translatedText: t.translatedText,
            clipStartTime: t.clipStartTime,
            clipEndTime: t.clipEndTime,
            sourceLanguage: t.sourceLanguage,
            status: t.status,
            createdAt: t.createdAt
          }))
        });

      } catch (error) {
        console.error('Error fetching approved transcriptions:', error);
        console.error('Stack:', error instanceof Error ? error.stack : 'No stack trace');

        return res.status(500).json({
          success: false,
          message: "Failed to fetch approved transcriptions",
          error: error instanceof Error ? error.message : "Unknown error",
          timestamp: new Date().toISOString()
        });
      }
    });

    // Add webhook to trigger Pusher when new transcription is created
    app.post("/api/transcriptions", async (req, res) => {
      try {
        const transcriptionData = req.body;
        const newTranscription = await storage.createTranscription(transcriptionData);

        // Format transcription data for Pusher
        const transcriptionForPusher = {
          id: newTranscription.id,
          originalText: newTranscription.originalText,
          translatedText: newTranscription.translatedText,
          clipStartTime: newTranscription.clipStartTime,
          clipEndTime: newTranscription.clipEndTime,
          sourceLanguage: newTranscription.sourceLanguage
        };

        // Trigger Pusher event on the session-specific channel
        const channelName = `session-${newTranscription.sessionId}-transcriptions`;
        await pusher.trigger(channelName, 'new-transcription', {
          transcription: transcriptionForPusher
        });

        // Log successful Pusher event
        console.log(`Triggered new transcription event on channel ${channelName}:`, transcriptionForPusher);

        res.status(201).json(newTranscription);
      } catch (error) {
        console.error("Error creating transcription:", error);
        res.status(500).json({ 
          message: "Failed to create transcription",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    app.post("/api/sessions", async (req, res) => {
      if (!req.isAuthenticated()) return res.sendStatus(401);
      try {
        const validated = insertSessionSchema.parse(req.body);
        const { speakerIds, ...sessionData } = validated;
        const session = await storage.createSession(sessionData);
        if (speakerIds && Array.isArray(speakerIds)) {
          for (const speakerId of speakerIds) {
            await storage.assignSpeakerToSession(session.id, speakerId);
          }
        }
        const sessionWithSpeakers = await storage.getSessionWithSpeakers(
          session.id,
        );
        res.status(201).json(sessionWithSpeakers);
      } catch (error) {
        console.error("Error creating session:", error);
        res.status(500).json({ error: "Failed to create session" });
      }
    });

    app.patch("/api/sessions/:id", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const sessionId = Number(req.params.id);
        const { speakerIds, ...updateData } = req.body;
        const updatedSession = await storage.updateSession(
          sessionId,
          updateData,
        );
        if (speakerIds && Array.isArray(speakerIds)) {
          await storage.removeSessionSpeakers(sessionId);
          for (const speakerId of speakerIds) {
            await storage.assignSpeakerToSession(sessionId, speakerId);
          }
        }
        const sessionWithSpeakers =
          await storage.getSessionWithSpeakers(sessionId);
        // Send Pusher notification
        await pusher.trigger("notifications", "session-updated", {
          sessionId,
          sessionTitle: updateData.sessionTitle,
          timestamp: new Date().toISOString(),
        });
        res.json(sessionWithSpeakers);
      } catch (error) {
        console.error("Error updating session:", error);
        res.status(500).json({ error: "Failed to update session" });
      }
    });

    app.delete("/api/sessions/:id", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const sessionId = Number(req.params.id);
        await storage.deleteSession(sessionId);
        res.sendStatus(200);
      } catch (error) {
        console.error("Error deleting session:", error);
        res.status(500).json({ error: "Failed to delete session" });
      }
    });

    // Speakers routes
    app.get("/api/speakers", async (_req, res) => {
      const speakers = await storage.getSpeakers();
      res.json(speakers);
    });

    app.post("/api/speakers", async (req, res) => {
      if (!req.isAuthenticated()) return res.sendStatus(401);
      const validated = insertSpeakerSchema.parse(req.body);
      const speaker = await storage.createSpeaker(validated);
      res.status(201).json(speaker);
    });

    app.patch("/api/speakers/:id", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const speakerId = Number(req.params.id);
        const validated = insertSpeakerSchema.parse(req.body);
        const updatedSpeaker = await storage.updateSpeaker(
          speakerId,
          validated,
        );
        if (!updatedSpeaker) {
          return res.status(404).json({ message: "Speaker not found" });
        }
        res.json(updatedSpeaker);
      } catch (error) {
        console.error("Error updating speaker:", error);
        res.status(500).json({ error: "Failed to update speaker" });
      }
    });

    app.delete("/api/speakers/:id", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const speakerId = Number(req.params.id);
        await storage.deleteSpeaker(speakerId);
        res.sendStatus(200);
      } catch (error) {
        console.error("Error deleting speaker:", error);
        res.status(500).json({ error: "Failed to delete speaker" });
      }
    });



    // Session Speakers routes
    app.get("/api/sessions/:sessionId/speakers", async (req, res) => {
      const speakers = await storage.getSessionSpeakers(
        Number(req.params.sessionId),
      );
      res.json(speakers);
    });

    app.post(
      "/api/sessions/:sessionId/speakers/:speakerId",
      async (req, res) => {
        if (!req.isAuthenticated()) return res.sendStatus(401);
        const sessionId = Number(req.params.sessionId);
        const speakerId = Number(req.params.speakerId);
        const assignment = await storage.assignSpeakerToSession(
          sessionId,
          speakerId,
        );
        res.status(201).json(assignment);
      },
    );

    // News routes
    app.get("/api/news", async (_req, res) => {
      const news = await storage.getNews();
      res.json(news);
    });

    app.post("/api/news", async (req, res) => {
      if (!req.isAuthenticated()) return res.sendStatus(401);
      const validated = insertNewsSchema.parse(req.body);
      const newsItem = await storage.createNews({
        ...validated,
        authorId: req.user!.id,
      });
      res.status(201).json(newsItem);
    });

    app.patch("/api/news/:id", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const newsId = Number(req.params.id);
        const validated = insertNewsSchema.parse(req.body);
        const updatedNews = await storage.updateNews(newsId, {
          ...validated,
          authorId: req.user!.id,
        });
        if (!updatedNews) {
          return res.status(404).json({ message: "News item not found" });
        }
        res.json(updatedNews);
      } catch (error) {
        console.error("Error updating news:", error);
        res.status(500).json({ error: "Failed to update news" });
      }
    });

    app.delete("/api/news/:id", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const newsId = Number(req.params.id);
        await storage.deleteNews(newsId);
        res.sendStatus(200);
      } catch (error) {
        console.error("Error deleting news:", error);
        res.status(500).json({ error: "Failed to delete news" });
      }
    });

    // Add poll delete endpoint with proper error handling
    app.delete("/api/polls/:id", async (req, res) => {
      try {
        const pollId = Number(req.params.id);
        
        if (isNaN(pollId)) {
          return res.status(400).json({
            success: false,
            message: "Invalid poll ID format",
            details: "Poll ID must be a number"
          });
        }

        await storage.deletePoll(pollId);
        
        res.json({
          success: true,
          message: "Poll and all related data deleted successfully"
        });
      } catch (error) {
        console.error("Error deleting poll:", error);
        res.status(500).json({
          success: false,
          message: "Failed to delete poll",
          error: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Add poll response submission endpoint with improved handling
    app.post("/api/polls/:pollId/responses", async (req, res) => {
      try {
        if (!req.isAuthenticated()) {
          return res.status(401).json({
            success: false,
            message: "Authentication required"
          });
        }

        const pollId = Number(req.params.pollId);
        
        if (isNaN(pollId)) {
          return res.status(400).json({
            success: false,
            message: "Invalid poll ID format", 
            details: "Poll ID must be a number"
          });
        }

        const responses = req.body.responses;
        if (!Array.isArray(responses)) {
          return res.status(400).json({
            success: false,
            message: "Invalid response format", 
            details: "Responses must be an array"
          });
        }

        const results = [];

        for (const response of responses) {
          if (!response || !response.questionId || response.answer === undefined) {
            console.log('Invalid response object:', response);
            continue;
          }

          console.log('Processing response for question', response.questionId, ':', response.answer);

          const pollResponse = {
            pollId,
            questionId: response.questionId,
            userId: req.user!.id,
            selectedOptions: [] as string[],
            textResponse: null as string | null,
            numericResponse: null as number | null,
            yesNoResponse: null as string | null
          };

          // Handle multiple choice (both simple and with other)
          if (Array.isArray(response.answer)) {
            // Simple multiple choice
            pollResponse.selectedOptions = response.answer;
          } else if (typeof response.answer === 'object' && response.answer !== null) {
            // Multiple choice with other
            if ('selected' in response.answer && Array.isArray(response.answer.selected)) {
              // Keep "Other" in selectedOptions to match with the poll question options
              pollResponse.selectedOptions = response.answer.selected;
              // Store the "Other" text separately
              if (response.answer.selected.includes('Other') && response.answer.other) {
                pollResponse.textResponse = response.answer.other;
              }
            }
          } else if (typeof response.answer === 'string') {
            if (['yes', 'no', 'maybe'].includes(response.answer.toLowerCase())) {
              pollResponse.yesNoResponse = response.answer.toLowerCase();
            } else {
              pollResponse.textResponse = response.answer;
            }
          } else if (typeof response.answer === 'number') {
            pollResponse.numericResponse = response.answer;
          }

          console.log('Formatted poll response:', pollResponse);
          const savedResponse = await storage.createPollResponse(pollResponse);
          results.push(savedResponse);
        }

        res.status(201).json({
          success: true,
          pollId,
          responses: results
        });

      } catch (error) {
        console.error("Error submitting poll responses:", error);
        res.status(500).json({
          success: false,
          message: "Failed to submit poll responses",
          error: error instanceof Error ? error.message : "Unknown error" 
        });
      }
    });

    // Get questions for a specific user - Unified route handler
    app.get("/api/users/:userId/questions", async (req, res) => {
      try {
        const userId = parseInt(req.params.userId, 10);
        
        if (isNaN(userId)) {
          return res.status(400).json({
            success: false,
            message: "Invalid user ID format",
            details: "User ID must be a number"
          });
        }

        // Get user's questions
        const questions = await storage.getUserQuestions(userId);
        
        res.json({
          success: true,
          questions: questions.map(q => ({
            id: q.id,
            question: q.question,
            questionAr: q.questionAr,
            sessionId: q.sessionId,
            userId: q.userId,
            status: q.status,
            response: q.response,
            responseAr: q.responseAr,
            timestamp: q.timestamp
          }))
        });
      } catch (error) {
        console.error("Error fetching user questions:", error);
        res.status(500).json({
          success: false,
          message: "Failed to fetch user questions",
          error: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Add webhook to trigger Pusher when new transcription is created
    app.post("/api/transcriptions", async (req, res) => {
      try {
        const transcriptionData = req.body;
        const newTranscription = await storage.createTranscription(transcriptionData);

        // Format transcription data for Pusher
        const transcriptionForPusher = {
          id: newTranscription.id,
          originalText: newTranscription.originalText,
          translatedText: newTranscription.translatedText,
          clipStartTime: newTranscription.clipStartTime,
          clipEndTime: newTranscription.clipEndTime,
          sourceLanguage: newTranscription.sourceLanguage,
          status: newTranscription.status
        };

        // Trigger Pusher event on the session-specific channel
        const channelName = `session-${newTranscription.sessionId}-transcriptions`;
        await pusher.trigger(channelName, 'new-transcription', {
          transcription: transcriptionForPusher
        });

        // Log successful Pusher event
        console.log(`Triggered new transcription event on channel ${channelName}:`, transcriptionForPusher);

        res.status(201).json(newTranscription);
      } catch (error) {
        console.error("Error creating transcription:", error);
        res.status(500).json({ 
          message: "Failed to create transcription",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Add endpoint to update transcription status with Pusher notification
    app.post("/api/transcriptions/:id/status", async (req, res) => {
      try {
        const transcriptionId = Number(req.params.id);
        const { status } = req.body;

        if (!['pending', 'accepted', 'rejected'].includes(status)) {
          return res.status(400).json({
            message: "Invalid status",
            details: "Status must be one of: pending, accepted, rejected"
          });
        }

        const updatedTranscription = await storage.updateTranscription(transcriptionId, { status });
        if (!updatedTranscription) {
          return res.status(404).json({
            message: "Transcription not found"
          });
        }

        // Trigger Pusher event for status update
        const channelName = `session-${updatedTranscription.sessionId}-transcriptions`;
        await pusher.trigger(channelName, 'transcription-status-updated', {
          transcriptionId: updatedTranscription.id,
          status: updatedTranscription.status,
          timestamp: new Date().toISOString()
        });

        res.json(updatedTranscription);
      } catch (error) {
        console.error("Error updating transcription status:", error);
        res.status(500).json({
          message: "Failed to update transcription status",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Get questions for a specific user in a specific session
    app.get("/api/users/:userId/sessions/:sessionId/questions", async (req, res) => {
      try {
        const userId = parseInt(req.params.userId, 10);
        const sessionId = parseInt(req.params.sessionId, 10);
        
        if (isNaN(userId) || isNaN(sessionId)) {
          return res.status(400).json({
            success: false,
            message: "Invalid ID format",
            details: "Both user ID and session ID must be numbers"
          });
        }

        // Get user's questions for the specific session
        const questions = await storage.getQuestionsByUserAndSession(userId, sessionId);
        
        res.json({
          success: true,
          questions: questions.map(q => ({
            id: q.id,
            question: q.question,
            questionAr: q.questionAr,
            sessionId: q.sessionId,
            userId: q.userId,
            status: q.status,
            response: q.response,
            responseAr: q.responseAr,
            timestamp: q.timestamp
          }))
        });
      } catch (error) {
        console.error("Error fetching user session questions:", error);
        res.status(500).json({
          success: false,
          message: "Failed to fetch user session questions",
          error: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Generic notification endpoint
    app.post("/api/notifications/send", async (req, res) => {
      try {
        console.log("Received notification request with body:", req.body);
        const { 
          title, 
          message, 
          description, 
          body, 
          type = "info", 
          userId, 
          url,
          sessionId,
          isLiveStream
        } = req.body;

        // Allow multiple field names for the message content
        const notificationMessage = message || description || body;

        if (!title || !notificationMessage) {
          console.log("Missing required fields in request:", { title, notificationMessage });
          return res.status(400).json({
            message: "Missing required fields",
            details: "Both title and description/message are required"
          });
        }

        // Get user's notification channel if userId is provided
        let channels = [];
        if (userId) {
          const userChannels = await storage.getAllNotificationChannels();
          channels = userChannels.filter(channel => channel.userId === userId);
        } else {
          channels = await storage.getAllNotificationChannels();
        }

        console.log(`Found ${channels.length} channels to notify`);

        // Send notification through Pusher to all relevant channels
        for (const channel of channels) {
          await pusher.trigger(channel.channelName, "notification", {
            title,
            message: notificationMessage,
            type,
            url,
            sessionId,
            isLiveStream,
            timestamp: new Date().toISOString()
          });
        }

        res.json({ message: "Notification sent successfully" });
      } catch (error) {
        console.error("Error sending notification:", error);
        res.status(500).json({
          message: "Failed to send notification",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // News notification endpoint
    app.post("/api/notifications/news/:newsId", async (req, res) => {
      try {
        console.log(`Attempting to send notification for news ID: ${req.params.newsId}`);
        const newsId = Number(req.params.newsId);
        const { userId } = req.body; // Optional: send to specific user

        // Get news items
        const newsItems = await storage.getNews();
        const newsItem = newsItems.find(n => n.id === newsId);
        
        console.log("Found news item:", newsItem);
        
        if (!newsItem) {
          return res.status(404).json({
            message: "News item not found",
            details: "The specified news article does not exist"
          });
        }

        // Get user's notification channel if userId is provided
        let channels = [];
        if (userId) {
          const userChannels = await storage.getAllNotificationChannels();
          channels = userChannels.filter(channel => channel.userId === userId);
        } else {
          channels = await storage.getAllNotificationChannels();
        }

        console.log(`Found ${channels.length} channels to notify about news`);

        // Send notification through Pusher to all relevant channels
        for (const channel of channels) {
          await pusher.trigger(channel.channelName, "notification", {
            title: newsItem.title,
            message: newsItem.content, 
            type: "news",
            timestamp: new Date().toISOString(),
            newsId: newsItem.id
          });
        }

        res.json({ message: "News notification sent successfully" });
      } catch (error) {
        console.error("Error sending news notification:", error);
        res.status(500).json({
          message: "Failed to send news notification", 
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Media routes
    app.get("/api/media", async (req, res) => {
      const type = req.query.type as string | undefined;
      const media = await storage.getMedia(type);
      res.json(media);
    });

    app.post("/api/media", async (req, res) => {
      if (!req.isAuthenticated()) return res.sendStatus(401);
      const validated = insertMediaSchema.parse(req.body);
      const mediaItem = await storage.createMedia({
        ...validated,
        uploaderId: req.user!.id,
      });
      res.status(201).json(mediaItem);
    });

    app.patch("/api/media/:id", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const mediaId = Number(req.params.id);
        const validated = insertMediaSchema.parse(req.body);
        const updatedMedia = await storage.updateMedia(mediaId, {
          ...validated,
          uploaderId: req.user!.id,
        });
        if (!updatedMedia) {
          return res.status(404).json({ message: "Media item not found" });
        }
        res.json(updatedMedia);
      } catch (error) {
        console.error("Error updating media:", error);
        res.status(500).json({ error: "Failed to update media" });
      }
    });

    app.delete("/api/media/:id", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const mediaId = Number(req.params.id);
        await storage.deleteMedia(mediaId);
        res.sendStatus(200);
      } catch (error) {
        console.error("Error deleting media:", error);
        res.status(500).json({ error: "Failed to delete media" });
      }
    });



    // Chatbot route with improved validation and error handling
    app.post("/api/chat", async (req, res) => {
      try {
        console.log("Received chat request with body:", req.body);

        const { message } = req.body;

        if (!message || typeof message !== 'string' || message.trim().length === 0) {
          console.log("Invalid message format received:", message);
          return res.status(400).json({
            error: "Invalid message format",
            details: "Message must be a non-empty string"
          });
        }

        console.log("Processing chat message:", message);
        const response = await handleChatbotQuery(message.trim());
        console.log("Chat response generated:", response);

        res.json({ response });
      } catch (error) {
        console.error("❌ AI Chatbot Error:", error);
        const message = error instanceof Error ? error.message : "Unknown error occurred";
        res.status(500).json({
          error: "Failed to process chat message",
          details: message
        });
      }
    });

    // Settings routes
    app.get("/api/settings", async (req, res) => {
      try {
        const settings = await storage.getSettings();
        if (!settings) {
          return res.status(404).json({ message: "Settings not found" });
        }

        // Check for JWT token
        const authHeader = req.headers.authorization;
        const isAuthenticated = authHeader && authHeader.startsWith('Bearer ');
        let isAdmin = false;

        if (isAuthenticated) {
          try {
            const token = authHeader.split(" ")[1];
            const decoded = jwt.verify(token, JWT_SECRET) as SelectUser;
            isAdmin = decoded.role === "admin";
          } catch (err) {
            console.error("JWT verification failed:", err);
          }
        }

        if (!isAuthenticated || !isAdmin) {
          const publicSettings = {
            siteTitle: settings.siteTitle,
            siteTitleAr: settings.siteTitleAr,
            logoText: settings.logoText,
            logoTextAr: settings.logoTextAr,
            homeBannerTitle: settings.homeBannerTitle,
            homeBannerTitleAr: settings.homeBannerTitleAr,
            homeBannerDescription: settings.homeBannerDescription,
            homeBannerDescriptionAr: settings.homeBannerDescriptionAr,
            authWelcomeTitle: settings.authWelcomeTitle,
            authWelcomeTitleAr: settings.authWelcomeTitleAr,
            authDescription: settings.authDescription,
            authDescriptionAr: settings.authDescriptionAr,
            enableRegistration: settings.enableRegistration,
            openaiApiKey: "",
            firebaseApiKey: "",
            firebaseProjectId: "",
            firebaseAppId: "",
            firebaseMessagingSenderId: "",
            firebaseVapidKey: "",
            pusherAppId: "",
            pusherKey: "",
            pusherSecret: "",
            pusherCluster: "",
            deepgramApiKey: "",
          };
          return res.json(publicSettings);
        }
        res.json(settings);
      } catch (error) {
        console.error("Error fetching settings:", error);
        const message = error instanceof Error ? error.message : "Failed to fetch settings";
        res.status(500).json({ message });
      }
    });

    app.post("/api/settings", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const insertSettings = insertSettingsSchema.parse(req.body);
        const updatedSettings = await storage.updateSettings(insertSettings);
        res.json(updatedSettings);
      } catch (error) {
        console.error("Error saving settings:", error);
        const message =
          error instanceof Error ? error.message : "Failed to save settings";
        res.status(500).json({ message });
      }
    });

    app.post("/api/users/:id/reset-password", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      const userId = Number(req.params.id);
      const { password } = req.body;
      if (!password) {
        return res.status(400).json({ message: "Password is required" });
      }
      try {
        const hashedPassword = await hashPassword(password);
        const updatedUser = await storage.updateUser(userId, {
          password: hashedPassword,
        });
        res.json(updatedUser);
      } catch (error) {
        console.error("Error resetting password:", error);
        const message =
          error instanceof Error ? error.message : "Failed to reset password";
        res.status(400).json({ message });
      }
    });

    // User Management routes
    app.get("/api/users", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      const users = await storage.getUsers();
      res.json(users);
    });

    // Modified user update endpoint with proper session handling
    app.patch("/api/users/:id", async (req, res) => {
      if (!req.isAuthenticated()) {
        console.log("Authentication check failed");
        return res.status(401).json({ message: "Unauthorized" });
      }

      const userId = Number(req.params.id);

      // Allow users to update their own profile or admins to update any profile
      if (req.user?.id !== userId && req.user?.role !== "admin") {
        console.log("Authorization check failed - user cannot edit this profile");
        return res.status(403).json({ message: "Forbidden" });
      }

      try {
        console.log("Updating user with data:", req.body);
        // Explicitly extract sessionId and other fields from request body
        const {
          sessionId,
          role,
          isActive,
          profileImage,
          organization,
          position,
          phoneNumber,
          email,
          name,
        } = req.body;

        // If not admin, prevent updating role and isActive
        const updateData = req.user?.role === "admin"
          ? {
              role,
              isActive,
              profileImage,
              organization,
              position,
              phoneNumber,
              email,
              name,
              // Handle sessionId conversion with null checks
              sessionId: sessionId && sessionId !== "none" && sessionId !== "undefined" ? Number(sessionId) : null,
            }
          : {
              profileImage,
              organization,
              position,
              phoneNumber,
              email,
              name,
              // Same sessionId handling for non-admin users
              sessionId: sessionId && sessionId !== "none" && sessionId !== "undefined" ? Number(sessionId) : null,
            };

        console.log("Final update data:", updateData);

        // First update the user in the users table
        const updatedUser = await storage.updateUser(userId, updateData);
        console.log("Updated user:", updatedUser);

        try {
          // Then handle session assignments
          if (updateData.sessionId) {
            // Remove any existing session assignments first
            await storage.removeUserFromAllSessions(userId);
            // Then add the new session assignment
            await storage.assignUserToSession(userId, updateData.sessionId);
          } else {
            // If no session specified, just remove all session assignments
            await storage.removeUserFromAllSessions(userId);
          }
        } catch (sessionError) {
          console.error("Error handling session assignments:", sessionError);
          // Don't fail the whole update if session assignment fails
          // but do log it and return a warning in the response
          res.json({
            ...updatedUser,
            warning: "User updated but session assignment failed",
          });
          return;
        }

        res.json(updatedUser);
      } catch (error) {
        console.error("Error updating user:", error);
        res.status(500).json({
          message: "Failed to update user",
          details: error instanceof Error ? error.message : "Unknown error",
        });
      }
    });

    // Notifications routes using Pusher
    app.post("/api/notifications/register", async (req, res) => {
      try {
        const { userId, channelName } = req.body;
        
        if (!userId || !channelName) {
          return res.status(400).json({
            message: "Missing required fields",
            details: "Both userId and channelName are required"
          });
        }

        await storage.storeNotificationChannel(userId, channelName);
        res.status(201).json({ message: "Notification channel registered successfully" });
      } catch (error) {
        console.error("Error registering notification channel:", error);
        res.status(500).json({
          message: "Failed to register notification channel", 
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    app.delete("/api/notifications/unregister", async (req, res) => {
      try {
        const { channelName } = req.body;
        
        if (!channelName) {
          return res.status(400).json({
            message: "Missing channel name",
            details: "Channel name is required"
          });
        }

        await storage.removeNotificationChannel(channelName);
        res.status(200).json({ message: "Notification channel unregistered successfully" });
      } catch (error) {
        console.error("Error unregistering notification channel:", error);
        res.status(500).json({
          message: "Failed to unregister notification channel",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });



    app.get("/api/notifications/user/:userId", async (req, res) => {
      try {
        const userId = Number(req.params.userId);
        
        if (isNaN(userId)) {
          return res.status(400).json({
            message: "Invalid user ID",
            details: "User ID must be a number"
          });
        }

        const channels = await storage.getAllNotificationChannels();
        const userChannels = channels.filter(channel => channel.userId === userId);

        res.json({ channels: userChannels });
      } catch (error) {
        console.error("Error fetching user notifications:", error);
        res.status(500).json({
          message: "Failed to fetch notifications",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    app.delete("/api/users/:id", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      const userId = Number(req.params.id);
      if (userId === req.user.id) {
        return res.status(400).json({ message: "Cannot delete own account" });
      }
      try {
        // Get user details before deletion to access profile image
        const user = await storage.getUser(userId);
        if (!user) {
          return res.status(404).json({ message: "User not found" });
        }

        // Delete the user from database
        await storage.deleteUser(userId);

        // If user had a profile image, delete it
        if (user.profileImage && !user.profileImage.startsWith("http")) {
          const imagePath = path.join(
            process.cwd(),
            user.profileImage.replace(/^\//, ""),
          );
          console.log("🗑️ Attempting to delete profile image:", imagePath);

          try {
            if (fs.existsSync(imagePath)) {
              fs.unlinkSync(imagePath);
              console.log("✅ Profile image deleted successfully");
            }
          } catch (fileError) {
            console.error("❌ Error deleting profile image:", fileError);
            // Don't return error since user is already deleted
          }
        }

        res.sendStatus(200);
      } catch (error) {
        console.error("Error deleting user:", error);
        res.status(400).json({
          message:
            error instanceof Error ? error.message : "Failed to delete user",
        });
      }
    });

    // User Sessions route - add this after other user routes
    app.get("/api/user/sessions", async (req, res) => {
      if (!req.isAuthenticated()) {
        return res.status(401).json({ message: "Unauthorized" });
      }

      try {
        // Get all sessions assigned to the user through userSessions table
        const sessions = await storage.getUserSessions(req.user!.id);
        res.json(sessions);
      } catch (error) {
        console.error("Error fetching user sessions:", error);
        res.status(500).json({ error: "Failed to fetch user sessions" });
      }
    });


    // Configure multer for handling file uploads with increased size limit
    const storageProfile = multer.diskStorage({
      destination: function (_req, _file, cb) {
        const uploadDir = "uploads/profiles";
        console.log("📁 Creating upload directory:", uploadDir);        // Create directory if it doesn't exist
        if (!fs.existsSync(uploadDir)) {
          fs.mkdirSync(uploadDir, {recursive: true });
          console.log("✅ Created upload directory");
        }
        cb(null, uploadDir);
      },
      filename: function (_req, file, cb) {
        console.log("📄 Processing file upload:", file.originalname);
        const uniqueSuffix = `${Date.now()}-${Math.round(Math.random() * 1e9)}`;
        const filename = `${uniqueSuffix}${path.extname(file.originalname)}`;
        console.log("📝 Generated filename:", filename);
        cb(null, filename);
      },
    });

    const uploadProfile = multer({
      storage: storageProfile,
      limits: {
        fileSize: 10 * 1024 * 1024 // 10MB in bytes
      }
    });

    // Add the file upload endpoint after the user management routes
    app.post("/api/upload", uploadProfile.single("file"), (req, res) => {
      console.log("📤 Received file upload request");
      if (!req.file) {
        console.error("❌ No file received in request");
        return res.status(400).json({ error: "No file uploaded" });
      }

      console.log("📦 File details:", {
        filename: req.file.filename,
        originalname: req.file.originalname,
        mimetype: req.file.mimetype,
        size: req.file.size
      });

      const fileUrl = `/uploads/profiles/${req.file.filename}`;
      console.log("🔗 Generated file URL:", fileUrl);
      res.json({ url: fileUrl });
    });

    // Serve uploaded files
    app.use("/uploads", express.static(path.join(process.cwd(), "uploads")));


    app.post("/api/notifications/poll", async (req, res) => {
      try {
        // Get token from Authorization header
        const authHeader = req.headers.authorization;
        if (!authHeader || !authHeader.startsWith('Bearer ')) {
          return res.status(401).json({ message: "Unauthorized" });
        }

        const token = authHeader.split(" ")[1];
        const decoded = jwt.verify(token, JWT_SECRET) as SelectUser;

        // Check if user is admin or moderator
        if (decoded.role !== "admin" && decoded.role !== "moderator") {
          return res.status(403).json({ message: "Forbidden" });
        }

        const { type, pollId, message } = req.body;

        if (type !== "poll" || !pollId) {
          return res.status(400).json({ message: "Invalid notification data" });
        }

        // Send notification through Pusher
        await pusher.trigger("notifications", "poll-notification", {
          type,
          pollId,
          message,
          url: `/polls/${pollId}/submit`,
          timestamp: new Date().toISOString(),
        });

        res.json({ success: true });
      } catch (error) {
        console.error("Error sending notification:", error);
        if (error instanceof jwt.JsonWebTokenError) {
          return res.status(401).json({ message: "Invalid token" });
        }
        res.status(500).json({ error: "Failed to send notification" });
      }
    });

    app.post("/api/polls/:id/announce-results", async (req, res) => {
      try {
        const pollId = Number(req.params.id);
        const poll = await storage.getPoll(pollId);

        if (!poll) {
          return res.status(404).json({ message: "Poll not found" });
        }

        // Update poll to mark results as published
        const updatedPoll = await storage.updatePoll(pollId, {
          resultsPublished: true
        });

        if (!updatedPoll) {
          throw new Error("Failed to update poll");
        }

        // Send notification about results
        await pusher.trigger("notifications", "notification", {
          id: Date.now().toString(),
          title: poll.title,
          body: "Poll results are now available!",
          url: `/polls/${pollId}/results`, // Ensure this URL points to results page
          timestamp: new Date().toISOString(),
          type: 'poll-results' // Add type to differentiate notification
        });

        res.json(updatedPoll);
      } catch (error) {
        console.error("Error announcing poll results:", error);
        res.status(500).json({ error: "Failed to announce poll results" });
      }
    });

    // Transcriptions routes
    app.get("/api/transcriptions", async (req, res) => {
      try {
        const sessionId = req.query.sessionId
          ? Number(req.query.sessionId)
          : undefined;
        const transcriptionList = await storage.getTranscriptions(sessionId);
        res.json(transcriptionList);
      } catch (error) {
        console.error("Error fetching transcriptions:", error);
        res.status(500).json({ error: "Failed to fetch transcriptions" });
      }
    });

    app.post("/api/transcriptions/start", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }

      try {
        const { sessionId, mode } = req.body;
        if (!sessionId) {
          return res.status(400).json({ error: "Session ID is required" });
        }

        // Update settings with the selected mode
        await storage.updateSettings({
          transcriptionMode: mode || "test", // Default totest mode if not specified
        });

        // Start transcription service
        startTranscriptionService(sessionId);
        res.json({ message: "Transcription started successfully" });
      } catch (error) {
        console.error("Error starting transcription:", error);
        res.status(500).json({
          error:
            error instanceof Error
              ? error.message
              : "Failed to start transcription",
        });
      }
    });

    app.post("/api/transcriptions/stop", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const { sessionId } = req.body;
        if (!sessionId) {
          return res.status(400).json({ error: "Session ID is required" });
        }
        stopTranscriptionService(sessionId);
        res.json({ message: "Transcription stopped successfully" });
      } catch (error) {
        console.error("Error stopping transcription:", error);
        res.status(500).json({ error: "Failed to stop transcription" });
      }
    });

    app.post("/api/transcriptions/:id/status", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const transcriptionId = Number(req.params.id);
        const { status } = req.body;
        if (!status || !["pending", "accepted", "rejected"].includes(status)) {
          return res.status(400).json({ message: "Invalid status" });
        }
        const updated = await storage.updateTranscription(transcriptionId, {
          status,
          updatedAt: new Date(),
        });
        res.json(updated);
      } catch (error) {
        console.error("Error updating transcription status:", error);
        res
          .status(500)
          .json({ error: "Failed to update transcription status" });
      }
    });

    app.post("/api/transcriptions/:id/edit", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const transcriptionId = Number(req.params.id);
        const { originalText, translatedText } = req.body;
        if (!originalText || !translatedText) {
          return res.status(400).json({ message: "Both texts are required" });
        }
        const updated = await storage.updateTranscription(transcriptionId, {
          originalText,
          translatedText,
          updatedAt: new Date(),
        });
        res.json(updated);
      } catch (error) {
        console.error("Error updating transcription:", error);
        res.status(500).json({ error: "Failed to update transcription" });
      }
    });

    // Add this after the other transcription routes
    app.get("/api/transcriptions/active", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const activeSessionIds = Array.from(transcriptionIntervals.keys());
        res.json({ activeSessionIds });
      } catch (error) {
        console.error("Error getting active transcription sessions:", error);
        res
          .status(500)
          .json({ error: "Failed to get active transcription sessions" });
      }
    });

    // Polls routes
    app.get("/api/polls", async (req, res) => {
      try {
        const eventId = req.query.eventId
          ? Number(req.query.eventId)
          : undefined;
        const sessionId = req.query.sessionId
          ? Number(req.query.sessionId)
          : undefined;
        const polls = await storage.getPolls(eventId, sessionId);
        res.json(polls);
      } catch (error) {
        console.error("Error fetching polls:", error);
        res.status(500).json({ error: "Failed to fetch polls" });
      }
    });

    app.post("/api/polls", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const startDate = new Date(req.body.startDate);
        const endDate = new Date(req.body.endDate);
        if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
          throw new Error("Invalid dates provided");
        }
        const pollData = {
          ...req.body,
          creatorId: req.user.id,
          startDate, // Pass the actual Date object
          endDate, // Pass the actual Date object
        };
        const questions = req.body.questions || [];
        delete pollData.questions;
        console.log("Poll data to insert:", pollData);
        const poll = await storage.createPoll(pollData);
        if (questions.length > 0) {
          for (const question of questions) {
            await storage.createPollQuestion({
              pollId: poll.id,
              pollTypeId: question.pollTypeId,
              question: question.question,
              questionAr: question.questionAr,
              options: question.options,
              optionsAr: question.optionsAr,
              required: question.required,
              order: question.order,
            });
          }
        }
        res.status(201).json(poll);
      } catch (error) {
        console.error("Error creating poll:", error);
        res.status(500).json({ error: "Failed to create poll" });
      }
    });

    app.get("/api/polls/:id", async (req, res) => {
      const pollId = Number(req.params.id);
      console.log(`[GET /api/polls/:id] Fetching poll with ID: ${pollId}`);
      if (isNaN(pollId)) {
        return res.status(400).json({ message: "Invalid poll ID" });
      }
      const poll = await storage.getPoll(pollId);
      if (!poll) {
        console.log(`[GET /api/polls/:id] Poll ${pollId} not found`);
        return res.status(404).json({ message: "Poll not found" });
      }
      console.log(`[GET /api/polls/:id] Successfully retrieved poll:`, poll);
      res.json(poll);
    });

    app.get("/api/polls/:id/questions", async (req, res) => {
      try {
        const pollId = Number(req.params.id);
        console.log(
          `[GET /api/polls/:id/questions] Fetching questions for poll ID: ${pollId}`,
        );
        const poll = await storage.getPoll(pollId);
        if (!poll) {
          console.log(
            `[GET /api/polls/:id/questions] Poll ${pollId} not found`,
          );
          return res.status(404).json({ message: "Poll not found" });
        }
        const questions = await storage.getPollQuestions(pollId);
        console.log(
          `[GET /api/polls/:id/questions] Found ${questions.length} questions for poll ${pollId}`,
        );
        res.json(questions);
      } catch (error) {
        console.error(
          "[GET /api/polls/:id/questions] Error fetching questions:",
          error,
        );
        res.status(500).json({ error: "Failed to fetch questions" });
      }
    });

    app.get("/api/polls/:id/responses", async (req, res) => {
      try {
        const pollId = Number(req.params.id);
        console.log(`Fetching responses for poll ID: ${pollId}`);
        const poll = await storage.getPoll(pollId);
        if (!poll) {
          console.log(`Poll ${pollId} not found when fetching responses`);
          return res.status(404).json({ message: "Poll not found" });
        }
        const responses = await storage.getPollResponses(pollId);
        console.log(`Found ${responses.length} responses for poll ${pollId}`);
        res.json(responses);
      } catch (error) {
        console.error("Error fetching poll responses:", error);
        res.status(500).json({ error: "Failed to fetch poll responses" });
      }
    });

    app.post("/api/polls/:id/responses", async (req, res) => {
      if (!req.isAuthenticated()) return res.sendStatus(401);
      try {
        const pollId = Number(req.params.id);
        if (isNaN(pollId)) {
          return res.status(400).json({ message: "Invalid poll ID" });
        }
        const { responses } = req.body;
        console.log("Received poll submission:", { pollId, responses });
        if (!responses) {
          return res.status(400).json({ error: "No answers provided" });
        }
        const questions = await storage.getPollQuestions(pollId);
        for (const [questionId, answer] of Object.entries(responses)) {
          const question = questions.find((q) => q.id === Number(questionId));
          if (!question) continue;
          const responseData: any = {
            pollId,
            questionId: Number(questionId),
            userId: req.user.id,
            numericResponse: null,
            textResponse: null,
            selectedOptions: null,
            yesNoResponse: null,
          };
          switch (question.pollTypeId) {
            case 1:
              responseData.numericResponse = Number(answer);
              break;
            case 2:
              responseData.yesNoResponse = answer as string;
              break;
            case 3:
              if (Array.isArray(answer)) {
                responseData.selectedOptions = answer;
              }
              break;
            case 4:
              responseData.textResponse = answer as string;
              break;
            case 7:
              if (typeof answer === "object" && "selected" in answer) {
                const { selected, other } = answer as {
                  selected: string[];
                  other: string;
                };
                responseData.selectedOptions = selected;
                if (selected.includes("Other") && other) {
                  responseData.textResponse = other;
                }
              }
              break;
          }
          console.log("Creating poll response:", responseData);
          await storage.createPollResponse(responseData);
        }
        res
          .status(201)
          .json({ message: "Poll responses submitted successfully" });
      } catch (error) {
        console.error("Error submitting poll responses:", error);
        res.status(500).json({ error: "Failed to submit poll responses" });
      }
    });

    // Add PATCH endpoint for polls
    app.patch("/api/polls/:id", async (req, res) => {
      try {
        // Get token from Authorization header
        const authHeader = req.headers.authorization;
        if (!authHeader || !authHeader.startsWith('Bearer ')) {
          return res.status(401).json({ message: "Unauthorized" });
        }

        const token = authHeader.split(" ")[1];
        const decoded = jwt.verify(token, JWT_SECRET) as SelectUser;

        // Check if user is admin or moderator
        if (decoded.role !== "admin" && decoded.role !== "moderator") {
          return res.status(403).json({ message: "Forbidden" });
        }

        const pollId = Number(req.params.id);
        const { resultsPublished, ...updateData } = req.body;

        // Update poll using storage interface
        const updatedPoll = await storage.updatePoll(pollId, {
          ...updateData,
          resultsPublished
        });

        if (!updatedPoll) {
          return res.status(404).json({ message: "Poll not found" });
        }

        res.json(updatedPoll);
      } catch (error) {
        console.error("Error updating poll:", error);
        if (error instanceof jwt.JsonWebTokenError) {
          return res.status(401).json({ message: "Invalid token" });
        }
        res.status(500).json({ error: "Failed to update poll" });
      }
    });

    app.delete("/api/polls/:id", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const pollId = Number(req.params.id);
        await storage.deletePoll(pollId);
        res.sendStatus(200);
      } catch (error) {
        console.error("Error deleting poll:", error);
        res.status(500).json({ error: "Failed to delete poll" });
      }
    });

    // Add questions routes
    app.get("/api/questions", async (req, res) => {
      try {
        const sessionId = req.query.sessionId
          ? Number(req.query.sessionId)
          : null;
        const questions = await storage.getQuestions(sessionId);
        res.json(questions);
      } catch (error) {
        console.error("Error fetching questions:", error);
        res.status(500).json({ error: "Failed to fetch questions" });
      }
    });

    app.post("/api/questions", async (req, res) => {
      if (!req.isAuthenticated()) {
        return res.status(401).json({ message: "Unauthorized" });
      }

      try {
        console.log("Question submission attempt by user:", req.user?.username);

        const questionData = {
          ...req.body,
          userId: req.user!.id,
          questionAr: req.body.questionAr || "",
          sessionId: req.body.sessionId || null,
        };

        const validated = insertQuestionSchema.parse(questionData);
        const question = await storage.createQuestion(validated);

        console.log("Question created successfully:", question);
        res.status(201).json(question);
      } catch (error) {
        console.error("Error creating question:", error);
        if (error instanceof z.ZodError) {
          return res.status(400).json({ error: error.errors[0].message });
        }
        res.status(500).json({ error: "Failed to create question" });
      }
    });
    // Question status update route
    app.post("/api/questions/:id/status", async (req, res) => {
      try {
        // Get token from Authorization header
        const authHeader = req.headers.authorization;
        if (!authHeader || !authHeader.startsWith('Bearer ')) {
          return res.status(401).json({ message: "Unauthorized" });
        }

        const token = authHeader.split(" ")[1];
        const decoded = jwt.verify(token, JWT_SECRET) as SelectUser;

        // Check if user is admin or moderator
        if (decoded.role !== "admin" && decoded.role !== "moderator") {
          return res.status(403).json({ message: "Forbidden" });
        }

        const questionId = Number(req.params.id);
        const { status } = req.body;

        const updatedQuestion = await storage.updateQuestion(questionId, { status });

        // Notify through Pusher if available
        try {
          await pusher.trigger("questions", "status-updated", {
            questionId,
            status,
            timestamp: new Date().toISOString(),
          });
        } catch (error) {
          console.warn("Failed to send pusher notification:", error);
        }

        res.json(updatedQuestion);
      } catch (error) {
        console.error("Error updating question status:", error);
        if (error instanceof jwt.JsonWebTokenError) {
          return res.status(401).json({ message: "Invalid token" });
        }
        res.status(500).json({ error: "Failed to update question status" });
      }
    });

    // Question response update route
    app.post("/api/questions/:id/respond", async (req, res) => {
      try {
        // Get token from Authorization header
        const authHeader = req.headers.authorization;
        if (!authHeader || !authHeader.startsWith('Bearer ')) {
          return res.status(401).json({ message: "Unauthorized" });
        }

        const token = authHeader.split(" ")[1];
        const decoded = jwt.verify(token, JWT_SECRET) as SelectUser;

        // Check if user is admin or moderator
        if (decoded.role !== "admin" && decoded.role !== "moderator") {
          return res.status(403).json({ message: "Forbidden" });
        }

        const questionId = Number(req.params.id);
        const { response } = req.body;

        const updatedQuestion = await storage.updateQuestion(questionId, {
          response,
          responseAr: "", // Add empty Arabic response as required by schema
        });

        // Notify through Pusher if available
        try {
          await pusher.trigger("questions", "response-updated", {
            questionId,
            timestamp: new Date().toISOString(),
          });
        } catch (error) {
          console.warn("Failed to send pusher notification:", error);
        }

        res.json(updatedQuestion);
      } catch (error) {
        console.error("Error updating question response:", error);
        if (error instanceof jwt.JsonWebTokenError) {
          return res.status(401).json({ message: "Invalid token" });
        }
        res.status(500).json({ error: "Failed to update question response" });
      }
    });

    // Test audio processing endpoint
    app.post("/api/test/process-audio", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const filePath = path.join(process.cwd(), "uploads", "1.mp3");
        if (!fs.existsSync(filePath)) {
          return res.status(404).json({ error: "Test audio file not found" });
        }
        await processAudioFile(1, filePath);
        res.json({ message: "Audio processing completed successfully" });
      } catch (error) {
        console.error("Error processing audio:", error);
        res.status(500).json({ error: "Failed to process audio file" });
      }
    });

    app.get("/api/poll-types", async (_req, res) => {
      try {
        const types = await storage.getPollTypes();
        res.json(types);
      } catch (error) {
        console.error("Error fetching poll types:", error);
        res.status(500).json({ error: "Failed to fetch poll types" });
      }
    });

    // RTMP Server Control
    app.post("/api/rtmp/start", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        if (isRTMPServerRunning()) {
          return res.json({ message: "RTMP server is already running" });
        }
        const success = startRTMPServer();
        if (success) {
          res.json({ message: "RTMP server started successfully" });
        } else {
          res.status(500).json({ error: "Failed to start RTMP server" });
        }
      } catch (error) {
        console.error("Error starting RTMP server:", error);
        res.status(500).json({ error: "Failed to start RTMP server" });
      }
    });

    app.post("/api/rtmp/stop", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const success = stopRTMPServer();
        if (success) {
          res.json({ message: "RTMP server stopped successfully" });
        } else {
          res.status(500).json({ error: "Failed to stop RTMP server" });
        }
      } catch (error) {
        console.error("Error stopping RTMP server:", error);
        res.status(500).json({ error: "Failed to stop RTMP server" });
      }
    });

    app.get("/api/rtmp/status", async (req, res) => {
      if (!req.isAuthenticated()) return res.sendStatus(401);
      const running = isRTMPServerRunning();
      console.log("[RTMP] Status check - Server running:", running);
      res.json({ isRunning: running });
    });

    app.get("/api/rtmp/status/:sessionId", async (req, res) => {
      if (!req.isAuthenticated()) return res.sendStatus(401);
      const sessionId = Number(req.params.sessionId);
      const running = isRTMPServerRunning();
      const active = isStreamActive(sessionId);
      res.json({
        isRunning: running,
        isActive: active,
        streamUrl: running ? getRTMPUrl(sessionId) : null,
      });
    });

    // Add the new route for sending invitations
    app.post("/api/users/:id/send-invitation", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }

      try {
        const userId = Number(req.params.id);
        const user = await storage.getUser(userId);

        if (!user) {
          return res.status(404).json({ message: "User not found" });
        }

        // Send invitation email
        await sendInvitationEmail(user);

        // Mark the invitation as sent
        await storage.markTokenAsUsed(user.id.toString());

        res.json({ message: "Invitation sent successfully" });
      } catch (error) {
        console.error("Error sending invitation:", error);
        res.status(500).json({
          message: "Failed to send invitation",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Add the user's submitted polls endpoint
    app.get("/api/users/:userId/poll-responses", async (req, res) => {
      try {
        const userId = Number(req.params.userId);

        // Get all poll responses for this user
        const pollResponses = await storage.getPollResponsesByUser(userId);

        // Group responses by poll
        const pollsSubmitted = pollResponses.reduce((acc, response) => {
          if (!acc[response.pollId]) {
            acc[response.pollId] = {
              pollId: response.pollId,
              responses: []
            };
          }
          acc[response.pollId].responses.push({
            questionId: response.questionId,
            numericResponse: response.numericResponse,
            yesNoResponse: response.yesNoResponse,
            selectedOptions: response.selectedOptions,
            textResponse: response.textResponse,
            createdAt: response.createdAt
          });
          return acc;
        }, {});

        res.json(Object.values(pollsSubmitted));
      } catch (error) {
        console.error("Error fetching user's poll responses:", error);
        res.status(500).json({
          error: "Failed to fetch poll responses",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Register new user
    app.post("/api/register", async (req, res, next) => {
      try {
        console.log("Received registration request with body:", req.body);

        const existingUser = await storage.getUserByUsername(req.body.username);
        console.log("Existing user checkresult:", !!existingUser);

        if (existingUser) {
          console.log("Registration failed: Username already exists");
          return res.status(400).json({ message: "Username already exists" });
        }

        console.log("Validating user data...");
        const validated = insertUserSchema.parse(req.body);
        console.log("Data validation successful");

        console.log("Creating new user in database...");
        const user = await storage.createUser({          ...validated,
                    password: await hashPassword(validated.password),
        });
        console.log("User created successfully:", { id: user.id, username: user.username });

        req.login(user, (err) => {
          if (err) {
            console.error("Login after registration failed:", err);
            return next(err);
          }
          console.log("User logged in successfully after registration");
          res.status(201).json(user);
        });
      } catch (error) {
        console.error("Registration error:", error);
        const message = error instanceof Error ? error.message : "Registration failed";
        res.status(400).json({ message });
      }
    });

    // Add the new route after the existing questions routes
    app.get("/api/questions/user/:userid", async (req, res) => {
      try {
        const authHeader = req.headers.authorization;
        const token = authHeader && authHeader.startsWith('Bearer ') ? authHeader.split(' ')[1] : null;

        if (!token) {
          return res.status(401).json({ message: "No authorization token provided" });
        }

        // Verify JWT token
        let currentUser;
        try {
          currentUser = jwt.verify(token, JWT_SECRET) as SelectUser;
        } catch (error) {
          return res.status(401).json({ message: "Invalid token" });
        }

        const targetUserId = Number(req.params.userid);

        // Check permissions - only allow users to view their own questions unless they're admin
        if (currentUser.role !== "admin" && currentUser.id !== targetUserId) {
          return res.status(403).json({ message: "Forbidden" });
        }

        // Get questions from storage
        const questions = await storage.getUserQuestions(targetUserId);

        res.json(questions);
      } catch (error) {
        console.error("Error fetching user questions:", error);
        res.status(500).json({ 
          message: "Failed to fetch questions",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Add live stream sessions route
    app.get("/api/sessions/live-streams", async (_req, res) => {
      try {
        const liveSessions = await storage.getLiveStreamSessions();
        // Format response according to spec
        res.json({
          sessions: liveSessions.map(session => ({
            id: session.id,
            sessionTitle: session.sessionTitle,
            sessionTitleAr: session.sessionTitleAr,
            liveStreamUrl: session.liveStreamUrl,
            sessionDate: session.sessionDate,
            sessionTime: session.sessionTime
          }))
        });
      } catch (error) {
        console.error("Error fetching live stream sessions:", error);
        res.status(500).json({ 
          message: "Failed to fetch live stream sessions",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Add session transcriptions route
    app.get("/api/sessions/:sessionId/transcriptions", async (req, res) => {
      try {
        const sessionId = Number(req.params.sessionId);
        const rawTranscriptions = await storage.getTranscriptions(sessionId);

        // Format response according to spec
        const transcriptions = rawTranscriptions.map(t => ({
          id: t.id,
          originalText: t.originalText,
          translatedText: t.translatedText,
          clipStartTime: t.clipStartTime,
          clipEndTime: t.clipEndTime,
          sourceLanguage: t.sourceLanguage
        }));

        res.json({ transcriptions });

      } catch (error) {
        console.error("Error fetching session transcriptions:", error);
        res.status(500).json({ 
          message: "Failed to fetch transcriptions",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Add webhook to trigger Pusher when new transcription is created
    app.post("/api/transcriptions", async (req, res) => {
      try {
        const transcriptionData = req.body;
        const newTranscription = await storage.createTranscription(transcriptionData);

        // Format transcription data for Pusher
        const transcriptionForPusher = {
          id: newTranscription.id,
          originalText: newTranscription.originalText,
          translatedText: newTranscription.translatedText,
          clipStartTime: newTranscription.clipStartTime,
          clipEndTime: newTranscription.clipEndTime,
          sourceLanguage: newTranscription.sourceLanguage
        };

        // Trigger Pusher event on the session-specific channel
        const channelName = `session-${newTranscription.sessionId}-transcriptions`;
        await pusher.trigger(channelName, 'new-transcription', {
          transcription: transcriptionForPusher
        });

        res.status(201).json(newTranscription);
      } catch (error) {
        console.error("Error creating transcription:", error);
        res.status(500).json({ 
          message: "Failed to create transcription",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Polls routes
    app.get("/api/polls", async (req, res) => {
      try {
        const eventId = req.query.eventId
          ? Number(req.query.eventId)
          : undefined;
        const sessionId = req.query.sessionId
          ? Number(req.query.sessionId)
          : undefined;
        const polls = await storage.getPolls(eventId, sessionId);
        res.json(polls);
      } catch (error) {
        console.error("Error fetching polls:", error);
        res.status(500).json({ error: "Failed to fetch polls" });
      }
    });

    app.post("/api/polls", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const startDate = new Date(req.body.startDate);
        const endDate = new Date(req.body.endDate);
        if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
          throw new Error("Invalid dates provided");
        }
        const pollData = {
          ...req.body,
          creatorId: req.user.id,
          startDate, // Pass the actual Date object
          endDate, // Pass the actual Date object
        };
        const questions = req.body.questions || [];
        delete pollData.questions;
        console.log("Poll data to insert:", pollData);
        const poll = await storage.createPoll(pollData);
        if (questions.length > 0) {
          for (const question of questions) {
            await storage.createPollQuestion({
              pollId: poll.id,
              pollTypeId: question.pollTypeId,
              question: question.question,
              questionAr: question.questionAr,
              options: question.options,
              optionsAr: question.optionsAr,
              required: question.required,
              order: question.order,
            });
          }
        }
        res.status(201).json(poll);
      } catch (error) {
        console.error("Error creating poll:", error);
        res.status(500).json({ error: "Failed to create poll" });
      }
    });

    app.get("/api/polls/:id", async (req, res) => {
      const pollId = Number(req.params.id);
      console.log(`[GET /api/polls/:id] Fetching poll with ID: ${pollId}`);
      if (isNaN(pollId)) {
        return res.status(400).json({ message: "Invalid poll ID" });
      }
      const poll = await storage.getPoll(pollId);
      if (!poll) {
        console.log(`[GET /api/polls/:id] Poll ${pollId} not found`);
        return res.status(404).json({ message: "Poll not found" });
      }
      console.log(`[GET /api/polls/:id] Successfully retrieved poll:`, poll);
      res.json(poll);
    });

    app.get("/api/polls/:id/questions", async (req, res) => {
      try {
        const pollId = Number(req.params.id);
        console.log(
          `[GET /api/polls/:id/questions] Fetching questions for poll ID: ${pollId}`,
        );
        const poll = await storage.getPoll(pollId);
        if (!poll) {
          console.log(
            `[GET /api/polls/:id/questions] Poll ${pollId} not found`,
          );
          return res.status(404).json({ message: "Poll not found" });
        }
        const questions = await storage.getPollQuestions(pollId);
        console.log(
          `[GET /api/polls/:id/questions] Found ${questions.length} questions for poll ${pollId}`,
        );
        res.json(questions);
      } catch (error) {
        console.error(
          "[GET /api/polls/:id/questions] Error fetching questions:",
          error,
        );
        res.status(500).json({ error: "Failed to fetch questions" });
      }
    });

    app.get("/api/polls/:id/responses", async (req, res) => {
      try {
        const pollId = Number(req.params.id);
        console.log(`Fetching responses for poll ID: ${pollId}`);
        const poll = await storage.getPoll(pollId);
        if (!poll) {
          console.log(`Poll ${pollId} not found when fetching responses`);
          return res.status(404).json({ message: "Poll not found" });
        }
        const responses = await storage.getPollResponses(pollId);
        console.log(`Found ${responses.length} responses for poll ${pollId}`);
        res.json(responses);
      } catch (error) {
        console.error("Error fetching poll responses:", error);
        res.status(500).json({ error: "Failed to fetch poll responses" });
      }
    });

    app.post("/api/polls/:id/responses", async (req, res) => {
      if (!req.isAuthenticated()) return res.sendStatus(401);
      try {
        const pollId = Number(req.params.id);
        if (isNaN(pollId)) {
          return res.status(400).json({ message: "Invalid poll ID" });
        }
        const { responses } = req.body;
        console.log("Received poll submission:", { pollId, responses });
        if (!responses) {
          return res.status(400).json({ error: "No answers provided" });
        }
        const questions = await storage.getPollQuestions(pollId);
        for (const [questionId, answer] of Object.entries(responses)) {
          const question = questions.find((q) => q.id === Number(questionId));
          if (!question) continue;
          const responseData: any = {
            pollId,
            questionId: Number(questionId),
            userId: req.user.id,
            numericResponse: null,
            textResponse: null,
            selectedOptions: null,
            yesNoResponse: null,
          };
          switch (question.pollTypeId) {
            case 1:
              responseData.numericResponse = Number(answer);
              break;
            case 2:
              responseData.yesNoResponse = answer as string;
              break;
            case 3:
              if (Array.isArray(answer)) {
                responseData.selectedOptions = answer;
              }
              break;
            case 4:
              responseData.textResponse = answer as string;
              break;
            case 7:
              if (typeof answer === "object" && "selected" in answer) {
                const { selected, other } = answer as {
                  selected: string[];
                  other: string;
                };
                responseData.selectedOptions = selected;
                if (selected.includes("Other") && other) {
                  responseData.textResponse = other;
                }
              }
              break;
          }
          console.log("Creating poll response:", responseData);
          await storage.createPollResponse(responseData);
        }
        res
          .status(201)
          .json({ message: "Poll responses submitted successfully" });
      } catch (error) {
        console.error("Error submitting poll responses:", error);
        res.status(500).json({ error: "Failed to submit poll responses" });
      }
    });

    // Add PATCH endpoint for polls
    app.patch("/api/polls/:id", async (req, res) => {
      try {
        // Get token from Authorization header
        const authHeader = req.headers.authorization;
        if (!authHeader || !authHeader.startsWith('Bearer ')) {
          return res.status(401).json({ message: "Unauthorized" });
        }

        const token = authHeader.split(" ")[1];
        const decoded = jwt.verify(token, JWT_SECRET) as SelectUser;

        // Check if user is admin or moderator
        if (decoded.role !== "admin" && decoded.role !== "moderator") {
          return res.status(403).json({ message: "Forbidden" });
        }

        const pollId = Number(req.params.id);
        const { resultsPublished, ...updateData } = req.body;

        // Update poll using storage interface
        const updatedPoll = await storage.updatePoll(pollId, {
          ...updateData,
          resultsPublished
        });

        if (!updatedPoll) {
          return res.status(404).json({ message: "Poll not found" });
        }

        res.json(updatedPoll);
      } catch (error) {
        console.error("Error updating poll:", error);
        if (error instanceof jwt.JsonWebTokenError) {
          return res.status(401).json({ message: "Invalid token" });
        }
        res.status(500).json({ error: "Failed to update poll" });
      }
    });

    app.delete("/api/polls/:id", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const pollId = Number(req.params.id);
        await storage.deletePoll(pollId);
        res.sendStatus(200);
      } catch (error) {
        console.error("Error deleting poll:", error);
        res.status(500).json({ error: "Failed to delete poll" });
      }
    });

    // Add questions routes
    app.get("/api/questions", async (req, res) => {
      try {
        const sessionId = req.query.sessionId
          ? Number(req.query.sessionId)
          : null;
        const questions = await storage.getQuestions(sessionId);
        res.json(questions);
      } catch (error) {
        console.error("Error fetching questions:", error);
        res.status(500).json({ error: "Failed to fetch questions" });
      }
    });

    app.post("/api/questions", async (req, res) => {
      if (!req.isAuthenticated()) {
        return res.status(401).json({ message: "Unauthorized" });
      }

      try {
        console.log("Question submission attempt by user:", req.user?.username);

        const questionData = {
          ...req.body,
          userId: req.user!.id,
          questionAr: req.body.questionAr || "",
          sessionId: req.body.sessionId || null,
        };

        const validated = insertQuestionSchema.parse(questionData);
        const question = await storage.createQuestion(validated);

        console.log("Question created successfully:", question);
        res.status(201).json(question);
      } catch (error) {
        console.error("Error creating question:", error);
        if (error instanceof z.ZodError) {
          return res.status(400).json({ error: error.errors[0].message });
        }
        res.status(500).json({ error: "Failed to create question" });
      }
    });
    // Question status update route
    app.post("/api/questions/:id/status", async (req, res) => {
      try {
        // Get token from Authorization header
        const authHeader = req.headers.authorization;
        if (!authHeader || !authHeader.startsWith('Bearer ')) {
          return res.status(401).json({ message: "Unauthorized" });
        }

        const token = authHeader.split(" ")[1];
        const decoded = jwt.verify(token, JWT_SECRET) as SelectUser;

        // Check if user is admin or moderator
        if (decoded.role !== "admin" && decoded.role !== "moderator") {
          return res.status(403).json({ message: "Forbidden" });
        }

        const questionId = Number(req.params.id);
        const { status } = req.body;

        const updatedQuestion = await storage.updateQuestion(questionId, { status });

        // Notify through Pusher if available
        try {
          await pusher.trigger("questions", "status-updated", {
            questionId,
            status,
            timestamp: new Date().toISOString(),
          });
        } catch (error) {
          console.warn("Failed to send pusher notification:", error);
        }

        res.json(updatedQuestion);
      } catch (error) {
        console.error("Error updating question status:", error);
        if (error instanceof jwt.JsonWebTokenError) {
          return res.status(401).json({ message: "Invalid token" });
        }
        res.status(500).json({ error: "Failed to update question status" });
      }
    });

    // Question response update route
    app.post("/api/questions/:id/respond", async (req, res) => {
      try {
        // Get token from Authorization header
        const authHeader = req.headers.authorization;
        if (!authHeader || !authHeader.startsWith('Bearer ')) {
          return res.status(401).json({ message: "Unauthorized" });
        }

        const token = authHeader.split(" ")[1];
        const decoded = jwt.verify(token, JWT_SECRET) as SelectUser;

        // Check if user is admin or moderator
        if (decoded.role !== "admin" && decoded.role !== "moderator") {
          return res.status(403).json({ message: "Forbidden" });
        }

        const questionId = Number(req.params.id);
        const { response } = req.body;

        const updatedQuestion = await storage.updateQuestion(questionId, {
          response,
          responseAr: "", // Add empty Arabic response as required by schema
        });

        // Notify through Pusher if available
        try {
          await pusher.trigger("questions", "response-updated", {
            questionId,
            timestamp: new Date().toISOString(),
          });
        } catch (error) {
          console.warn("Failed to send pusher notification:", error);
        }

        res.json(updatedQuestion);
      } catch (error) {
        console.error("Error updating question response:", error);
        if (error instanceof jwt.JsonWebTokenError) {
          return res.status(401).json({ message: "Invalid token" });
        }
        res.status(500).json({ error: "Failed to update question response" });
      }
    });

    // Test audio processing endpoint
    app.post("/api/test/process-audio", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const filePath = path.join(process.cwd(), "uploads", "1.mp3");
        if (!fs.existsSync(filePath)) {
          return res.status(404).json({ error: "Test audio file not found" });
        }
        await processAudioFile(1, filePath);
        res.json({ message: "Audio processing completed successfully" });
      } catch (error) {
        console.error("Error processing audio:", error);
        res.status(500).json({ error: "Failed to process audio file" });
      }
    });

    app.get("/api/poll-types", async (_req, res) => {
      try {
        const types = await storage.getPollTypes();
        res.json(types);
      } catch (error) {
        console.error("Error fetching poll types:", error);
        res.status(500).json({ error: "Failed to fetch poll types" });
      }
    });

    // RTMP Server Control
    app.post("/api/rtmp/start", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        if (isRTMPServerRunning()) {
          return res.json({ message: "RTMP server is already running" });
        }
        const success = startRTMPServer();
        if (success) {
          res.json({ message: "RTMP server started successfully" });
        } else {
          res.status(500).json({ error: "Failed to start RTMP server" });
        }
      } catch (error) {
        console.error("Error starting RTMP server:", error);
        res.status(500).json({ error: "Failed to start RTMP server" });
      }
    });

    app.post("/api/rtmp/stop", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }
      try {
        const success = stopRTMPServer();
        if (success) {
          res.json({ message: "RTMP server stopped successfully" });
        } else {
          res.status(500).json({ error: "Failed to stop RTMP server" });
        }
      } catch (error) {
        console.error("Error stopping RTMP server:", error);
        res.status(500).json({ error: "Failed to stop RTMP server" });
      }
    });

    app.get("/api/rtmp/status", async (req, res) => {
      if (!req.isAuthenticated()) return res.sendStatus(401);
      const running = isRTMPServerRunning();
      console.log("[RTMP] Status check - Server running:", running);
      res.json({ isRunning: running });
    });

    app.get("/api/rtmp/status/:sessionId", async (req, res) => {
      if (!req.isAuthenticated()) return res.sendStatus(401);
      const sessionId = Number(req.params.sessionId);
      const running = isRTMPServerRunning();
      const active = isStreamActive(sessionId);
      res.json({
        isRunning: running,
        isActive: active,
        streamUrl: running ? getRTMPUrl(sessionId) : null,
      });
    });

    // Add the new route for sending invitations
    app.post("/api/users/:id/send-invitation", async (req, res) => {
      if (!req.isAuthenticated() || req.user?.role !== "admin") {
        return res.status(403).json({ message: "Forbidden" });
      }

      try {
        const userId = Number(req.params.id);
        const user = await storage.getUser(userId);

        if (!user) {
          return res.status(404).json({ message: "User not found" });
        }

        // Send invitation email
        await sendInvitationEmail(user);

        // Mark the invitation as sent
        await storage.markTokenAsUsed(user.id.toString());

        res.json({ message: "Invitation sent successfully" });
      } catch (error) {
        console.error("Error sending invitation:", error);
        res.status(500).json({
          message: "Failed to send invitation",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Add the user's submitted polls endpoint
    app.get("/api/users/:userId/poll-responses", async (req, res) => {
      try {
        const userId = Number(req.params.userId);

        // Get all poll responses for this user
        const pollResponses = await storage.getPollResponsesByUser(userId);

        // Group responses by poll
        const pollsSubmitted = pollResponses.reduce((acc, response) => {
          if (!acc[response.pollId]) {
            acc[response.pollId] = {
              pollId: response.pollId,
              responses: []
            };
          }
          acc[response.pollId].responses.push({
            questionId: response.questionId,
            numericResponse: response.numericResponse,
            yesNoResponse: response.yesNoResponse,
            selectedOptions: response.selectedOptions,
            textResponse: response.textResponse,
            createdAt: response.createdAt
          });
          return acc;
        }, {});

        res.json(Object.values(pollsSubmitted));
      } catch (error) {
        console.error("Error fetching user's poll responses:", error);
        res.status(500).json({
          error: "Failed to fetch poll responses",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Register new user
    app.post("/api/register", async (req, res, next) => {
      try {
        console.log("Received registration request with body:", req.body);

        const existingUser = await storage.getUserByUsername(req.body.username);
        console.log("Existing user checkresult:", !!existingUser);

        if (existingUser) {
          console.log("Registration failed: Username already exists");
          return res.status(400).json({ message: "Username already exists" });
        }

        console.log("Validating user data...");
        const validated = insertUserSchema.parse(req.body);
        console.log("Data validation successful");

        console.log("Creating new user in database...");
        const user = await storage.createUser({          ...validated,
          password: await hashPassword(validated.password),
        });
        console.log("User created successfully:", { id: user.id, username: user.username });

        req.login(user, (err) => {
          if (err) {
            console.error("Login after registration failed:", err);
            return next(err);
          }
          console.log("User logged in successfully after registration");
          res.status(201).json(user);
        });
      } catch (error) {
        console.error("Registration error:", error);
        const message = error instanceof Error ? error.message : "Registration failed";
        res.status(400).json({ message });
      }
    });

    // Add the new route after the existing questions routes
    app.get("/api/questions/user/:userid", async (req, res) => {
      try {
        const authHeader = req.headers.authorization;
        const token = authHeader && authHeader.startsWith('Bearer ') ? authHeader.split(' ')[1] : null;

        if (!token) {
          return res.status(401).json({ message: "No authorization token provided" });
        }

        // Verify JWT token
        let currentUser;
        try {
          currentUser = jwt.verify(token, JWT_SECRET) as SelectUser;
        } catch (error) {
          return res.status(401).json({ message: "Invalid token" });
        }

        const targetUserId = Number(req.params.userid);

        // Check permissions - only allow users to view their own questions unless they're admin
        if (currentUser.role !== "admin" && currentUser.id !== targetUserId) {
          return res.status(403).json({ message: "Forbidden" });
        }

        // Get questions from storage
        const questions = await storage.getUserQuestions(targetUserId);

        res.json(questions);
      } catch (error) {
        console.error("Error fetching user questions:", error);
        res.status(500).json({ 
          message: "Failed to fetch questions",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Add live stream sessions route
    app.get("/api/sessions/live-streams", async (_req, res) => {
      try {
        const liveSessions = await storage.getLiveStreamSessions();
        // Format response according to spec
        res.json({
          sessions: liveSessions.map(session => ({
            id: session.id,
            sessionTitle: session.sessionTitle,
            sessionTitleAr: session.sessionTitleAr,
            liveStreamUrl: session.liveStreamUrl,
            sessionDate: session.sessionDate,
            sessionTime: session.sessionTime
          }))
        });
      } catch (error) {
        console.error("Error fetching live stream sessions:", error);
        res.status(500).json({ 
          message: "Failed to fetch live stream sessions",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Add session transcriptions route
    app.get("/api/sessions/:sessionId/transcriptions", async (req, res) => {
      try {
        const sessionId = Number(req.params.sessionId);
        const rawTranscriptions = await storage.getTranscriptions(sessionId);

        // Format response according to spec
        const transcriptions = rawTranscriptions.map(t => ({
          id: t.id,
          originalText: t.originalText,
          translatedText: t.translatedText,
          clipStartTime: t.clipStartTime,
          clipEndTime: t.clipEndTime,
          sourceLanguage: t.sourceLanguage
        }));

        res.json({ transcriptions });

      } catch (error) {
        console.error("Error fetching session transcriptions:", error);
        res.status(500).json({ 
          message: "Failed to fetch transcriptions",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    // Add webhook to trigger Pusher when new transcription is created
    app.post("/api/transcriptions", async (req, res) => {
      try {
        const transcriptionData = req.body;
        const newTranscription = await storage.createTranscription(transcriptionData);

        // Format transcription data for Pusher
        const transcriptionForPusher = {
          id: newTranscription.id,
          originalText: newTranscription.originalText,
          translatedText: newTranscription.translatedText,
          clipStartTime: newTranscription.clipStartTime,
          clipEndTime: newTranscription.clipEndTime,
          sourceLanguage: newTranscription.sourceLanguage
        };

        // Trigger Pusher event on the session-specific channel
        const channelName = `session-${newTranscription.sessionId}-transcriptions`;
        await pusher.trigger(channelName, 'new-transcription', {
          transcription: transcriptionForPusher
        });

        res.status(201).json(newTranscription);
      } catch (error) {
        console.error("Error creating transcription:", error);
        res.status(500).json({ 
          message: "Failed to create transcription",
          details: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });

    const httpServer = createServer(app);

    // Initialize optional services completely asynchronously
    // This ensures server startup is not blocked
    setImmediate(() => {
      initializeOptionalServices().catch((error) => {
        console.error("Error in optional services initialization:", error);
      });
    });

    return httpServer;
  } catch (error) {
    console.error("❌ Error in routes registration:", error);
    throw error;
  }
}

async function markTokenAsUsed(token: string) {
  try {
    await storage.markTokenAsUsed(token);
  } catch (error) {
    console.error("Error marking token as used:", error);    // Consider adding retry logic or alternative handling here.  For simplicity, logging only for now.
  }
}