import 'reflect-metadata';
import { INestApplication } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { Logger } from 'nestjs-pino';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import helmet from 'helmet';
import cookieParser from 'cookie-parser';
import * as express from 'express';
import { AppModule } from './app.module';
import { loadEnv } from './config/env';

/**
 * Builds the fully configured HTTP application (middleware, CORS, swagger)
 * without listening. Shared by main.ts and the e2e test harness so tests run
 * against exactly the production pipeline.
 */
export async function createApp(options: { swagger?: boolean; logger?: boolean } = {}): Promise<INestApplication> {
  const env = loadEnv();
  const app = await NestFactory.create(AppModule, { bufferLogs: true, bodyParser: false, ...(options.logger === false ? { logger: false } : {}) });
  if (options.logger !== false) app.useLogger(app.get(Logger));
  app.setGlobalPrefix(env.API_PREFIX);
  app.use(helmet());
  app.use(cookieParser());
  // ERP documents (IDoc XML, CSV) arrive as text bodies
  app.use(express.text({ type: ['application/xml', 'text/xml', 'text/plain', 'text/csv'], limit: '25mb' }));
  app.use(express.json({ limit: '10mb' }));
  app.use(express.urlencoded({ extended: true, limit: '10mb' }));
  app.enableCors({ origin: env.CORS_ORIGINS.split(',').map((o) => o.trim()), credentials: true, exposedHeaders: ['x-request-id'] });
  app.enableShutdownHooks();

  if (options.swagger !== false) {
    const config = new DocumentBuilder()
      .setTitle('WMS API')
      .setDescription('Multi-tenant warehouse management system API. Auth: Bearer JWT for users, X-API-Key for integrations.')
      .setVersion('1.0')
      .addBearerAuth()
      .addApiKey({ type: 'apiKey', name: 'X-API-Key', in: 'header' }, 'api-key')
      .build();
    const doc = SwaggerModule.createDocument(app, config);
    SwaggerModule.setup(`${env.API_PREFIX}/docs`, app, doc, { swaggerOptions: { persistAuthorization: true } });
  }
  return app;
}
