const express = require('express');
const compression = require('compression');
const { applySecurityMiddleware } = require('./middleware/security.js');
const requestLogger = require('./middleware/requestLogger.js');
const metricsMiddleware = require('./middleware/metrics.js');
const { errorHandler, notFoundHandler } = require('./middleware/errorHandler.js');
const { createSessionMiddleware } = require('./config/session.js');
const { languageMiddleware } = require('./middleware/language.js');
const { setupSwagger, generatePostmanCollection } = require('./config/swagger.js');

/**
 * Create and configure Express application
 */
const createApp = () => {
  const app = express();

  // Setup Swagger API documentation (skip in test environment)
  if (process.env.NODE_ENV !== 'test') {
    setupSwagger(app);
  }

  // Apply security middleware (helmet, cors, rate limiting)
  applySecurityMiddleware(app);

  // Body parsing middleware
  app.use(express.json({ limit: '10mb' }));
  app.use(express.urlencoded({ extended: true, limit: '10mb' }));

  // Compression middleware
  app.use(compression());

  // Session middleware with Redis store (skip in test environment)
  if (process.env.NODE_ENV !== 'test') {
    app.use(createSessionMiddleware());
  }

  // Request logging middleware
  app.use(requestLogger);

  // Metrics collection middleware
  app.use(metricsMiddleware);

  // Language detection middleware
  app.use(languageMiddleware);

  // Response formatter middleware (converts all responses to unified format)
  const responseFormatter = require('./middleware/responseFormatter');
  app.use(responseFormatter);

  // Serve static files from uploads directory
  const path = require('path');
  const config = require('./config/env');
  app.use('/uploads', express.static(path.resolve(config.upload.path)));

  // Health check and metrics endpoints
  const healthRoutes = require('./routes/healthRoutes');
  app.use('/health', healthRoutes);
  app.get('/metrics', (req, res, next) => {
    // Forward to health routes metrics endpoint
    req.url = '/metrics';
    healthRoutes(req, res, next);
  });

  // Postman collection export endpoint
  app.get('/api-docs/postman', (req, res) => {
    const collection = generatePostmanCollection();
    res.setHeader('Content-Type', 'application/json');
    res.setHeader('Content-Disposition', 'attachment; filename="overseas-appointment-api.postman_collection.json"');
    res.send(JSON.stringify(collection, null, 2));
  });

  // API routes
  const authRoutes = require('./routes/authRoutes');
  app.use('/api/v1/auth', authRoutes);

  const userRoutes = require('./routes/userRoutes');
  app.use('/api/v1/users', userRoutes);

  const serviceRoutes = require('./routes/serviceRoutes');
  app.use('/api/v1', serviceRoutes);

  const appointmentRoutes = require('./routes/appointmentRoutes');
  app.use('/api/v1/appointments', appointmentRoutes);

  const notificationRoutes = require('./routes/notificationRoutes');
  app.use('/api/v1/notifications', notificationRoutes);

  const invitationRoutes = require('./routes/invitationRoutes');
  app.use('/api/v1/invitations', invitationRoutes);

  const commissionRoutes = require('./routes/commissionRoutes');
  app.use('/api/v1/commissions', commissionRoutes);

  const withdrawalRoutes = require('./routes/withdrawalRoutes');
  app.use('/api/v1/withdrawals', withdrawalRoutes);

  const uploadRoutes = require('./routes/uploadRoutes');
  app.use('/api/v1/upload', uploadRoutes);

  const qrcodeRoutes = require('./routes/qrcodeRoutes');
  app.use('/api/v1/qrcode', qrcodeRoutes);

  const adminAuthRoutes = require('./routes/adminAuthRoutes');
  app.use('/api/v1/admin', adminAuthRoutes);

  const adminUserRoutes = require('./routes/adminUserRoutes');
  app.use('/api/v1/admin/users', adminUserRoutes);

  const adminAppointmentRoutes = require('./routes/adminAppointmentRoutes');
  app.use('/api/v1/admin/appointments', adminAppointmentRoutes);

  const adminWithdrawalRoutes = require('./routes/adminWithdrawalRoutes');
  app.use('/api/v1/admin/withdrawals', adminWithdrawalRoutes);

  const adminServiceRoutes = require('./routes/adminServiceRoutes');
  app.use('/api/v1/admin/services', adminServiceRoutes);

  const adminStatisticsRoutes = require('./routes/adminStatisticsRoutes');
  app.use('/api/v1/admin/statistics', adminStatisticsRoutes);

  const adminTranslationRoutes = require('./routes/adminTranslationRoutes');
  app.use('/api/v1/admin/translations', adminTranslationRoutes);

  const adminUploadRoutes = require('./routes/adminUploadRoutes');
  app.use('/api/v1/admin/upload', adminUploadRoutes);

  const configRoutes = require('./routes/configRoutes');
  app.use('/api/v1/config', configRoutes);

  const homeRoutes = require('./routes/homeRoutes');
  app.use('/api/v1/home', homeRoutes);

  const bookingRuleRoutes = require('./routes/bookingRuleRoutes');
  app.use('/api/v1/booking-rules', bookingRuleRoutes);

  const adminConfigRoutes = require('./routes/adminConfigRoutes');
  app.use('/api/v1/admin/config', adminConfigRoutes);

  const adminHomeRoutes = require('./routes/adminHomeRoutes');
  app.use('/api/v1/admin/home', adminHomeRoutes);

  const adminCategoryRoutes = require('./routes/adminCategoryRoutes');
  app.use('/api/v1/admin/categories', adminCategoryRoutes);

  const adminNotificationRoutes = require('./routes/adminNotificationRoutes');
  app.use('/api/v1/admin/notifications', adminNotificationRoutes);

  const adminPaymentOrderRoutes = require('./routes/adminPaymentOrderRoutes');
  app.use('/api/v1/admin/payment-orders', adminPaymentOrderRoutes);

  const adminCommissionRoutes = require('./routes/adminCommissionRoutes');
  app.use('/api/v1/admin/commissions', adminCommissionRoutes);

  const adminBookingRuleRoutes = require('./routes/adminBookingRuleRoutes');
  app.use('/api/v1/admin/booking-rules', adminBookingRuleRoutes);

  // 404 handler
  app.use(notFoundHandler);

  // Global error handler (must be last)
  app.use(errorHandler);

  return app;
};

module.exports = createApp;
