import { INestApplication, ValidationPipe } from '@nestjs/common';
import { HttpAdapterHost, NestFactory } from '@nestjs/core';

import { ConfigService } from '@nestjs/config';
import * as bodyParser from 'body-parser';
import cookieParser from 'cookie-parser';
import { Logger, LoggerErrorInterceptor } from 'nestjs-pino';
import { AppModule } from './app.module';
import { AllExceptionFilter } from './fliters/all-exception.filter';
import { RequestCountInterceptor } from './interceptors/request-count.interceptor';
import { setupKernel } from './kernel';
import { AlertSignalService } from './modules/alert/alert-signal.service';
import { setupSwagger } from './swagger';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, { bufferLogs: true });
  const httpAdapterHost = app.get(HttpAdapterHost);
  //* A4 신호 수집(M2 §D3) — 필터(분자)와 인터셉터(분모)가 같은 인스턴스를 쓴다.
  const alertSignals = app.get(AlertSignalService);

  setupCors(app);
  app.use(bodyParser.json({ limit: '10mb' }));
  app.use(bodyParser.urlencoded({ limit: '10mb', extended: true }));
  app.use(cookieParser());
  // app.useGlobalPipes(new ValidationPipe({ transform: true }));
  app.useGlobalFilters(new AllExceptionFilter(httpAdapterHost, alertSignals));

  app.useLogger(app.get(Logger));
  app.useGlobalInterceptors(
    new LoggerErrorInterceptor(),
    new RequestCountInterceptor(alertSignals),
  );

  process.env.NODE_ENV !== 'production' && setupSwagger(app);
  if (process.platform === 'win32') {
    await setupKernel();
  }

  //* 대용량 엑셀 스트리밍 다운로드(분석관리 등 10만행+)가 Node 기본 requestTimeout(5분)에
  //*   "request aborted"로 끊기던 문제 → 30분으로 상향. headersTimeout(기본 60초)은 유지.
  const httpServer = app.getHttpServer();
  httpServer.requestTimeout = 30 * 60 * 1000;

  //* 기본값은 7200 그대로. PORT 가 있을 때만 그 값을 쓴다 — 같은 머신에서 worktree별
  //* 인스턴스를 동시에 띄우려면 포트가 하드코딩돼 있으면 안 된다. 미설정/비수치면 7200.
  const port = Number(process.env.PORT) || 7200;
  await app.listen(port);
}

bootstrap();

function setupCors(app: INestApplication) {
  const configService = app.get(ConfigService);
  const rawOrigins = configService.get<string>('allowOrigins');
  if (!rawOrigins) {
    return;
  }

  const origins = rawOrigins.split(',');
  app.enableCors({
    origin: origins,
    credentials: true,
    exposedHeaders: ['Content-Disposition'],
  });
}
