import type { Express } from "express";
import { createServer, type Server } from "http";
import { storage } from "./storage";
import { insertUserSchema, insertPropertySchema, insertMessageSchema, insertBookingSchema, type User, type Booking } from "@shared/schema";
import { NotificationManager } from "./notifications";

const notificationManager = new NotificationManager();

export async function registerRoutes(app: Express): Promise<Server> {
  // Auth routes
  app.post("/api/register", async (req, res) => {
    try {
      const userData = insertUserSchema.parse(req.body);
      
      // Check if user already exists
      const existingUser = await storage.getUserByEmail(userData.email);
      if (existingUser) {
        return res.status(400).json({ error: "User already exists" });
      }
      
      const user = await storage.createUser(userData);
      
      // Send welcome email notification
      try {
        await notificationManager.sendWelcomeNotifications(user);
      } catch (error) {
        console.error('Failed to send welcome notification:', error);
        // Don't fail registration if email fails
      }
      
      const { password, ...userWithoutPassword } = user;
      res.status(201).json(userWithoutPassword);
    } catch (error) {
      res.status(400).json({ error: "Invalid user data" });
    }
  });

  app.post("/api/login", async (req, res) => {
    try {
      const { email, password } = req.body;
      
      // First check if this is an admin trying to login via regular form
      let adminUser = await storage.getAdminUserByEmail(email);
      if (!adminUser) {
        adminUser = await storage.getAdminUserByUsername(email);
      }
      
      if (adminUser && adminUser.password === password && adminUser.isActive) {
        // Admin login successful - redirect to admin dashboard
        const token = Buffer.from(`${adminUser.id}:${Date.now()}`).toString('base64');
        adminUser.lastLogin = new Date();
        await storage.updateAdminUser(adminUser.id, { lastLogin: adminUser.lastLogin });
        
        return res.json({ 
          token, 
          admin: adminUser,
          redirectTo: '/admin/dashboard',
          isAdmin: true
        });
      }
      
      // Regular user login
      const user = await storage.getUserByEmail(email);
      
      if (!user || user.password !== password) {
        return res.status(401).json({ error: "Invalid credentials" });
      }
      
      // Check if user is active
      if (user.isActive === false) {
        return res.status(403).json({ error: "Account is inactive. Please contact support." });
      }
      
      const { password: _, ...userWithoutPassword } = user;
      res.json(userWithoutPassword);
    } catch (error) {
      res.status(400).json({ error: "Login failed" });
    }
  });

  // Property routes
  app.get("/api/properties", async (req, res) => {
    try {
      const filters = {
        type: req.query.type as string,
        propertyType: req.query.propertyType as string,
        location: req.query.location as string,
        minPrice: req.query.minPrice ? parseFloat(req.query.minPrice as string) : undefined,
        maxPrice: req.query.maxPrice ? parseFloat(req.query.maxPrice as string) : undefined,
        limit: req.query.limit ? parseInt(req.query.limit as string) : undefined,
        offset: req.query.offset ? parseInt(req.query.offset as string) : undefined
      };

      const properties = await storage.getActiveUserProperties();
      res.json(properties);
    } catch (error) {
      res.status(500).json({ error: "Failed to fetch properties" });
    }
  });

  // Get properties for map (lightweight endpoint) - MUST come before :id route
  // Optimized map data endpoint for Somali internet speeds
  app.get("/api/properties/map", async (req, res) => {
    try {
      const mapProperties = await storage.getActiveUserPropertiesForMap();
      
      // Add cache headers for performance optimization (Somali internet speeds)
      res.set({
        'Cache-Control': 'public, max-age=30', // Cache for 30 seconds
        'Content-Type': 'application/json',
        'X-Content-Type-Options': 'nosniff'
      });
      
      res.json(mapProperties);
    } catch (error) {
      console.error("Error fetching map properties:", error);
      res.status(500).json({ error: "Failed to fetch map properties" });
    }
  });

  app.get("/api/properties/:id", async (req, res) => {
    try {
      const property = await storage.getProperty(req.params.id);
      if (!property) {
        return res.status(404).json({ error: "Property not found" });
      }
      res.json(property);
    } catch (error) {
      res.status(500).json({ error: "Failed to fetch property" });
    }
  });

  app.put("/api/properties/:id", async (req, res) => {
    try {
      const updates = req.body;
      
      // Remove timestamp fields from updates as they should be handled by the database
      const { createdAt, updatedAt, ...cleanUpdates } = updates;
      
      const updatedProperty = await storage.updateProperty(req.params.id, cleanUpdates);
      if (!updatedProperty) {
        return res.status(404).json({ error: "Property not found" });
      }
      res.json(updatedProperty);
    } catch (error) {
      console.error('Error updating property:', error);
      res.status(500).json({ error: "Failed to update property" });
    }
  });

  app.delete("/api/properties/:id", async (req, res) => {
    try {
      const deleted = await storage.deleteProperty(req.params.id);
      if (!deleted) {
        return res.status(404).json({ error: "Property not found" });
      }
      res.json({ success: true });
    } catch (error) {
      console.error('Error deleting property:', error);
      res.status(500).json({ error: "Failed to delete property" });
    }
  });

  app.post("/api/properties", async (req, res) => {
    try {
      const propertyData = insertPropertySchema.parse(req.body);
      
      // Check if the owner (user) is active
      const owner = await storage.getUser(propertyData.ownerId);
      if (!owner || owner.isActive === false) {
        return res.status(403).json({ error: "Account is inactive. Cannot create properties." });
      }
      
      const property = await storage.createProperty(propertyData);
      res.status(201).json(property);
    } catch (error) {
      res.status(400).json({ error: "Invalid property data" });
    }
  });

  // Message routes
  app.get("/api/messages", async (req, res) => {
    try {
      const userId = req.query.userId as string;
      if (!userId) {
        return res.status(400).json({ error: "User ID required" });
      }
      
      const messages = await storage.getMessages();
      res.json(messages);
    } catch (error) {
      res.status(500).json({ error: "Failed to fetch messages" });
    }
  });

  app.post("/api/messages", async (req, res) => {
    try {
      const messageData = insertMessageSchema.parse(req.body);
      const message = await storage.createMessage(messageData);
      res.status(201).json(message);
    } catch (error) {
      res.status(400).json({ error: "Invalid message data" });
    }
  });

  // Moving service routes
  app.get("/api/moving-services", async (req, res) => {
    try {
      const limit = req.query.limit ? parseInt(req.query.limit as string) : undefined;
      const services = await storage.getActiveMovingServices();
      const limitedServices = limit ? services.slice(0, limit) : services;
      res.json(limitedServices);
    } catch (error) {
      res.status(500).json({ error: "Failed to fetch moving services" });
    }
  });

  app.get("/api/moving-services/:id", async (req, res) => {
    try {
      const services = await storage.getMovingServices();
      const service = services.find(s => s.id === req.params.id);
      if (!service) {
        return res.status(404).json({ error: "Moving service not found" });
      }
      res.json(service);
    } catch (error) {
      res.status(500).json({ error: "Failed to fetch moving service" });
    }
  });

  // Booking routes
  app.get("/api/bookings", async (req, res) => {
    try {
      const userId = req.query.userId as string;
      const bookings = await storage.getBookings();
      
      // Filter bookings by userId if provided
      if (userId) {
        const userBookings = bookings.filter(booking => booking.userId === userId);
        res.json(userBookings);
      } else {
        res.json(bookings);
      }
    } catch (error) {
      res.status(500).json({ error: "Failed to fetch bookings" });
    }
  });

  app.post("/api/bookings", async (req, res) => {
    try {
      const bookingData = insertBookingSchema.parse(req.body);
      
      // Check if the user is active
      const user = await storage.getUser(bookingData.userId);
      if (!user || user.isActive === false) {
        return res.status(403).json({ error: "Account is inactive. Cannot create bookings." });
      }
      
      const booking = await storage.createBooking(bookingData);
      
      // Send booking confirmation notifications
      try {
        if (user) {
          await notificationManager.sendBookingConfirmation(booking, user.email, user.phone || undefined);
        }
        
        // Send admin alert
        await notificationManager.sendAdminAlert(
          'New Booking Created',
          `A new moving service booking has been created. Contact: ${booking.phone}`
        );
      } catch (error) {
        console.error('Failed to send booking notifications:', error);
        // Don't fail booking creation if notifications fail
      }
      
      res.status(201).json(booking);
    } catch (error) {
      res.status(400).json({ error: "Invalid booking data" });
    }
  });

  app.put("/api/bookings/:id", async (req, res) => {
    try {
      const updates = req.body;
      const booking = await storage.updateBooking(req.params.id, updates);
      if (!booking) {
        return res.status(404).json({ error: "Booking not found" });
      }
      res.json(booking);
    } catch (error) {
      res.status(500).json({ error: "Failed to update booking" });
    }
  });

  app.delete("/api/admin/bookings/:id", async (req, res) => {
    try {
      const success = await storage.deleteBooking(req.params.id);
      if (!success) {
        return res.status(404).json({ error: "Booking not found" });
      }
      res.json({ success: true });
    } catch (error) {
      res.status(500).json({ error: "Failed to delete booking" });
    }
  });

  // Admin booking messaging
  app.post("/api/admin/bookings/:id/message", async (req, res) => {
    try {
      const { subject, message, sendMethod, customerPhone, customerEmail } = req.body;
      const bookingId = req.params.id;
      
      // Get booking details for context
      const booking = await storage.getBooking(bookingId);
      if (!booking) {
        return res.status(404).json({ error: "Booking not found" });
      }

      // Send notifications based on selected method
      try {
        if (sendMethod === 'email' || sendMethod === 'both') {
          // Use existing notification service for booking confirmations
          const fakeUser = { email: customerEmail || 'customer@example.com', name: 'Customer' } as any;
          await notificationManager.sendBookingConfirmation(booking, fakeUser.email, customerPhone);
          
          // Send admin message as a follow-up email
          await notificationManager.sendAdminAlert(
            `Message sent to customer: ${subject}`,
            `Admin message sent to ${fakeUser.email}: ${message}`
          );
        }

        if (sendMethod === 'sms' || sendMethod === 'both') {
          // SMS mock notification (would integrate with Twilio in production)
          console.log(`SMS sent to ${customerPhone || booking.phone}: KiroServices: ${message.substring(0, 120)}...`);
          
          await notificationManager.sendAdminAlert(
            'SMS Message Sent',
            `SMS sent to ${customerPhone || booking.phone}: ${message.substring(0, 100)}...`
          );
        }

        res.json({ success: true, message: "Message sent successfully" });
      } catch (error) {
        console.error('Failed to send booking message:', error);
        res.status(500).json({ error: "Failed to send message. Please try again." });
      }
    } catch (error) {
      res.status(400).json({ error: "Invalid message data" });
    }
  });

  // User message to service provider
  app.post("/api/bookings/:id/user-message", async (req, res) => {
    try {
      const { id } = req.params;
      const { message, userId } = req.body;
      
      // Get the booking to verify ownership
      const bookings = await storage.getBookings();
      const booking = bookings.find(b => b.id === id);
      
      if (!booking) {
        return res.status(404).json({ error: "Booking not found" });
      }
      
      if (booking.userId !== userId) {
        return res.status(403).json({ error: "Not authorized" });
      }
      
      // Send notification to admin about user message
      await notificationManager.sendAdminAlert(
        'New Customer Message',
        `
        <h2>New Message from Customer</h2>
        <p><strong>Booking ID:</strong> ${booking.id}</p>
        <p><strong>Customer Phone:</strong> ${booking.phone}</p>
        <p><strong>Pickup:</strong> ${booking.pickupLocation}</p>
        <p><strong>Dropoff:</strong> ${booking.dropoffLocation}</p>
        <p><strong>Date:</strong> ${booking.date}</p>
        <p><strong>Status:</strong> ${booking.status}</p>
        <p><strong>Customer Message:</strong></p>
        <div style="background: #f5f5f5; padding: 15px; border-radius: 5px; margin: 10px 0;">
          ${message}
        </div>
        <p>Please respond to the customer via admin dashboard or call them directly.</p>
        `
      );
      
      res.json({ success: true });
    } catch (error) {
      console.error('Error sending user message:', error);
      res.status(500).json({ error: "Failed to send message" });
    }
  });

  // Admin authentication routes
  app.post("/api/admin/login", async (req, res) => {
    try {
      const { email, password } = req.body;
      
      // Try to find admin by email first, then by username if email fails
      let adminUser = await storage.getAdminUserByEmail(email);
      if (!adminUser) {
        adminUser = await storage.getAdminUserByUsername(email); // Allow username in email field
      }
      
      if (!adminUser || adminUser.password !== password || !adminUser.isActive) {
        return res.status(401).json({ error: "Invalid credentials" });
      }
      
      // Update last login
      await storage.updateAdminUser(adminUser.id, { lastLogin: new Date() });
      
      // Generate simple token (in production, use JWT)
      const token = Buffer.from(`${adminUser.id}:${Date.now()}`).toString('base64');
      
      const { password: _, ...adminWithoutPassword } = adminUser;
      res.json({ token, admin: adminWithoutPassword });
    } catch (error) {
      res.status(400).json({ error: "Login failed" });
    }
  });

  // Admin dashboard stats
  app.get("/api/admin/stats", async (req, res) => {
    try {
      const stats = await storage.getDashboardStats();
      res.json(stats);
    } catch (error) {
      res.status(500).json({ error: "Failed to fetch admin stats" });
    }
  });

  // Admin user management
  app.get("/api/admin/users", async (req, res) => {
    try {
      // Get actual registered users
      const actualUsers = await storage.getAllUsers();
      
      // Return actual registered users with property counts
      const allProperties = await storage.getProperties();
      const usersWithStats = actualUsers.map(user => {
        const { password, ...userWithoutPassword } = user;
        const userProperties = allProperties.filter(p => p.ownerId === user.id);
        return {
          ...userWithoutPassword,
          properties: userProperties.length
        };
      });
      
      res.json(usersWithStats);
    } catch (error) {
      res.status(500).json({ error: "Failed to fetch users" });
    }
  });

  app.delete("/api/admin/users/:id", async (req, res) => {
    try {
      const { id } = req.params;
      const deleted = await storage.deleteUser(id);
      if (deleted) {
        res.json({ success: true, message: "User deleted successfully" });
      } else {
        res.status(404).json({ error: "User not found" });
      }
    } catch (error) {
      res.status(500).json({ error: "Failed to delete user" });
    }
  });

  app.put("/api/admin/users/:id", async (req, res) => {
    try {
      const { id } = req.params;
      const { name, email, role, isActive } = req.body;
      
      const updates: any = {};
      if (name !== undefined) updates.name = name;
      if (email !== undefined) updates.email = email;
      if (role !== undefined) updates.role = role;
      
      const updatedUser = await storage.updateUser(id, updates);
      
      if (isActive !== undefined) {
        await storage.updateUserStatus(id, isActive);
      }
      
      if (updatedUser) {
        res.json({ success: true, user: updatedUser });
      } else {
        res.status(404).json({ error: "User not found" });
      }
    } catch (error) {
      res.status(500).json({ error: "Failed to update user" });
    }
  });

  // Admin property management
  app.get("/api/admin/properties", async (req, res) => {
    try {
      const properties = await storage.getProperties();
      res.json(properties);
    } catch (error) {
      res.status(500).json({ error: "Failed to fetch properties" });
    }
  });

  app.put("/api/admin/properties/:id", async (req, res) => {
    try {
      const updates = req.body;
      
      // Remove timestamp fields from updates as they should be handled by the database
      const { createdAt, updatedAt, ...cleanUpdates } = updates;
      
      const updatedProperty = await storage.updateProperty(req.params.id, cleanUpdates);
      if (!updatedProperty) {
        return res.status(404).json({ error: "Property not found" });
      }
      res.json(updatedProperty);
    } catch (error) {
      console.error('Error updating property:', error);
      res.status(500).json({ error: "Failed to update property" });
    }
  });

  app.delete("/api/admin/properties/:id", async (req, res) => {
    try {
      const success = await storage.deleteProperty(req.params.id);
      if (!success) {
        return res.status(404).json({ error: "Property not found" });
      }
      res.json({ success: true });
    } catch (error) {
      res.status(500).json({ error: "Failed to delete property" });
    }
  });

  // Admin booking management
  app.get("/api/admin/bookings", async (req, res) => {
    try {
      const bookings = await storage.getBookings();
      res.json(bookings);
    } catch (error) {
      res.status(500).json({ error: "Failed to fetch bookings" });
    }
  });

  app.put("/api/admin/bookings/:id", async (req, res) => {
    try {
      const updates = req.body;
      
      // Remove timestamp fields from updates
      const { createdAt, updatedAt, ...cleanUpdates } = updates;
      
      const booking = await storage.updateBooking(req.params.id, cleanUpdates);
      if (!booking) {
        return res.status(404).json({ error: "Booking not found" });
      }
      res.json(booking);
    } catch (error) {
      res.status(500).json({ error: "Failed to update booking" });
    }
  });

  app.delete("/api/admin/bookings/:id", async (req, res) => {
    try {
      const success = await storage.deleteBooking(req.params.id);
      if (!success) {
        return res.status(404).json({ error: "Booking not found" });
      }
      res.json({ success: true });
    } catch (error) {
      res.status(500).json({ error: "Failed to delete booking" });
    }
  });

  // Admin moving services management
  app.get("/api/admin/moving-services", async (req, res) => {
    try {
      const services = await storage.getMovingServices();
      res.json(services);
    } catch (error) {
      res.status(500).json({ error: "Failed to fetch moving services" });
    }
  });

  app.post("/api/admin/moving-services", async (req, res) => {
    try {
      const serviceData = insertMovingServiceSchema.parse(req.body);
      const service = await storage.createMovingService(serviceData);
      res.status(201).json(service);
    } catch (error) {
      console.error('Error creating moving service:', error);
      res.status(400).json({ error: "Invalid service data" });
    }
  });

  app.put("/api/admin/moving-services/:id", async (req, res) => {
    try {
      const { id } = req.params;
      const updates = req.body;
      
      // Remove timestamp fields from updates
      const { createdAt, updatedAt, ...cleanUpdates } = updates;
      
      const updatedService = await storage.updateMovingService(id, cleanUpdates);
      
      if (updatedService) {
        res.json(updatedService);
      } else {
        res.status(404).json({ error: "Service not found" });
      }
    } catch (error) {
      console.error('Error updating moving service:', error);
      res.status(500).json({ error: "Failed to update service" });
    }
  });

  app.delete("/api/admin/moving-services/:id", async (req, res) => {
    try {
      const success = await storage.deleteMovingService(req.params.id);
      if (!success) {
        return res.status(404).json({ error: "Moving service not found" });
      }
      res.json({ success: true });
    } catch (error) {
      res.status(500).json({ error: "Failed to delete moving service" });
    }
  });

  // Stats route for public dashboard
  app.get("/api/stats", async (req, res) => {
    try {
      const allProperties = await storage.getProperties();
      const allBookings = await storage.getBookings();
      const allServices = await storage.getMovingServices();
      
      const stats = {
        totalProperties: allProperties.length,
        activeUsers: 3892, // Mock data as no user count available
        bookings: allBookings.length,
        revenue: "$89,420" // Mock data
      };
      
      res.json(stats);
    } catch (error) {
      res.status(500).json({ error: "Failed to fetch stats" });
    }
  });

  // Notification endpoints
  app.post("/api/notifications/property-inquiry", async (req, res) => {
    try {
      const { propertyId, inquirerEmail, message } = req.body;
      
      if (!propertyId || !inquirerEmail || !message) {
        return res.status(400).json({ error: "Missing required fields" });
      }
      
      const property = await storage.getProperty(propertyId);
      if (!property) {
        return res.status(404).json({ error: "Property not found" });
      }
      
      await notificationManager.sendPropertyInquiry(property, inquirerEmail, message);
      
      // Send admin alert about new inquiry
      await notificationManager.sendAdminAlert(
        'New Property Inquiry',
        `Property: ${property.title} - Inquirer: ${inquirerEmail}`
      );
      
      res.json({ success: true, message: "Inquiry sent successfully" });
    } catch (error) {
      console.error('Failed to send property inquiry:', error);
      res.status(500).json({ error: "Failed to send inquiry" });
    }
  });

  app.post("/api/notifications/price-alert", async (req, res) => {
    try {
      const { propertyId, userEmail, targetPrice, userPhone } = req.body;
      
      if (!propertyId || !userEmail || !targetPrice) {
        return res.status(400).json({ error: "Missing required fields" });
      }
      
      const property = await storage.getProperty(propertyId);
      if (!property) {
        return res.status(404).json({ error: "Property not found" });
      }
      
      await notificationManager.sendPriceAlert(userEmail, property, targetPrice, userPhone);
      
      res.json({ success: true, message: "Price alert sent successfully" });
    } catch (error) {
      console.error('Failed to send price alert:', error);
      res.status(500).json({ error: "Failed to send price alert" });
    }
  });

  app.post("/api/notifications/admin-alert", async (req, res) => {
    try {
      const { subject, message } = req.body;
      
      if (!subject || !message) {
        return res.status(400).json({ error: "Subject and message are required" });
      }
      
      await notificationManager.sendAdminAlert(subject, message);
      
      res.json({ success: true, message: "Admin alert sent successfully" });
    } catch (error) {
      console.error('Failed to send admin alert:', error);
      res.status(500).json({ error: "Failed to send admin alert" });
    }
  });

  // Test notification endpoint
  app.post("/api/notifications/test", async (req, res) => {
    try {
      const { type, email } = req.body;
      
      if (!type || !email) {
        return res.status(400).json({ error: "Type and email are required" });
      }
      
      if (type === 'welcome') {
        const testUser = { 
          id: 'test-user',
          name: 'Test User', 
          email,
          password: '',
          role: 'buyer',
          phone: null,
          profileCompleted: false,
          createdAt: new Date(),
          updatedAt: new Date()
        };
        await notificationManager.sendWelcomeNotifications(testUser);
      } else if (type === 'admin') {
        await notificationManager.sendAdminAlert('Test Alert', 'This is a test notification from KiroServices platform.');
      }
      
      res.json({ success: true, message: `Test ${type} notification sent to ${email}` });
    } catch (error) {
      console.error('Failed to send test notification:', error);
      res.status(500).json({ error: "Failed to send test notification" });
    }
  });

  // User role management
  app.put('/api/users/update-role', async (req, res) => {
    try {
      const { userId, role, profileCompleted } = req.body;
      
      if (!userId || !role) {
        return res.status(400).json({ error: 'User ID and role are required' });
      }

      if (!['buyer', 'renter', 'property_owner'].includes(role)) {
        return res.status(400).json({ error: 'Invalid role specified' });
      }

      const updatedUser = await storage.updateUserRole(userId, role, profileCompleted || false);
      if (!updatedUser) {
        return res.status(404).json({ error: 'User not found' });
      }

      res.json(updatedUser);
    } catch (error) {
      console.error('Error updating user role:', error);
      res.status(500).json({ error: 'Failed to update user role' });
    }
  });



  // Placeholder image endpoint for development
  app.get("/api/placeholder/:width/:height", (req, res) => {
    const { width, height } = req.params;
    const svg = `
      <svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">
        <defs>
          <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
            <stop offset="0%" style="stop-color:#0091B9;stop-opacity:1" />
            <stop offset="100%" style="stop-color:#FF6500;stop-opacity:1" />
          </linearGradient>
        </defs>
        <rect width="100%" height="100%" fill="url(#bg)"/>
        <circle cx="50%" cy="40%" r="30" fill="white" opacity="0.8"/>
        <text x="50%" y="40%" text-anchor="middle" dy="0.3em" font-family="Arial, sans-serif" font-size="20" fill="#0091B9" font-weight="bold">
          🚛
        </text>
        <text x="50%" y="70%" text-anchor="middle" dy="0.3em" font-family="Arial, sans-serif" font-size="14" fill="white" font-weight="bold">
          Moving Service
        </text>
        <text x="50%" y="85%" text-anchor="middle" dy="0.3em" font-family="Arial, sans-serif" font-size="12" fill="white" opacity="0.8">
          Professional & Reliable
        </text>
      </svg>
    `;
    res.setHeader('Content-Type', 'image/svg+xml');
    res.send(svg);
  });

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