import Fastify from 'fastify';
import cors from '@fastify/cors';
import cookie from '@fastify/cookie';
import helmet from '@fastify/helmet';
import rateLimit from '@fastify/rate-limit';
import authenticatePlugin from './plugins/authenticate.js';
import { registerErrorHandler } from './middlewares/errorHandler.js';
import { registerRoutes } from './routes/index.js';
import { registerActivityLogHandler } from './events/handlers/activityLog.handler.js';
import { logger } from './utils/logger.js';

export async function buildApp() {
  const app = Fastify({
    logger: false,
    // Needed for request.protocol to reflect the original scheme (https)
    // when running behind a reverse proxy that terminates TLS — otherwise
    // Fastify only sees the proxy's plain-http connection to this process.
    trustProxy: true,
  });

  // Standard security headers (X-Content-Type-Options, X-Frame-Options,
  // HSTS, etc.) — this is a JSON API with no server-rendered HTML, so the
  // default CSP (meant for pages serving their own scripts/styles) is
  // switched off rather than fighting it for no benefit here.
  await app.register(helmet, { contentSecurityPolicy: false });

  // Global ceiling against brute-force/scraping in general; the login route
  // gets its own much stricter limit below since that's the one endpoint
  // where "try many times fast" is actually an attack (password guessing),
  // not just heavy usage. Keyed by IP, so an office with many staff sharing
  // one NAT'd/proxied IP shares this same budget — kept generous enough
  // (each page load fires several requests at once) to absorb that.
  await app.register(rateLimit, {
    max: 1000,
    timeWindow: '1 minute',
  });

  // Allow any origin, in every environment — reflects the request's own
  // Origin header (fastify/cors's `true` behavior) rather than a fixed
  // allow-list, so it works with credentials too.
  await app.register(cors, {
    origin: true,
    methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'],
    credentials: true,
  });

  await app.register(cookie);

  await app.register(authenticatePlugin);

  registerErrorHandler(app);

  registerActivityLogHandler();

  await registerRoutes(app);

  return app;
}
