import { webcrypto } from 'crypto';
import { NestFactory } from '@nestjs/core';

// Polyfill crypto for @nestjs/typeorm
if (!global.crypto) {
  global.crypto = webcrypto as any;
}
//import { Logger } from '@nestjs/common';
import { Logger, ValidationPipe } from '@nestjs/common';
import { NestExpressApplication } from '@nestjs/platform-express';
import { utilities, WinstonModule } from 'nest-winston';
import winston from 'winston';
import cookieParser from 'cookie-parser';

import { AppModule } from './app.module';
import { ApiDocumentation } from './documentation';
import { extractSubdomain, LoggingInterceptor } from './common';

function getLogger() {
  return process.env.WINSTON_ENABLED === 'true'
    ? WinstonModule.createLogger({
        level: 'debug',
        transports: [
          new winston.transports.Console({
            format: winston.format.combine(
              winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
              utilities.format.nestLike(process.env.APPLICATION_NAME, { colors: true, prettyPrint: true }),
            ),
          }),
        ],
      })
    : undefined;
}

async function bootstrap() {
  if (process.env.NEW_RELIC_ENABLED === 'true') {
    // eslint-disable-next-line @typescript-eslint/no-require-imports
    require('newrelic');
  }

  const app = await NestFactory.create<NestExpressApplication>(AppModule, { rawBody: true, logger: getLogger() });
  app.enableCors({
    origin: process.env['FRONTEND_URL'] || 'http://localhost:3000',
    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
    credentials: true,
    allowedHeaders: ['Content-Type', 'Authorization', 'X-CSRF-Token']
  });

  app.set('trust proxy', true);
  app.use(cookieParser());
  app.use(extractSubdomain);
  app.setGlobalPrefix('api');

  //Global validation
  // app.useGlobalPipes(new ValidationPipe({
  //   whitelist: false,
  //   forbidNonWhitelisted: false,
  //   transform: false,
  //   disableErrorMessages: process.env['NODE_ENV'] === 'production'
  // }));

  app.useGlobalInterceptors(new LoggingInterceptor());

  ApiDocumentation.configure(app);

  const logger = new Logger('main');

  process.on('uncaughtException', (error) => {
    logger.error(`Uncaught Exception`, error.stack);
  });

  await app.listen(process.env.APPLICATION_PORT, '127.0.0.1');

  logger.log(`Application is running on: ${await app.getUrl()}`);
  logger.log(`Application version is: ${process.env.npm_package_version}`);
}

bootstrap();
