const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
const compression = require('compression');
const rateLimit = require('express-rate-limit');
const path = require('path');
const config = require('./config');
const { errorHandler, notFound } = require('./middlewares/errorHandler');

const app = express();

// Security middleware - configure helmet to allow cross-origin resource sharing for static files
app.use(helmet({
  crossOriginResourcePolicy: { policy: "cross-origin" },
  crossOriginEmbedderPolicy: false
}));

// CORS configuration
app.use(cors({
  origin: config.cors.origin,
  credentials: true
}));

// Rate limiting - More lenient for development, stricter in production
// const limiter = rateLimit({
//   windowMs: 15 * 60 * 1000, // 15 minutes
//   max: config.env === 'development' ? 1000 : 100, // Higher limit for development
//   standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
//   legacyHeaders: false, // Disable the `X-RateLimit-*` headers
//   message: 'Too many requests from this IP, please try again later.',
//   skipSuccessfulRequests: false, // Count successful requests too
// });
// app.use(limiter);

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

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

// Logging middleware
if (config.env === 'development') {
  app.use(morgan('dev'));
} else {
  app.use(morgan('combined'));
}

// Serve static files (drawings/uploads) with CORS headers
// Add explicit CORS middleware for /uploads route
app.use('/uploads', (req, res, next) => {
  const origin = req.headers.origin;

  // Determine allowed origin - use same logic as main CORS config
  let allowedOrigin = '*';
  if (config.cors.origin === true) {
    // Allow any origin in development
    allowedOrigin = origin || '*';
  } else if (Array.isArray(config.cors.origin)) {
    // Check if origin is in allowed list
    if (origin && config.cors.origin.includes(origin)) {
      allowedOrigin = origin;
    } else {
      allowedOrigin = config.cors.origin[0] || '*';
    }
  } else if (config.cors.origin) {
    // Single origin
    allowedOrigin = config.cors.origin;
  } else if (origin) {
    // Fallback to request origin
    allowedOrigin = origin;
  }

  // Set CORS headers
  res.setHeader('Access-Control-Allow-Origin', allowedOrigin);
  res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  res.setHeader('Access-Control-Allow-Credentials', 'true');
  res.setHeader('Access-Control-Expose-Headers', 'Content-Length, Content-Type');

  // Handle preflight OPTIONS request
  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }

  next();
});

// Create a custom static file handler with additional CORS headers
const staticOptions = {
  setHeaders: (res, filePath) => {
    const origin = res.req.headers.origin;

    // Determine allowed origin
    let allowedOrigin = '*';
    if (config.cors.origin === true) {
      allowedOrigin = origin || '*';
    } else if (Array.isArray(config.cors.origin)) {
      if (origin && config.cors.origin.includes(origin)) {
        allowedOrigin = origin;
      } else {
        allowedOrigin = config.cors.origin[0] || '*';
      }
    } else if (config.cors.origin) {
      allowedOrigin = config.cors.origin;
    } else if (origin) {
      allowedOrigin = origin;
    }

    // Ensure CORS headers are set (in case middleware didn't run)
    res.setHeader('Access-Control-Allow-Origin', allowedOrigin);
    res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    res.setHeader('Access-Control-Allow-Credentials', 'true');
  }
};

app.use('/uploads', express.static(path.join(__dirname, 'uploads'), staticOptions));

// Health check endpoint
app.get('/health', (req, res) => {
  res.json({
    success: true,
    message: 'Server is running',
    timestamp: new Date().toISOString()
  });
});

// API routes
const routes = require('./routes');
app.use(`${config.api.prefix}/${config.api.version}`, routes);

// 404 handler
app.use(notFound);

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

module.exports = app;

