import 'dotenv/config';
import express from 'express';
import cors from 'cors';
import path from 'path';
import { fileURLToPath } from 'url';
import { log } from './config/logger.js';
import requestResponseLogger from './middleware/logging.js';
import { initDatabase } from './config/database.js';
import { initMailer } from './config/mailer.js';
import authRoutes from './routes/auth.js';
import roomRoutes from './routes/rooms.js';
import recordingRoutes from './routes/recordings.js';
import adminRoutes from './routes/admin.js';
import brandingRoutes from './routes/branding.js';
import federationRoutes, { wellKnownHandler } from './routes/federation.js';
import calendarRoutes from './routes/calendar.js';
import caldavRoutes from './routes/caldav.js';
import notificationRoutes from './routes/notifications.js';
import oauthRoutes from './routes/oauth.js';
import analyticsRoutes from './routes/analytics.js';
import { startFederationSync } from './jobs/federationSync.js';
import { startCalendarReminders } from './jobs/calendarReminders.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

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

// Trust proxy - configurable via TRUST_PROXY env var (default: 1 = one local reverse proxy)
// Use a number to trust that many hops, or a string like 'loopback' / an IP/CIDR.
const rawTrustProxy = process.env.TRUST_PROXY ?? 'loopback';
const trustProxy = /^\d+$/.test(rawTrustProxy) ? parseInt(rawTrustProxy, 10) : rawTrustProxy;
app.set('trust proxy', trustProxy);

// ── Security headers ───────────────────────────────────────────────────────
app.use((req, res, next) => {
  res.setHeader('X-Content-Type-Options', 'nosniff');
  res.setHeader('X-Frame-Options', 'SAMEORIGIN');
  res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
  res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');
  if (process.env.NODE_ENV === 'production') {
    res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
  }
  next();
});

// Middleware
// M10: restrict CORS in production; deny cross-origin by default
const corsOptions = process.env.APP_URL
  ? { origin: process.env.APP_URL, credentials: true }
  : { origin: false };
app.use(cors(corsOptions));
// Global JSON body limit kept tight as a hardening measure. The BBB learning
// analytics callback can send much larger payloads, so it is excluded here and
// gets its own, more generous limit on the route itself (see routes/analytics.js).
const jsonParser = express.json({ limit: '100kb' });
app.use((req, res, next) => {
  if (req.path.startsWith('/api/analytics/callback/')) return next();
  return jsonParser(req, res, next);
});
// Request/Response logging (filters sensitive fields)
app.use(requestResponseLogger);

// Initialize database & start server
async function start() {
  await initDatabase();
  initMailer();

  // Serve uploaded files (avatars are served via /api/auth/avatar/:filename)
  const uploadsPath = path.join(__dirname, '..', 'uploads');
  app.use('/uploads/branding', express.static(path.join(uploadsPath, 'branding')));
  // Presentations are served via /api/rooms/presentations/:filename?token=… (HMAC-protected)

  // API Routes
  app.use('/api/auth', authRoutes);
  app.use('/api/rooms', roomRoutes);
  app.use('/api/recordings', recordingRoutes);
  app.use('/api/admin', adminRoutes);
  app.use('/api/branding', brandingRoutes);
  app.use('/api/federation', federationRoutes);
  app.use('/api/calendar', calendarRoutes);
  app.use('/api/notifications', notificationRoutes);
  app.use('/api/oauth', oauthRoutes);
  app.use('/api/analytics', analyticsRoutes);
  // CalDAV — mounted outside /api so calendar clients use a clean path
  app.use('/caldav', caldavRoutes);
  // Mount calendar federation receive also under /api/federation for remote instances
  app.use('/api/federation', calendarRoutes);
  app.get('/.well-known/redlight', wellKnownHandler);

  // ── CalDAV service discovery (RFC 6764) ──────────────────────────────────
  // Clients probe /.well-known/caldav then PROPFIND / before they know the
  // real CalDAV mount point.  Redirect them to /caldav/ for all HTTP methods.
  app.all('/.well-known/caldav', (req, res) => {
    res.redirect(301, '/caldav/');
  });
  // Some clients (e.g. Thunderbird) send PROPFIND / directly at the server root.
  // Express doesn't register non-standard methods, so intercept via middleware.
  app.use('/', (req, res, next) => {
    if (req.method === 'PROPFIND' && req.path === '/') {
      return res.redirect(301, '/caldav/');
    }
    next();
  });

  // Serve static files in production
  if (process.env.NODE_ENV === 'production') {
    app.use(express.static(path.join(__dirname, '..', 'dist')));
    app.get('/*splat', (req, res) => {
      res.sendFile(path.join(__dirname, '..', 'dist', 'index.html'));
    });
  }

  app.listen(PORT, () => {
    log.server.info(`Redlight server running on http://localhost:${PORT}`);
  });

  // Start periodic federation sync job (checks remote room settings every 60s)
  startFederationSync();
  // Start calendar reminder job (sends in-app + browser notifications before events)
  startCalendarReminders();
}

start().catch(err => {
  log.server.error(`Failed to start server: ${err.message}`);
  process.exit(1);
});
