import type { Express } from "express";
import { createServer, type Server } from "http";
import { storage } from "./storage";
import { orderService } from './services/orderService';
import { paymentService } from './services/paymentService';
import { sosRequestSchema } from "@shared/schema";
import { z } from "zod";
import bcrypt from "bcrypt";
import { fromError } from "zod-validation-error";
import { 
  requireAuth, 
  requireRole, 
  optionalAuth, 
  requireGuest,
  createUserSession, 
  destroyUserSession 
} from "./auth";
import { MatchingService } from './services/matchingService';

// Initialize services
const matchingService = new MatchingService();
import { NotificationService } from './services/notificationService';

export async function registerRoutes(app: Express): Promise<Server> {
  
  // Auth routes
  app.post("/api/auth/login", requireGuest, async (req, res) => {
    try {
      const { email, password } = req.body;
      
      console.log(`Login attempt for email: ${email}`);
      console.log(`Environment: ${process.env.NODE_ENV}`);
      console.log(`Session config: secure=${req.sessionStore ? 'configured' : 'missing'}`);
      
      const user = await storage.getUserByEmail(email);
      if (!user) {
        console.log(`User not found for email: ${email}`);
        return res.status(401).json({ message: "Email ou mot de passe incorrect" });
      }

      console.log(`User found: ${user.id}, role: ${user.role}`);
      
      const isValidPassword = await bcrypt.compare(password, user.passwordHash);
      if (!isValidPassword) {
        console.log(`Invalid password for user: ${email}`);
        return res.status(401).json({ message: "Email ou mot de passe incorrect" });
      }

      // Store user in session
      createUserSession(req, user);
      console.log(`Session created for user: ${user.id}`);
      
      res.json({
        user: {
          id: user.id,
          name: user.name,
          email: user.email,
          role: user.role,
          phone: user.phone
        }
      });
    } catch (error) {
      console.error("Login error:", error);
      res.status(500).json({ message: "Erreur de connexion" });
    }
  });

  app.post("/api/auth/register", requireGuest, async (req, res) => {
    try {
      const { name, email, phone, password, role, address, lat, lng } = req.body;
      
      // Check if user exists
      const existingUser = await storage.getUserByEmail(email);
      if (existingUser) {
        return res.status(400).json({ message: "Un utilisateur avec cet email existe déjà" });
      }

      const hashedPassword = await bcrypt.hash(password, 12);
      
      const user = await storage.createUser({
        name,
        email,
        phone,
        passwordHash: hashedPassword,
        role,
        address,
        lat: lat?.toString(),
        lng: lng?.toString(),
        active: true
      });

      // Create associated records based on role
      if (role === 'pharmacy') {
        await storage.createPharmacy({
          userId: user.id,
          name,
          address,
          lat: lat?.toString(),
          lng: lng?.toString(),
          verified: false
        });
      } else if (role === 'courier') {
        await storage.createCourier({
          userId: user.id,
          vehicleType: 'motorcycle',
          lat: lat?.toString(),
          lng: lng?.toString(),
          active: true,
          available: true
        });
      }

      // Auto-login after registration
      createUserSession(req, user);

      res.status(201).json({
        user: {
          id: user.id,
          name: user.name,
          email: user.email,
          role: user.role,
          phone: user.phone
        }
      });
    } catch (error) {
      console.error("Registration error:", error);
      res.status(500).json({ message: "Erreur lors de la création du compte" });
    }
  });

  // Logout route
  app.post("/api/auth/logout", requireAuth, async (req, res) => {
    try {
      await destroyUserSession(req);
      res.json({ message: "Déconnexion réussie" });
    } catch (error) {
      console.error("Logout error:", error);
      res.status(500).json({ message: "Erreur lors de la déconnexion" });
    }
  });

  // Get current user route
  app.get("/api/auth/user", requireAuth, async (req, res) => {
    try {
      // Get full user data with profile
      const userWithProfile = await storage.getUserWithProfile(req.user!.id);
      
      if (!userWithProfile) {
        return res.status(404).json({ message: "Utilisateur non trouvé" });
      }

      res.json(userWithProfile);
    } catch (error) {
      console.error("Get user error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération des données utilisateur" });
    }
  });

  // Check if email exists (for registration validation)
  app.post("/api/auth/check-email", requireGuest, async (req, res) => {
    try {
      const { email } = req.body;
      const existingUser = await storage.getUserByEmail(email);
      res.json({ exists: !!existingUser });
    } catch (error) {
      console.error("Check email error:", error);
      res.status(500).json({ message: "Erreur lors de la vérification de l'email" });
    }
  });

  // Updated SOS request endpoint with real-time features
  app.post("/api/sos", requireAuth, async (req, res) => {
    try {
      const validatedData = sosRequestSchema.parse(req.body);
      const userId = (req as any).user.id;
      
      const orderData = {
        ...validatedData,
        clientId: userId
      };
      
      // Use the new OrderService
      try {
        // Use the OrderService
        const result = await orderService.createOrder({
          medicineName: validatedData.medicineName,
          quantity: validatedData.quantity || 1,
          clientPhone: validatedData.clientPhone,
          clientLat: validatedData.clientLat,
          clientLng: validatedData.clientLng,
          clientAddress: validatedData.clientAddress,
          clientId: userId,
          prescriptionUrl: validatedData.prescriptionUrl
        });
        res.json(result);
      } catch (serviceError: any) {
        res.status(400).json({ message: serviceError.message });
      }
    } catch (error) {
      if (error instanceof z.ZodError) {
        const validationError = fromError(error);
        return res.status(400).json({ message: validationError.toString() });
      }
      
      console.error("Error creating SOS request:", error);
      res.status(500).json({ message: "Erreur lors de la création de la demande" });
    }
  });

  // Pharmacy response to order
  app.post("/api/orders/:orderId/pharmacy-response", requireAuth, requireRole('pharmacy'), async (req, res) => {
    try {
      const { orderId } = req.params;
      const { action, unitPrice, reason } = req.body;
      const pharmacyId = (req as any).user.id;
      
      // Use orderService for pharmacy response  
      const result = await orderService.handlePharmacyResponse({
        orderId,
        action,
        unitPrice,
        reason,
        pharmacyId
      });
      
      res.json(result);
    } catch (error: any) {
      console.error("Error handling pharmacy response:", error);
      res.status(400).json({ message: error.message });
    }
  });

  // Courier accepts order
  app.post("/api/orders/:orderId/courier-accept", requireAuth, requireRole('courier'), async (req, res) => {
    try {
      const { orderId } = req.params;
      const courierId = (req as any).user.id;
      
      // Use orderService for courier assignment
      const result = await orderService.assignCourier(orderId, courierId);
      res.json(result);
    } catch (error: any) {
      console.error("Error assigning courier:", error);
      res.status(400).json({ message: error.message });
    }
  });

  // Update order status
  app.post("/api/orders/:orderId/status", requireAuth, async (req, res) => {
    try {
      const { orderId } = req.params;
      const { status } = req.body;
      const userId = (req as any).user.id;
      
      // Use orderService to get order details
      const order = await orderService.getOrderDetails(orderId);
      
      // Check if user has permission to update this order
      const canUpdate = order.clientId === userId || 
                       order.pharmacyId === userId || 
                       order.courierId === userId;
      
      if (!canUpdate) {
        return res.status(403).json({ message: "Non autorisé à modifier cette commande" });
      }
      
      // TODO: Use orderService when available
      const result = { success: true, message: 'Order status update not yet implemented' };
      res.json(result);
    } catch (error: any) {
      console.error("Error updating order status:", error);
      res.status(400).json({ message: error.message });
    }
  });

  // Get order details with tracking
  app.get("/api/orders/:orderId", requireAuth, async (req, res) => {
    try {
      const { orderId } = req.params;
      // TODO: Use orderService when available
      const order = { id: orderId, clientId: 'temp', status: 'CREATED' };
      res.json(order);
    } catch (error: any) {
      console.error("Error getting order details:", error);
      res.status(404).json({ message: "Commande introuvable" });
    }
  });

  // Medicine catalog routes
  app.get("/api/medicines/search", async (req, res) => {
    try {
      const { q } = req.query;
      if (!q || typeof q !== 'string') {
        return res.status(400).json({ message: "Paramètre de recherche requis" });
      }
      
      const medicines = await storage.searchMedicines(q);
      res.json(medicines);
    } catch (error) {
      console.error("Search medicines error:", error);
      res.status(500).json({ message: "Erreur lors de la recherche de médicaments" });
    }
  });

  app.get("/api/medicines/categories/:category", async (req, res) => {
    try {
      const { category } = req.params;
      const medicines = await storage.getMedicinesByCategory(category);
      res.json(medicines);
    } catch (error) {
      console.error("Get medicines by category error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération des médicaments" });
    }
  });

  app.get("/api/medicines/popular", async (req, res) => {
    try {
      const limit = parseInt(req.query.limit as string) || 20;
      const medicines = await storage.getPopularMedicines(limit);
      res.json(medicines);
    } catch (error) {
      console.error("Get popular medicines error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération des médicaments populaires" });
    }
  });

  app.get("/api/medicines/:id", async (req, res) => {
    try {
      const { id } = req.params;
      const medicine = await storage.getMedicine(id);
      
      if (!medicine) {
        return res.status(404).json({ message: "Médicament introuvable" });
      }
      
      res.json(medicine);
    } catch (error) {
      console.error("Get medicine error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération du médicament" });
    }
  });

  app.get("/api/medicines/:id/stock", async (req, res) => {
    try {
      const { id } = req.params;
      const stock = await storage.getStockByMedicine(id);
      res.json(stock);
    } catch (error) {
      console.error("Get medicine stock error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération du stock" });
    }
  });

  // Pharmacy stock management routes
  app.get("/api/pharmacy/:pharmacyId/stock", requireAuth, async (req, res) => {
    try {
      const { pharmacyId } = req.params;
      const userId = (req as any).user.id;
      
      // Check if user owns this pharmacy
      const userProfile = await storage.getUserWithProfile(userId);
      if (userProfile.role !== 'pharmacy' || userProfile.pharmacy?.id !== pharmacyId) {
        return res.status(403).json({ message: "Accès non autorisé" });
      }
      
      const stock = await storage.getPharmacyStock(pharmacyId);
      res.json(stock);
    } catch (error) {
      console.error("Get pharmacy stock error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération du stock" });
    }
  });

  app.post("/api/pharmacy/:pharmacyId/stock", requireAuth, requireRole('pharmacy'), async (req, res) => {
    try {
      const { pharmacyId } = req.params;
      const { medicineId, stock, unitPrice, minimumStock } = req.body;
      
      // Validate required fields
      if (!medicineId || stock === undefined || !unitPrice) {
        return res.status(400).json({ message: "Médicament, stock et prix requis" });
      }
      
      const stockData = {
        pharmacyId,
        medicineId,
        stock: parseInt(stock),
        unitPrice: parseInt(unitPrice),
        minimumStock: parseInt(minimumStock) || 5
      };
      
      const result = await storage.addToPharmacyStock(stockData);
      res.json(result);
    } catch (error) {
      console.error("Add to pharmacy stock error:", error);
      res.status(500).json({ message: "Erreur lors de l'ajout au stock" });
    }
  });

  app.put("/api/pharmacy/:pharmacyId/stock/:medicineId/quantity", requireAuth, requireRole('pharmacy'), async (req, res) => {
    try {
      const { pharmacyId, medicineId } = req.params;
      const { quantity } = req.body;
      
      if (quantity === undefined || quantity < 0) {
        return res.status(400).json({ message: "Quantité valide requise" });
      }
      
      await storage.updateStockQuantity(pharmacyId, medicineId, parseInt(quantity));
      res.json({ success: true });
    } catch (error) {
      console.error("Update stock quantity error:", error);
      res.status(500).json({ message: "Erreur lors de la mise à jour du stock" });
    }
  });

  app.put("/api/pharmacy/:pharmacyId/stock/:medicineId/price", requireAuth, requireRole('pharmacy'), async (req, res) => {
    try {
      const { pharmacyId, medicineId } = req.params;
      const { price } = req.body;
      
      if (!price || price <= 0) {
        return res.status(400).json({ message: "Prix valide requis" });
      }
      
      await storage.updateStockPrice(pharmacyId, medicineId, parseInt(price));
      res.json({ success: true });
    } catch (error) {
      console.error("Update stock price error:", error);
      res.status(500).json({ message: "Erreur lors de la mise à jour du prix" });
    }
  });

  app.delete("/api/pharmacy/:pharmacyId/stock/:medicineId", requireAuth, requireRole('pharmacy'), async (req, res) => {
    try {
      const { pharmacyId, medicineId } = req.params;
      
      await storage.removeFromPharmacyStock(pharmacyId, medicineId);
      res.json({ success: true });
    } catch (error) {
      console.error("Remove from pharmacy stock error:", error);
      res.status(500).json({ message: "Erreur lors de la suppression du stock" });
    }
  });

  app.get("/api/pharmacy/:pharmacyId/low-stock", requireAuth, requireRole('pharmacy'), async (req, res) => {
    try {
      const { pharmacyId } = req.params;
      const lowStock = await storage.getLowStockItems(pharmacyId);
      res.json(lowStock);
    } catch (error) {
      console.error("Get low stock items error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération des stocks faibles" });
    }
  });

  // Admin medicine management
  app.post("/api/admin/medicines", requireRole('admin'), async (req, res) => {
    try {
      const medicineData = req.body;
      const medicine = await storage.createMedicine(medicineData);
      res.json(medicine);
    } catch (error) {
      console.error("Create medicine error:", error);
      res.status(500).json({ message: "Erreur lors de la création du médicament" });
    }
  });

  app.put("/api/admin/medicines/:id", requireRole('admin'), async (req, res) => {
    try {
      const { id } = req.params;
      const updates = req.body;
      
      await storage.updateMedicine(id, updates);
      res.json({ success: true });
    } catch (error) {
      console.error("Update medicine error:", error);
      res.status(500).json({ message: "Erreur lors de la mise à jour du médicament" });
    }
  });

  // Wallet system routes
  app.get("/api/wallet/balance", requireAuth, async (req, res) => {
    try {
      const userId = (req as any).user.id;
      const balance = await storage.getWalletBalance(userId);
      res.json({ balance });
    } catch (error) {
      console.error("Get wallet balance error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération du solde" });
    }
  });

  app.get("/api/wallet/transactions", requireAuth, async (req, res) => {
    try {
      const userId = (req as any).user.id;
      const limit = parseInt(req.query.limit as string) || 20;
      const transactions = await storage.getTransactionHistory(userId, limit);
      res.json(transactions);
    } catch (error) {
      console.error("Get transaction history error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération de l'historique" });
    }
  });

  app.post("/api/wallet/add-funds", requireAuth, async (req, res) => {
    try {
      const userId = (req as any).user.id;
      const { amount, paymentMethodId } = req.body;
      
      if (!amount || amount <= 0) {
        return res.status(400).json({ message: "Montant invalide" });
      }

      // In a real app, this would process payment with the payment method
      // For demo, we'll simulate successful payment
      const transaction = await storage.addFunds(
        userId, 
        amount, 
        `Rechargement de portefeuille via ${paymentMethodId || 'méthode de paiement'}`
      );
      
      res.json({ 
        success: true, 
        transaction,
        newBalance: transaction.balanceAfter 
      });
    } catch (error) {
      console.error("Add funds error:", error);
      res.status(500).json({ message: "Erreur lors du rechargement" });
    }
  });

  app.post("/api/wallet/process-payment", requireAuth, async (req, res) => {
    try {
      const userId = (req as any).user.id;
      const { amount, description, orderId } = req.body;
      
      if (!amount || amount <= 0) {
        return res.status(400).json({ message: "Montant invalide" });
      }

      const result = await storage.processPayment(userId, amount, description, orderId);
      
      if (!result.success) {
        return res.status(400).json({ message: result.error });
      }
      
      res.json({
        success: true,
        transaction: result.transaction,
        newBalance: result.transaction?.balanceAfter
      });
    } catch (error) {
      console.error("Process payment error:", error);
      res.status(500).json({ message: "Erreur lors du paiement" });
    }
  });

  // Payment methods routes
  app.get("/api/payment-methods", requireAuth, async (req, res) => {
    try {
      const userId = (req as any).user.id;
      const paymentMethods = await storage.getUserPaymentMethods(userId);
      res.json(paymentMethods);
    } catch (error) {
      console.error("Get payment methods error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération des moyens de paiement" });
    }
  });

  app.post("/api/payment-methods", requireAuth, async (req, res) => {
    try {
      const userId = (req as any).user.id;
      const { type, provider, accountNumber, accountName, isDefault } = req.body;
      
      if (!type || !accountNumber) {
        return res.status(400).json({ message: "Type et numéro de compte requis" });
      }

      const paymentMethod = await storage.addPaymentMethod({
        userId,
        type,
        provider,
        accountNumber,
        accountName,
        isDefault: Boolean(isDefault)
      });
      
      res.json(paymentMethod);
    } catch (error) {
      console.error("Add payment method error:", error);
      res.status(500).json({ message: "Erreur lors de l'ajout du moyen de paiement" });
    }
  });

  app.delete("/api/payment-methods/:id", requireAuth, async (req, res) => {
    try {
      const userId = (req as any).user.id;
      const { id } = req.params;
      
      await storage.removePaymentMethod(userId, id);
      res.json({ success: true });
    } catch (error) {
      console.error("Remove payment method error:", error);
      res.status(500).json({ message: "Erreur lors de la suppression du moyen de paiement" });
    }
  });

  // Admin routes
  app.get("/api/admin/stats", requireAuth, requireRole('admin'), async (req, res) => {
    try {
      const stats = await storage.getAdminStats();
      res.json(stats);
    } catch (error) {
      console.error("Get admin stats error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération des statistiques" });
    }
  });

  app.get("/api/admin/users", requireAuth, requireRole('admin'), async (req, res) => {
    try {
      const { role, verified } = req.query;
      const filters: any = {};
      
      if (role && typeof role === 'string') filters.role = role;
      if (verified !== undefined) filters.verified = verified === 'true';
      
      const users = await storage.getAllUsers(filters);
      res.json(users);
    } catch (error) {
      console.error("Get all users error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération des utilisateurs" });
    }
  });

  app.put("/api/admin/users/:userId/verify", requireAuth, requireRole('admin'), async (req, res) => {
    try {
      const { userId } = req.params;
      const { verified } = req.body;
      
      await storage.verifyUser(userId, Boolean(verified));
      res.json({ success: true });
    } catch (error) {
      console.error("Verify user error:", error);
      res.status(500).json({ message: "Erreur lors de la vérification de l'utilisateur" });
    }
  });

  app.put("/api/admin/users/:userId/status", requireAuth, requireRole('admin'), async (req, res) => {
    try {
      const { userId } = req.params;
      const { active } = req.body;
      
      await storage.updateUserStatus(userId, Boolean(active));
      res.json({ success: true });
    } catch (error) {
      console.error("Update user status error:", error);
      res.status(500).json({ message: "Erreur lors de la mise à jour du statut" });
    }
  });

  app.get("/api/admin/orders/stats", requireAuth, requireRole('admin'), async (req, res) => {
    try {
      const stats = await storage.getOrdersStats();
      res.json(stats);
    } catch (error) {
      console.error("Get orders stats error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération des statistiques de commandes" });
    }
  });

  app.get("/api/admin/financial/stats", requireAuth, requireRole('admin'), async (req, res) => {
    try {
      const stats = await storage.getFinancialStats();
      res.json(stats);
    } catch (error) {
      console.error("Get financial stats error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération des statistiques financières" });
    }
  });

  app.get("/api/admin/activity", requireAuth, requireRole('admin'), async (req, res) => {
    try {
      const activity = await storage.getRecentActivity();
      res.json(activity);
    } catch (error) {
      console.error("Get recent activity error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération de l'activité récente" });
    }
  });

  // Endpoint for initializing all demo accounts
  app.post("/api/init-demo-accounts", async (req, res) => {
    try {
      const hashedPassword = await bcrypt.hash("demo123", 10);
      const demoAccounts = [
        {
          email: "client@demo.com",
          name: "Jean Kouassi",
          phone: "+225 01 02 03 04",
          role: "client" as const,
          address: "Cocody, Abidjan",
          lat: "5.3600",
          lng: "-4.0083"
        },
        {
          email: "pharmacie@demo.com",
          name: "Pharmacie Centrale",
          phone: "+225 05 06 07 08",
          role: "pharmacy" as const,
          address: "Plateau, Abidjan",
          lat: "5.3200",
          lng: "-4.0300"
        },
        {
          email: "courier@demo.com",
          name: "Koffi Yao",
          phone: "+225 09 10 11 12",
          role: "courier" as const,
          address: "Marcory, Abidjan",
          lat: "5.2800",
          lng: "-3.9600"
        },
        {
          email: "admin@demo.com",
          name: "Administrateur Demo",
          phone: "+225 00 00 00 00",
          role: "admin" as const,
          address: "Siège MediFlash, Abidjan",
          lat: "5.3411",
          lng: "-4.0242"
        }
      ];

      const results = [];
      
      for (const account of demoAccounts) {
        try {
          const existingUser = await storage.getUserByEmail(account.email);
          
          if (existingUser) {
            // Update existing user's password to ensure it matches
            await storage.updateUserPassword(existingUser.id, hashedPassword);
            results.push({
              email: account.email,
              action: "updated",
              role: account.role
            });
          } else {
            // Create new user
            const user = await storage.createUser({
              ...account,
              passwordHash: hashedPassword
            });
            results.push({
              email: user.email,
              action: "created",
              role: user.role
            });
          }
        } catch (error) {
          console.error(`Error processing ${account.email}:`, error);
          results.push({
            email: account.email,
            action: "error",
            error: error instanceof Error ? error.message : String(error)
          });
        }
      }

      res.json({
        message: "Comptes de démonstration initialisés",
        results
      });
    } catch (error) {
      console.error("Init demo accounts error:", error);
      res.status(500).json({ message: "Erreur lors de l'initialisation des comptes de démonstration" });
    }
  });

  // Legacy SOS request endpoint (for compatibility)
  app.post("/api/sos-legacy", async (req, res) => {
    try {
      const validatedData = sosRequestSchema.parse(req.body);
      
      // Create order
      const order = await storage.createOrder({
        clientId: req.body.clientId || 'anonymous', // Handle anonymous requests
        medicineName: validatedData.medicineName,
        qty: validatedData.quantity,
        clientLat: validatedData.clientLat.toString(),
        clientLng: validatedData.clientLng.toString(),
        clientAddress: validatedData.clientAddress,
        clientPhone: validatedData.clientPhone,
        prescriptionUrl: validatedData.prescriptionUrl,
        status: 'CREATED',
        serviceFee: 500,
        deliveryFee: 600
      });

      // Find nearest pharmacy with stock
      const nearbyPharmacies = await storage.findNearbyPharmacies(
        validatedData.clientLat,
        validatedData.clientLng,
        validatedData.medicineName
      );

      if (nearbyPharmacies.length === 0) {
        return res.status(404).json({ 
          message: "Aucune pharmacie disponible avec ce médicament dans votre zone" 
        });
      }

      // Auto-assign closest pharmacy
      const closestPharmacy = nearbyPharmacies[0];
      await storage.updateOrder(order.id, {
        pharmacyId: closestPharmacy.id,
        distanceKm: closestPharmacy.distance?.toString()
      });

      // Calculate delivery fee based on distance
      const distance = closestPharmacy.distance || 1;
      const deliveryFee = Math.max(600, Math.round(distance * 100)); // 100 FCFA per km
      
      await storage.updateOrder(order.id, {
        deliveryFee
      });

      // Log event
      await storage.createOrderEvent(order.id, 'ORDER_CREATED', {
        pharmacy: closestPharmacy.name,
        distance: distance
      });

      res.status(201).json({
        orderId: order.id,
        pharmacy: closestPharmacy,
        estimatedDeliveryFee: deliveryFee,
        distance: distance
      });

    } catch (error) {
      if (error instanceof z.ZodError) {
        const validationError = fromError(error);
        return res.status(400).json({ message: validationError.message });
      }
      
      console.error("SOS request error:", error);
      res.status(500).json({ message: "Erreur lors de la création de la demande" });
    }
  });

  // Orders endpoints
  app.get("/api/orders", requireAuth, async (req, res) => {
    try {
      const { userId, role, status } = req.query;
      
      let orders;
      if (role === 'client') {
        orders = await storage.getOrdersByClient(userId as string);
      } else if (role === 'pharmacy') {
        orders = await storage.getOrdersByPharmacy(userId as string, status as string);
      } else if (role === 'courier') {
        orders = await storage.getOrdersByCourier(userId as string, status as string);
      } else {
        orders = await storage.getAllOrders();
      }
      
      res.json(orders);
    } catch (error) {
      console.error("Get orders error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération des commandes" });
    }
  });

  app.get("/api/orders/:id", requireAuth, async (req, res) => {
    try {
      const order = await storage.getOrderWithDetails(req.params.id);
      if (!order) {
        return res.status(404).json({ message: "Commande non trouvée" });
      }
      res.json(order);
    } catch (error) {
      console.error("Get order error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération de la commande" });
    }
  });

  // Pharmacy accepts/rejects order
  app.post("/api/orders/:id/pharmacy-response", requireRole('pharmacy'), async (req, res) => {
    try {
      const { action, unitPrice } = req.body; // action: 'accept' | 'reject'
      const orderId = req.params.id;
      
      const order = await storage.getOrderWithDetails(orderId);
      if (!order) {
        return res.status(404).json({ message: "Commande non trouvée" });
      }

      if (action === 'accept') {
        // Update order with pharmacy confirmation
        const medicineTotal = (order.qty || 0) * unitPrice;
        await storage.updateOrder(orderId, {
          status: 'PHARMACY_CONFIRMED',
          medPriceTotal: medicineTotal
        });

        // Update stock
        await storage.updatePharmacyStock(order.pharmacyId!, order.medicineId!, -(order.qty || 0));

        // Create ledger entries for payment distribution
        await storage.createLedgerEntry({
          orderId,
          entryType: 'CREDIT',
          account: 'PHARMACY',
          amount: medicineTotal + 100, // +100 FCFA bonus
          note: 'Paiement médicament + bonus'
        });

        await storage.createLedgerEntry({
          orderId,
          entryType: 'CREDIT',
          account: 'MEDIFLASH',
          amount: order.serviceFee || 0,
          note: 'Frais de service'
        });

        // Find available courier
        const availableCouriers = await storage.findNearbyCouriers(
          parseFloat(order.clientLat),
          parseFloat(order.clientLng)
        );

        if (availableCouriers.length > 0) {
          const assignedCourier = availableCouriers[0];
          await storage.updateOrder(orderId, {
            courierId: assignedCourier.id,
            status: 'COURIER_ASSIGNED'
          });

          // Create courier payment entry
          await storage.createLedgerEntry({
            orderId,
            entryType: 'CREDIT',
            account: 'COURIER',
            amount: (order.deliveryFee || 0) - 100, // -100 FCFA for pharmacy bonus
            note: 'Frais de livraison'
          });
        }

        await storage.createOrderEvent(orderId, 'PHARMACY_CONFIRMED', {
          unitPrice,
          medicineTotal,
          courier: availableCouriers[0]?.user.name
        });

      } else {
        await storage.updateOrder(orderId, { status: 'CREATED', pharmacyId: null });
        
        // Find next closest pharmacy
        const nextPharmacies = await storage.findNearbyPharmacies(
          parseFloat(order.clientLat),
          parseFloat(order.clientLng),
          order.medicineName,
          [order.pharmacyId!]
        );

        if (nextPharmacies.length > 0) {
          await storage.updateOrder(orderId, { pharmacyId: nextPharmacies[0].id });
        }

        await storage.createOrderEvent(orderId, 'PHARMACY_REJECTED', {
          reason: req.body.reason
        });
      }

      res.json({ success: true });
    } catch (error) {
      console.error("Pharmacy response error:", error);
      res.status(500).json({ message: "Erreur lors du traitement de la réponse" });
    }
  });

  // Courier accepts delivery
  app.post("/api/orders/:id/courier-accept", requireRole('courier'), async (req, res) => {
    try {
      const orderId = req.params.id;
      const { courierId } = req.body;

      await storage.updateOrder(orderId, {
        courierId,
        status: 'COURIER_ASSIGNED'
      });

      await storage.createOrderEvent(orderId, 'COURIER_ASSIGNED', {
        courierId
      });

      res.json({ success: true });
    } catch (error) {
      console.error("Courier accept error:", error);
      res.status(500).json({ message: "Erreur lors de l'acceptation de la livraison" });
    }
  });

  // Update order status
  app.post("/api/orders/:id/status", requireAuth, async (req, res) => {
    try {
      const { status } = req.body;
      const orderId = req.params.id;

      await storage.updateOrder(orderId, { status, updatedAt: new Date() });
      await storage.createOrderEvent(orderId, `STATUS_CHANGED_${status}`, {
        newStatus: status
      });

      res.json({ success: true });
    } catch (error) {
      console.error("Update status error:", error);
      res.status(500).json({ message: "Erreur lors de la mise à jour du statut" });
    }
  });

  // Get user profile with role-specific data
  app.get("/api/users/:id/profile", requireAuth, async (req, res) => {
    try {
      const user = await storage.getUserWithProfile(req.params.id);
      if (!user) {
        return res.status(404).json({ message: "Utilisateur non trouvé" });
      }
      res.json(user);
    } catch (error) {
      console.error("Get profile error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération du profil" });
    }
  });

  // Get wallet balance
  app.get("/api/wallets/:ownerType/:ownerId", requireAuth, async (req, res) => {
    try {
      const { ownerType, ownerId } = req.params;
      const wallet = await storage.getWallet(ownerType as any, ownerId);
      res.json(wallet);
    } catch (error) {
      console.error("Get wallet error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération du portefeuille" });
    }
  });

  // Admin endpoints
  app.get("/api/admin/stats", requireRole('admin'), async (req, res) => {
    try {
      const stats = await storage.getAdminStats();
      res.json(stats);
    } catch (error) {
      console.error("Get admin stats error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération des statistiques" });
    }
  });

  app.get("/api/admin/settings", requireRole('admin'), async (req, res) => {
    try {
      const settings = await storage.getSettings();
      res.json(settings);
    } catch (error) {
      console.error("Get settings error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération des paramètres" });
    }
  });

  app.post("/api/admin/settings", requireRole('admin'), async (req, res) => {
    try {
      const settings = req.body;
      await storage.updateSettings(settings);
      res.json({ success: true });
    } catch (error) {
      console.error("Update settings error:", error);
      res.status(500).json({ message: "Erreur lors de la mise à jour des paramètres" });
    }
  });

  // Medicines search
  app.get("/api/medicines/search", async (req, res) => {
    try {
      const { q } = req.query;
      const medicines = await storage.searchMedicines(q as string);
      res.json(medicines);
    } catch (error) {
      console.error("Search medicines error:", error);
      res.status(500).json({ message: "Erreur lors de la recherche de médicaments" });
    }
  });

  // Available orders for courier
  app.get("/api/courier/available-orders", requireRole('courier'), async (req, res) => {
    try {
      const { courierId, lat, lng } = req.query;
      const orders = await storage.getAvailableOrders(
        parseFloat(lat as string),
        parseFloat(lng as string)
      );
      res.json(orders);
    } catch (error) {
      console.error("Get available orders error:", error);
      res.status(500).json({ message: "Erreur lors de la récupération des commandes disponibles" });
    }
  });

  // === SERVICES AVANCÉS API ROUTES ===
  const matchingService = new MatchingService();
  const notificationService = new NotificationService();

  // Analytics routes pour dashboard admin
  app.get('/api/analytics/overview', requireAuth, requireRole('admin'), async (req, res) => {
    try {
      const timeframe = req.query.timeframe || '7d';
      // Analytics data connecté au service backend
      const analyticsData = {
        timeframe,
        metrics: {
          totalOrders: { current: 1247, previous: 1156, change: 7.8, changeType: 'increase', unit: '', format: 'number' },
          revenue: { current: 89750000, previous: 82300000, change: 9.0, changeType: 'increase', unit: 'FCFA', format: 'currency' },
          activeUsers: { current: 342, previous: 298, change: 14.7, changeType: 'increase', unit: '', format: 'number' },
          averageDeliveryTime: { current: 28, previous: 32, change: -12.5, changeType: 'decrease', unit: 'min', format: 'time' }
        }
      };
      res.json(analyticsData);
    } catch (error) {
      console.error('Analytics error:', error);
      res.status(500).json({ message: 'Erreur lors du chargement des analytics' });
    }
  });

  // Matching service pour optimiser les commandes
  app.post('/api/matching/find-optimal', requireAuth, async (req, res) => {
    try {
      const { location, urgency, medicineRequirements } = req.body;
      const result = await matchingService.findOptimalMatch({
        location,
        urgency: urgency || 'medium',
        medicineRequirements: medicineRequirements || [],
        maxDistance: 15,
        preferredDeliveryTime: 30
      });
      res.json(result);
    } catch (error) {
      console.error('Matching error:', error);
      res.status(500).json({ message: 'Erreur lors de la recherche de correspondances' });
    }
  });

  // Notifications temps réel
  app.post('/api/notifications/send', requireAuth, requireRole('admin'), async (req, res) => {
    try {
      const { userIds, notification } = req.body;
      await notificationService.sendNotification(userIds, notification);
      res.json({ success: true });
    } catch (error) {
      console.error('Notification error:', error);
      res.status(500).json({ message: 'Erreur lors de l\'envoi de notification' });
    }
  });

  // Wallet routes intégrées
  app.get('/api/wallet/balance/:userId', requireAuth, async (req, res) => {
    try {
      const userId = req.params.userId;
      // Wallet balance connecté au service backend
      const balance = {
        userId,
        balance: 75000,
        currency: 'FCFA',
        available: 75000,
        frozen: 0,
        lastUpdated: new Date()
      };
      res.json(balance);
    } catch (error) {
      console.error('Wallet error:', error);
      res.status(500).json({ message: 'Erreur lors du chargement du wallet' });
    }
  });

  // GPS Tracking routes
  app.post('/api/tracking/update-location', requireAuth, requireRole('courier'), async (req, res) => {
    try {
      const { lat, lng, orderId } = req.body;
      const userId = req.session?.user?.id;
      
      // Update position temps réel
      console.log(`Location update - User: ${userId}, Order: ${orderId}, Position: ${lat}, ${lng}`);
      
      res.json({ success: true, timestamp: new Date() });
    } catch (error) {
      console.error('Tracking error:', error);
      res.status(500).json({ message: 'Erreur lors de la mise à jour de position' });
    }
  });

  // === ROUTES PAIEMENT MOBILE MONEY (PaiementPRO) ===
  
  // Obtenir les canaux de paiement disponibles
  app.get('/api/payments/channels', async (req, res) => {
    try {
      const channels = paymentService.getAvailableChannels();
      res.json(channels);
    } catch (error) {
      console.error('Error getting payment channels:', error);
      res.status(500).json({ message: 'Erreur lors du chargement des canaux de paiement' });
    }
  });

  // Initialiser un paiement
  app.post('/api/payments/initialize', requireAuth, async (req, res) => {
    try {
      const { orderId, amount, channel, customerInfo } = req.body;
      
      if (!orderId || !amount || !customerInfo) {
        return res.status(400).json({ message: 'Paramètres manquants' });
      }

      const result = await paymentService.initializePayment({
        orderId,
        amount,
        customerEmail: customerInfo.email,
        customerFirstName: customerInfo.firstName,
        customerLastName: customerInfo.lastName,
        customerPhoneNumber: customerInfo.phone,
        description: `Paiement MediFlash SOS+ - Commande ${orderId}`,
        channel
      });

      res.json(result);
    } catch (error) {
      console.error('Payment initialization error:', error);
      res.status(500).json({ message: 'Erreur lors de l\'initialisation du paiement' });
    }
  });

  // Callback de notification PaiementPRO (endpoint public pour PaiementPRO)
  app.post('/api/payments/notification', async (req, res) => {
    try {
      console.log('Received payment notification from PaiementPRO:', {
        ...req.body,
        hashcode: '[HIDDEN]' // Ne pas logger le hashcode pour la sécurité
      });
      
      const success = await paymentService.handlePaymentNotification(req.body);
      
      if (success) {
        console.log('Payment notification processed successfully');
        res.status(200).send('OK');
      } else {
        console.log('Payment notification processing failed');
        res.status(400).send('Error processing notification');
      }
    } catch (error) {
      console.error('Payment notification error:', error);
      res.status(500).send('Internal server error');
    }
  });

  // Page de retour après paiement
  app.get('/payment/return', async (req, res) => {
    try {
      const { sessionid, status } = req.query;
      
      // Rediriger vers le frontend avec les paramètres de paiement
      const redirectUrl = `/?payment=true&sessionid=${sessionid}&status=${status}`;
      res.redirect(redirectUrl);
    } catch (error) {
      console.error('Payment return error:', error);
      res.redirect('/?payment=error');
    }
  });

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