import type { Express } from "express";
import { createServer, type Server } from "http";
import { storage } from './storage.js';
// import { registerTemplateRoutes } from './template-routes.js'; // Commented out to fix compilation
// import contentRoutes from './content-routes.js'; // Commented out to fix compilation

export async function registerRoutes(app: Express): Promise<Server> {
  // Health check endpoint for Cloud Run (must be registered early)
  app.get("/health", async (req: any, res: any) => {
    res.json({ 
      status: "healthy", 
      timestamp: new Date().toISOString(),
      version: "0.8"
    });
  });

  // API routes
  app.get("/api/health", async (req: any, res: any) => {
    res.json({ status: "ok", timestamp: new Date().toISOString() });
  });

  // Basic API endpoints for testing
  app.get("/api/users", async (req: any, res: any) => {
    const users = await storage.getAllUsers();
    res.json({ users });
  });

  app.get("/api/items", async (req: any, res: any) => {
    const items = await storage.getAllAvailableItems(false);
    res.json({ items });
  });

  // Hour offerings API routes
  app.get("/api/hour-offerings", async (req: any, res: any) => {
    try {
      const offerings = await storage.getAvailableHourOfferings();
      res.json({ offerings });
    } catch (error) {
      console.error('Error fetching hour offerings:', error);
      res.status(500).json({ error: 'Failed to fetch hour offerings' });
    }
  });

  app.get("/api/hour-offerings/user/:userId", async (req: any, res: any) => {
    try {
      const userId = parseInt(req.params.userId);
      const offerings = await storage.getUserHourOfferings(userId);
      res.json({ offerings });
    } catch (error) {
      console.error('Error fetching user hour offerings:', error);
      res.status(500).json({ error: 'Failed to fetch user hour offerings' });
    }
  });

  app.post("/api/hour-offerings", async (req: any, res: any) => {
    try {
      console.log('Hour offering creation request received:', req.body);
      console.log('Session data:', req.session);
      
      const { title, description, date, startTime, endTime, isRecurring, recurringType, recurringCount } = req.body;
      
      // Get userId from session
      const userId = req.session?.userId;
      console.log('User ID from session:', userId);
      
      if (!userId) {
        return res.status(401).json({ error: 'User not authenticated' });
      }
      
      // Validate required fields
      if (!title || !date || !startTime || !endTime) {
        console.log('Missing required fields:', { title, date, startTime, endTime });
        return res.status(400).json({ error: 'Missing required fields' });
      }
      
      // Combine date and time into proper timestamps
      // Parse dates in local timezone, not UTC
      const offerDate = new Date(`${date}T${startTime}:00`);
      const endTimeStamp = new Date(`${date}T${endTime}:00`);
      
      console.log('Parsed dates:', { offerDate, endTimeStamp });
      
      // Validate that the Date objects are valid
      if (isNaN(offerDate.getTime()) || isNaN(endTimeStamp.getTime())) {
        return res.status(400).json({ error: 'Invalid date or time format' });
      }
      
      // Validate that end time is after start time
      if (endTimeStamp <= offerDate) {
        return res.status(400).json({ error: 'End time must be after start time' });
      }
      
      // Handle recurring offerings
      const offerings = [];
      if (isRecurring && recurringCount && recurringCount >= 2 && recurringCount <= 20) {
        // Create recurring series
        const currentDate = new Date(offerDate);
        const currentEndTime = new Date(endTimeStamp);
        
        for (let i = 0; i < recurringCount; i++) {
          const thisOfferDate = new Date(currentDate);
          const thisEndTime = new Date(currentEndTime);
          
          // Add weeks for each occurrence
          thisOfferDate.setDate(thisOfferDate.getDate() + (i * 7));
          thisEndTime.setDate(thisEndTime.getDate() + (i * 7));
          
          const offeringData = {
            userId,
            title: title.trim(),
            description: description?.trim() || null,
            offerDate: thisOfferDate,
            endTime: thisEndTime,
            isRecurring: true,
            recurringType: 'weekly',
            recurringCount: i === 0 ? recurringCount : null,
            parentOfferingId: null // Will be updated after first creation
          };
          
          const newOffering = await storage.createHourOffering(offeringData);
          offerings.push(newOffering);
          
          // Set parent ID for all offerings in series (including first one)
          if (i === 0) {
            await storage.updateHourOffering(newOffering.id, { parentOfferingId: newOffering.id });
            offerings[0].parentOfferingId = newOffering.id;
          } else {
            await storage.updateHourOffering(newOffering.id, { parentOfferingId: offerings[0].id });
            offerings[i].parentOfferingId = offerings[0].id;
          }
        }
      } else {
        // Create single offering
        const offeringData = {
          userId,
          title: title.trim(),
          description: description?.trim() || null,
          offerDate: offerDate,
          endTime: endTimeStamp,
          isRecurring: false
        };
        
        const newOffering = await storage.createHourOffering(offeringData);
        offerings.push(newOffering);
      }
      
      console.log(`Created ${offerings.length} hour offering(s):`, offerings);
      res.json({ offerings, count: offerings.length, isRecurring: !!isRecurring });
    } catch (error) {
      console.error('Error creating hour offering:', error);
      res.status(500).json({ error: 'Failed to create hour offering', details: error.message });
    }
  });

  app.get("/api/hour-offerings/:id", async (req: any, res: any) => {
    try {
      const id = parseInt(req.params.id);
      const offering = await storage.getHourOfferingById(id);
      if (offering) {
        res.json({ offering });
      } else {
        res.status(404).json({ error: 'Hour offering not found' });
      }
    } catch (error) {
      console.error('Error fetching hour offering:', error);
      res.status(500).json({ error: 'Failed to fetch hour offering' });
    }
  });

  app.put("/api/hour-offerings/:id", async (req: any, res: any) => {
    try {
      const id = parseInt(req.params.id);
      const { title, description, date, startTime, endTime, isRecurring, recurringCount } = req.body;
      
      console.log('Received update data:', { date, startTime, endTime });
      
      // Create dates in UTC but treat input as local time
      // Parse as local time by creating Date object with timezone offset
      const tempStartDate = new Date(`${date}T${startTime}:00`);
      const tempEndDate = new Date(`${date}T${endTime}:00`);
      
      // Get timezone offset to convert local time to UTC properly
      const timezoneOffset = tempStartDate.getTimezoneOffset() * 60000; // offset in milliseconds
      
      // Adjust for timezone to store correct UTC time that represents local time
      const offerDate = new Date(tempStartDate.getTime() - timezoneOffset);
      const endTimeStamp = new Date(tempEndDate.getTime() - timezoneOffset);
      
      console.log('Converted times - Start:', offerDate.toISOString(), 'End:', endTimeStamp.toISOString());
      
      // Validate dates
      if (isNaN(offerDate.getTime()) || isNaN(endTimeStamp.getTime())) {
        return res.status(400).json({ error: 'Invalid date or time format' });
      }
      
      if (endTimeStamp <= offerDate) {
        return res.status(400).json({ error: 'End time must be after start time' });
      }
      
      const updateData = {
        title: title?.trim(),
        description: description?.trim() || null,
        offerDate,
        endTime: endTimeStamp,
        isRecurring: !!isRecurring,
        recurringType: isRecurring ? 'weekly' : null,
        recurringCount: (isRecurring && recurringCount) ? recurringCount : null
      };
      
      const offering = await storage.updateHourOffering(id, updateData);
      console.log('Updated hour offering:', offering);
      res.json({ offering, success: true });
    } catch (error) {
      console.error('Error updating hour offering:', error);
      res.status(500).json({ error: 'Failed to update hour offering' });
    }
  });

  app.delete("/api/hour-offerings/:id", async (req: any, res: any) => {
    try {
      const id = parseInt(req.params.id);
      await storage.deleteHourOffering(id);
      res.json({ success: true });
    } catch (error) {
      console.error('Error deleting hour offering:', error);
      res.status(500).json({ error: 'Failed to delete hour offering' });
    }
  });

  app.post("/api/hour-offerings/:id/book", async (req: any, res: any) => {
    try {
      const id = parseInt(req.params.id);
      const success = await storage.bookHourOffering(id);
      res.json({ success });
    } catch (error) {
      console.error('Error booking hour offering:', error);
      res.status(500).json({ error: 'Failed to book hour offering' });
    }
  });

  app.get("/api/hour-offerings/calendar/:startDate/:endDate", async (req: any, res: any) => {
    try {
      const { startDate, endDate } = req.params;
      const offerings = await storage.getHourOfferingsByDateRange(startDate, endDate);
      res.json({ success: true, offerings });
    } catch (error) {
      console.error('Error fetching hour offerings for calendar:', error);
      res.status(500).json({ error: 'Failed to fetch calendar data' });
    }
  });

  // Contact helper API endpoint
  app.post("/api/hour-offerings/contact", async (req: any, res: any) => {
    try {
      const { offeringId, message } = req.body;
      
      // Get userId from session
      const userId = req.session?.userId;
      
      if (!userId) {
        return res.status(401).json({ error: 'User not authenticated' });
      }
      
      // Validate required fields
      if (!offeringId || !message) {
        return res.status(400).json({ error: 'Missing required fields' });
      }
      
      // Get the hour offering to find the helper
      const offering = await storage.getHourOfferingById(parseInt(offeringId));
      
      if (!offering) {
        return res.status(404).json({ error: 'Hour offering not found' });
      }
      
      // Start a conversation between the requester and the helper
      const conversation = await storage.startConversation({
        itemId: null, // No item for hour offerings
        ownerId: offering.userId, // Helper is the "owner"
        borrowerId: userId // Requester is the "borrower"
      });
      
      // Send the initial message
      await storage.sendMessage({
        conversationId: conversation.id,
        senderId: userId,
        message: message,
        messageType: 'text'
      });
      
      res.json({ success: true, message: 'Contact request sent successfully' });
    } catch (error) {
      console.error('Error sending contact request:', error);
      res.status(500).json({ error: 'Failed to send contact request' });
    }
  });

  // Email notification system API endpoints (Admin only)
  app.get('/api/email/settings', async (req: any, res: any) => {
    try {
      const userId = req.session?.userId;
      if (!userId) {
        return res.status(401).json({ error: 'Authentication required' });
      }

      const user = await storage.getUser(userId);
      if (!user || !user.roles?.includes('ROLE_ADMIN')) {
        return res.status(403).json({ error: 'Admin access required' });
      }

      const settings = await storage.getEmailNotificationSettings();
      res.json(settings);
    } catch (error) {
      console.error('Error fetching email settings:', error);
      res.status(500).json({ error: 'Failed to fetch email settings' });
    }
  });

  app.get('/api/email/status', async (req: any, res: any) => {
    try {
      const userId = req.session?.userId;
      if (!userId) {
        return res.status(401).json({ error: 'Authentication required' });
      }

      const user = await storage.getUser(userId);
      if (!user || !user.roles?.includes('ROLE_ADMIN')) {
        return res.status(403).json({ error: 'Admin access required' });
      }

      const settings = await storage.getEmailNotificationSettings();
      const today = new Date().toLocaleDateString('en-CA');
      const stats = await storage.getEmailDigestStats(today);
      
      res.json({
        schedulerRunning: true,
        settings: settings,
        todayStats: stats,
        hasApiKey: !!process.env.SENDGRID_API_KEY,
        temporaryEmail: 'manager@tatacommons.com'
      });
    } catch (error) {
      console.error('Error fetching email status:', error);
      res.status(500).json({ error: 'Failed to fetch email status' });
    }
  });

  app.post('/api/email/test', async (req: any, res: any) => {
    try {
      const userId = req.session?.userId;
      if (!userId) {
        return res.status(401).json({ error: 'Authentication required' });
      }

      const user = await storage.getUser(userId);
      if (!user || !user.roles?.includes('ROLE_ADMIN')) {
        return res.status(403).json({ error: 'Admin access required' });
      }

      const { EmailNotificationService } = await import('./email-service.js');
      const emailService = new EmailNotificationService(storage);
      const success = await emailService.testConnection();
      
      res.json({ 
        success, 
        message: success ? 'Email test successful - check manager@tatacommons.com' : 'Email test failed - check logs' 
      });
    } catch (error) {
      console.error('Error testing email connection:', error);
      res.status(500).json({ error: 'Failed to test email connection' });
    }
  });

  app.get('/api/email/logs', async (req: any, res: any) => {
    try {
      const userId = req.session?.userId;
      if (!userId) {
        return res.status(401).json({ error: 'Authentication required' });
      }

      const user = await storage.getUser(userId);
      if (!user || !user.roles?.includes('ROLE_ADMIN')) {
        return res.status(403).json({ error: 'Admin access required' });
      }

      const limit = parseInt(req.query.limit as string) || 20;
      const logs = await storage.getEmailLogs(limit);
      
      res.json(logs);
    } catch (error) {
      console.error('Error fetching email logs:', error);
      res.status(500).json({ error: 'Failed to fetch email logs' });
    }
  });

  // Note: Root route and other pages will be handled by template-routes.ts

  // Import and register the full template routes
  const { registerTemplateRoutes } = await import('./template-routes.js');
  registerTemplateRoutes(app, storage);

  // Import and register content routes
  try {
    const contentRoutes = await import('./content-routes.js');
    app.use(contentRoutes.default);
    console.log('Content routes registered successfully');
  } catch (error) {
    console.error('Error loading content routes:', error);
  }

  const httpServer = createServer(app);
  return httpServer;
}
