import express, { Request, Response, NextFunction } from 'express';
import cors from 'cors';
import helmet from 'helmet';
import morgan from 'morgan';
import cookieParser from 'cookie-parser';
import path from 'path';
import { env } from './config/env';
import { sendError } from './utils/helpers';
import { globalRateLimiter } from './middleware/rateLimiter';
import { xssSanitize } from './middleware/xss';
import { csrfIssue } from './middleware/csrf';
import authRoutes from './routes/auth';
import studentRoutes from './routes/student';
import adminRoutes from './routes/admin';

const app = express();

const allowedOrigins = env.CLIENT_ORIGIN.split(',').map((o) => o.trim());

app.use(
  cors({
    origin: (origin, callback) => {
      if (!origin || allowedOrigins.includes(origin)) {
        return callback(null, true);
      }
      return callback(new Error('Not allowed by CORS'));
    },
    credentials: true,
    methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
    allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token', 'x-xsrf-token'],
  })
);

app.use(helmet());
app.use(morgan(env.NODE_ENV === 'production' ? 'combined' : 'dev'));
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
app.use(cookieParser());
app.use(xssSanitize);
app.use(globalRateLimiter);
app.use(csrfIssue);

app.use('/uploads', express.static(path.join(process.cwd(), env.UPLOAD_DIR)));

app.get('/health', (req: Request, res: Response) => {
  res.json({ success: true, message: 'Server is healthy', data: { uptime: process.uptime() } });
});

app.use('/api/auth', authRoutes);
app.use('/api/student', studentRoutes);
app.use('/api/admin', adminRoutes);

app.use((req: Request, res: Response) => {
  sendError(res, `Route not found: ${req.method} ${req.originalUrl}`, 404);
});

// eslint-disable-next-line @typescript-eslint/no-unused-vars
app.use((err: any, req: Request, res: Response, next: NextFunction) => {
  console.error('Unhandled error:', err);
  if (err && err.type === 'entity.parse.failed') {
    return sendError(res, 'Invalid JSON payload', 400);
  }
  if (err && err.message && err.message.includes('CORS')) {
    return sendError(res, 'CORS policy violation', 403);
  }
  const status = err?.statusCode || err?.status || 500;
  const message =
    env.NODE_ENV === 'production' ? 'Internal server error' : err?.message || 'Internal server error';
  return res.status(status).json({ success: false, message });
});

export default app;
