import "reflect-metadata";
import { NestFactory } from "@nestjs/core";
import { ValidationPipe } from "@nestjs/common";
import * as session from "express-session";
import * as passport from "passport";
import { AppModule } from "./app.module";

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Every request body is validated and stripped of unknown fields before it
  // reaches a controller — this is the structural replacement for the old
  // app's complete lack of input validation (src/core/db.php took every
  // $_POST field straight into a SQL string).
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
      forbidNonWhitelisted: true,
      transform: true,
    })
  );

  const sessionSecret = process.env.SESSION_SECRET;
  if (!sessionSecret) {
    throw new Error("SESSION_SECRET must be set (see .env.example)");
  }

  // Whether the session cookie carries the Secure flag. This CANNOT simply
  // follow NODE_ENV: express-session silently declines to send a Secure cookie
  // over a plain-HTTP connection, so a production image served over http://ial
  // issues no cookie at all. Login then returns 200 with a user, no session is
  // established, every later request 403s, and the UI loops back to /login —
  // which is exactly what happened on the first galactus deploy.
  //
  // Leave it ON wherever the app is reached over TLS. Turn it OFF only for a
  // deployment that is HTTP but reached over an already-encrypted transport
  // (the galactus install is Tailscale-only, so WireGuard encrypts the wire).
  // Behind a TLS-terminating proxy, set trust proxy instead of turning this off.
  // An EMPTY value counts as unset, not as "false". Compose interpolation turns
  // an absent `${SESSION_COOKIE_SECURE:-}` into the empty string, so testing
  // `!== undefined` here would silently drop the Secure flag on any deployment
  // that merely passes the variable through without setting it.
  const cookieSecureRaw = process.env.SESSION_COOKIE_SECURE;
  const cookieSecure = cookieSecureRaw
    ? cookieSecureRaw === "true"
    : process.env.NODE_ENV === "production";

  app.use(
    session({
      secret: sessionSecret,
      resave: false,
      saveUninitialized: false,
      cookie: {
        httpOnly: true,
        secure: cookieSecure,
        maxAge: 1000 * 60 * 60 * 8, // 8-hour session, matches a staff workday
      },
    })
  );
  app.use(passport.initialize());
  app.use(passport.session());

  app.enableCors({ credentials: true, origin: process.env.WEB_ORIGIN ?? "http://localhost:3000" });

  const port = process.env.PORT ? Number(process.env.PORT) : 3001;
  await app.listen(port);
}

bootstrap();
