import express from 'express';
import helmet from 'helmet';
import cors from 'cors';
import cookieParser from 'cookie-parser';
import morgan from 'morgan';
import rateLimit from 'express-rate-limit';

import { env, isProd } from './config/env.js';
import apiRoutes from './routes/index.js';
import { handleWebhook } from './controllers/payment.controller.js';
import { errorHandler, notFoundHandler } from './middleware/error.middleware.js';

const app = express();

app.set('trust proxy', 1);

// --- Security headers (OWASP) ---
app.use(
  helmet({
    crossOriginResourcePolicy: { policy: 'cross-origin' },
    contentSecurityPolicy: false, // API only; CSP handled by frontend host
  })
);

// --- CORS ---
app.use(
  cors({
    origin: env.clientUrl,
    credentials: true,
  })
);

// --- Stripe webhook needs the raw body, mount BEFORE json parser ---
app.post('/api/payments/webhook', express.raw({ type: 'application/json' }), handleWebhook);

// --- Body parsers ---
app.use(express.json({ limit: '1mb' }));
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());

if (!isProd) app.use(morgan('dev'));

// --- Rate limiting ---
const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 600,
  standardHeaders: true,
  legacyHeaders: false,
});
app.use('/api', apiLimiter);

const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 40,
  message: { success: false, message: 'Too many attempts, please try again later' },
});
app.use('/api/auth/login', authLimiter);
app.use('/api/auth/register', authLimiter);
app.use('/api/auth/google', authLimiter);
app.use('/api/auth/verify-email', authLimiter);
app.use('/api/auth/resend-otp', authLimiter);
app.use('/api/auth/forgot-password', authLimiter);
app.use('/api/auth/reset-password', authLimiter);

// --- Routes ---
app.use('/api', apiRoutes);

// --- 404 + errors ---
app.use(notFoundHandler);
app.use(errorHandler);

export default app;
