/* eslint-disable no-console */
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import morgan from 'morgan';
import path from 'path';
import dotenv from 'dotenv';
import expressLayouts from 'express-ejs-layouts';
import { assertDatabaseConnection } from './config/database';
import { HomeController } from './controllers/homeController';
import { authRateLimiter } from './middleware/rateLimit';
import { validateBasicAuth } from './middleware/basicAuth';

// Load environment variables
dotenv.config();

const app = express();
const PORT = process.env.PORT || 3000;

// Trust proxy - required when behind reverse proxy (Apache)
// This allows Express to properly handle X-Forwarded-For and other proxy headers
app.set('trust proxy', true);

// Middleware
app.use(helmet());
app.use(cors());
app.use(morgan('combined'));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Set view engine to EJS
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, '../views'));
app.use(expressLayouts);
app.set('layout', 'layouts/main');

// Serve static files (non-download assets only). Keep after dynamic download handler for /downloads
app.use('/css', express.static(path.join(__dirname, './styles')));
app.use('/js', express.static(path.join(__dirname, '../public/js')));
app.use('/images', express.static(path.join(__dirname, '../public/images')));
app.use('/fonts', express.static(path.join(__dirname, '../public/fonts')));

// Pre-validate credentials once so rate limiter and controller share the result
app.use((req, _res, next) => {
  validateBasicAuth(req);
  next();
});

// Home route
app.get('/', HomeController.index);
app.get('/*', authRateLimiter, HomeController.browseOrDownload);

// 404 handler
app.use('*', (req, res) => {
  res.status(404).render('pages/404', {
    title: 'Page Not Found',
  });
});

// Error handler
app.use((err: Error, req: express.Request, res: express.Response) => {
  console.error(err.stack);
  res.status(500).render('pages/500', {
    title: 'Internal Server Error',
    error:
      process.env.NODE_ENV === 'development'
        ? err.message
        : 'Something went wrong!',
  });
});

app.listen(PORT, async () => {
  try {
    await assertDatabaseConnection();
  } catch (err) {
    console.error('Database connection failed:', err);
  }
});
