/**
 * Routes API optimisées avec cache et pagination
 */

import { Router } from 'express';
import { requireAuth, requireRole } from './auth';
import { storage } from './storage';
import { 
  performanceCache, 
  getAdminStatsOptimized, 
  createPaginatedQuery,
  PaginationOptions,
  PaginatedResult 
} from './optimizations';

const router = Router();

/**
 * Route optimisée pour les statistiques admin
 */
router.get('/api/admin/stats', requireAuth, requireRole('admin'), async (req, res) => {
  try {
    const stats = await getAdminStatsOptimized();
    
    // Headers de cache
    res.set({
      'Cache-Control': 'public, max-age=300', // 5 minutes
      'ETag': `admin-stats-${Date.now()}`
    });
    
    res.json(stats);
  } catch (error) {
    console.error("Get optimized admin stats error:", error);
    res.status(500).json({ message: "Erreur lors de la récupération des statistiques" });
  }
});

/**
 * Route optimisée pour les utilisateurs avec pagination
 */
router.get('/api/admin/users/paginated', requireAuth, requireRole('admin'), async (req, res) => {
  try {
    const {
      page = 1,
      limit = 20,
      sortBy = 'createdAt',
      sortOrder = 'desc',
      role,
      verified
    } = req.query;

    const paginationOptions: PaginationOptions = {
      page: Number(page),
      limit: Math.min(Number(limit), 100), // Max 100 items par page
      sortBy: sortBy as string,
      sortOrder: sortOrder as 'asc' | 'desc'
    };

    // Construire les filtres
    const filters: any = {};
    if (role && typeof role === 'string') filters.role = role;
    if (verified !== undefined) filters.verified = verified === 'true';

    // Cache key unique pour cette requête
    const cacheKey = `admin_users:${JSON.stringify({ ...paginationOptions, ...filters })}`;
    
    // Vérifier le cache (2 minutes pour les utilisateurs)
    const cached = performanceCache.get(cacheKey);
    if (cached !== null) {
      res.set('X-Cache', 'HIT');
      return res.json(cached);
    }

    // Récupérer le total pour la pagination
    const totalQuery = storage.db
      .select({ count: storage.sql`count(*)` })
      .from(storage.users);

    if (filters.role) {
      totalQuery.where(storage.eq(storage.users.role, filters.role));
    }

    const totalResult = await totalQuery;
    const total = Number(totalResult[0]?.count || 0);

    // Récupérer les données paginées
    let baseQuery = storage.db
      .select({
        id: storage.users.id,
        name: storage.users.name,
        email: storage.users.email,
        phone: storage.users.phone,
        role: storage.users.role,
        active: storage.users.active,
        createdAt: storage.users.createdAt,
        pharmacy: {
          id: storage.pharmacies.id,
          name: storage.pharmacies.name,
          verified: storage.pharmacies.verified,
          address: storage.pharmacies.address
        },
        courier: {
          id: storage.couriers.id,
          active: storage.couriers.active,
          vehicleType: storage.couriers.vehicleType
        }
      })
      .from(storage.users)
      .leftJoin(storage.pharmacies, storage.eq(storage.users.id, storage.pharmacies.userId))
      .leftJoin(storage.couriers, storage.eq(storage.users.id, storage.couriers.userId));

    if (filters.role) {
      baseQuery = baseQuery.where(storage.eq(storage.users.role, filters.role));
    }

    // Appliquer la pagination et le tri
    const { query } = createPaginatedQuery(baseQuery, paginationOptions);
    const users = await query;

    // Formater les résultats
    const formattedUsers = users.map((user: any) => ({
      ...user,
      verified: user.role === 'pharmacy' ? user.pharmacy?.verified : 
                user.role === 'courier' ? user.courier?.active : true
    }));

    const result: PaginatedResult<any> = {
      data: formattedUsers,
      pagination: {
        page: paginationOptions.page,
        limit: paginationOptions.limit,
        total,
        totalPages: Math.ceil(total / paginationOptions.limit),
        hasNext: paginationOptions.page < Math.ceil(total / paginationOptions.limit),
        hasPrev: paginationOptions.page > 1
      }
    };

    // Mettre en cache
    performanceCache.set(cacheKey, result, 120); // 2 minutes

    res.set({
      'X-Cache': 'MISS',
      'X-Total-Count': total.toString(),
      'X-Page': paginationOptions.page.toString()
    });

    res.json(result);
  } catch (error) {
    console.error("Get paginated users error:", error);
    res.status(500).json({ message: "Erreur lors de la récupération des utilisateurs" });
  }
});

/**
 * Route optimisée pour les métriques temps réel
 */
router.get('/api/admin/realtime', requireAuth, requireRole('admin'), async (req, res) => {
  try {
    // Pas de cache pour les données temps réel
    const [ordersStats, financialStats, activity] = await Promise.all([
      storage.getOrdersStats(),
      storage.getFinancialStats(),
      storage.getRecentActivity()
    ]);

    const result = {
      orders: ordersStats,
      financial: financialStats,
      activity: activity,
      timestamp: new Date().toISOString()
    };

    res.set({
      'Cache-Control': 'no-cache, must-revalidate',
      'X-Data-Freshness': 'realtime'
    });

    res.json(result);
  } catch (error) {
    console.error("Get realtime stats error:", error);
    res.status(500).json({ message: "Erreur lors de la récupération des données temps réel" });
  }
});

/**
 * Route pour vider le cache (admin uniquement)
 */
router.post('/api/admin/cache/clear', requireAuth, requireRole('admin'), async (req, res) => {
  try {
    const { pattern } = req.body;
    
    if (pattern) {
      performanceCache.clear(pattern);
    } else {
      performanceCache.clear();
    }

    res.json({ 
      message: 'Cache nettoyé avec succès',
      pattern: pattern || 'all'
    });
  } catch (error) {
    console.error("Clear cache error:", error);
    res.status(500).json({ message: "Erreur lors du nettoyage du cache" });
  }
});

/**
 * Route pour les statistiques de cache
 */
router.get('/api/admin/cache/stats', requireAuth, requireRole('admin'), async (req, res) => {
  try {
    const stats = {
      size: performanceCache.size(),
      timestamp: new Date().toISOString()
    };

    res.json(stats);
  } catch (error) {
    console.error("Get cache stats error:", error);
    res.status(500).json({ message: "Erreur lors de la récupération des stats cache" });
  }
});

/**
 * Middleware de compression pour les réponses JSON
 */
router.use((req, res, next) => {
  // Compression automatique des réponses > 1KB
  if (req.headers['accept-encoding']?.includes('gzip')) {
    res.set('Content-Encoding', 'gzip');
  }
  next();
});

/**
 * Middleware de monitoring des performances
 */
router.use((req, res, next) => {
  const start = Date.now();
  
  res.on('finish', () => {
    const duration = Date.now() - start;
    const route = `${req.method} ${req.route?.path || req.path}`;
    
    // Log des requêtes lentes
    if (duration > 1000) {
      console.warn(`[SLOW API] ${route}: ${duration}ms`);
    }
    
    // Headers de performance
    res.set({
      'X-Response-Time': `${duration}ms`,
      'X-Optimized': 'true'
    });
  });
  
  next();
});

export default router;