// CODING-RULES §09 (PGD-OBS-001): tracing PRECISA ser o primeiro import.
// OTel NodeSDK faz monkey-patch dos módulos node:http/pg/etc. antes do Nest.
import './tracing';

import { NestFactory } from '@nestjs/core';
import { VersioningType, type INestApplication } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Logger } from 'nestjs-pino';
import helmet from 'helmet';
import compression from 'compression';
import { AppModule } from './app/app.module';
import type { Env } from './app/config/env.schema';

async function bootstrap(): Promise<void> {
  const app: INestApplication = await NestFactory.create(AppModule, {
    bufferLogs: true, // logs do boot vão pro Pino quando ele subir
  });

  // Logger Pino global (substitui o NestLogger padrão).
  app.useLogger(app.get(Logger));

  const config = app.get(ConfigService) as ConfigService<Env, true>;

  // CORS — origens vindas do EnvSchema (já parseadas em array).
  app.enableCors({
    origin: config.get('CORS_ORIGINS', { infer: true }),
    credentials: true,
    methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
    allowedHeaders: [
      'Content-Type',
      'Authorization',
      'X-Request-Id',
      'X-Correlation-Id',
      'Idempotency-Key',
    ],
    exposedHeaders: ['X-Request-Id'],
    maxAge: 600,
  });

  // Helmet — headers de segurança canônicos.
  app.use(
    helmet({
      contentSecurityPolicy: false, // SPA serve CSP via Nginx; API JSON dispensa.
      crossOriginEmbedderPolicy: false,
    }),
  );

  // Compression — gzip/br.
  app.use(compression());

  // Versionamento via URI: /api/v1/...
  const globalPrefix = config.get('API_GLOBAL_PREFIX', { infer: true });
  const apiVersion = config.get('API_VERSION', { infer: true }).replace(/^v/, '');
  app.setGlobalPrefix(globalPrefix);
  app.enableVersioning({
    type: VersioningType.URI,
    defaultVersion: apiVersion,
    prefix: 'v',
  });

  // Graceful shutdown — Nest emite SIGTERM/SIGINT → hooks rodam → dreno de conexões.
  // Compose: stop_grace_period: 30s + HAProxy drain 30s (CODING-RULES §18).
  app.enableShutdownHooks();

  const port = config.get('API_PORT', { infer: true });
  const host = config.get('API_HOST', { infer: true });

  await app.listen(port, host);

  app
    .get(Logger)
    .log(
      `SAR API pronta em http://${host}:${port}/${globalPrefix}/${apiVersion === '0' ? '' : `v${apiVersion}`}`,
      'Bootstrap',
    );
}

bootstrap().catch((err) => {
  // Antes do Logger Pino estar disponível, qualquer erro de boot cai aqui.
  console.error('[bootstrap] crash fatal — encerrando:', err);
  process.exit(1);
});
