import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { DocumentBuilder, SwaggerCustomOptions, SwaggerModule } from '@nestjs/swagger';
import { Logger, ValidationPipe } from '@nestjs/common';
import { config } from 'dotenv';
import * as cors from 'cors';
config();
import * as fs from "fs";
import helmet from "helmet";
import * as morgan from 'morgan';
import { ErrorHandler } from './handler/handler.service';
import { IoAdapter } from '@nestjs/platform-socket.io';
import { json } from 'express';
let { SSL, LOCAL_PORT, SSL_CERT, SSL_PRIV_KEY } = process.env

async function bootstrap() {
    let PORT = process.env.LOCAL_PORT ?? 3011;
    let httpsOptions = {}
    if (SSL == "true") {
        httpsOptions = {
            key: fs.readFileSync(String(SSL_PRIV_KEY)),
            cert: fs.readFileSync(String(SSL_CERT)),
        };
    }
    const app = SSL == "true" ? await NestFactory.create(AppModule, { httpsOptions }) : await NestFactory.create(AppModule);
    app.use(cors());
    app.enableCors();

    app.use(helmet()); // helmet is used basicaly for securing a headers
    app.useGlobalFilters(new ErrorHandler());
    app.use(
        json({
            verify: (req: any, res, buf) => {
                req.rawBody = buf;
            },
        }),
    ); // this line is used to get the data in body from webhooks

    // app.useGlobalPipes(new ValidationPipe({ skipMissingProperties: false, transform: true, whitelist: true }));
    
    // Custom morgan tokens for logging body and query
    morgan.token('body', (req: any) => {
        return req.body && Object.keys(req.body).length > 0 
            ? JSON.stringify(req.body) 
            : '';
    });
    morgan.token('query', (req: any) => {
        return Object.keys(req.query).length > 0 
            ? JSON.stringify(req.query) 
            : '';
    });
    
    app.use(morgan(':method :url :status :res[content-length] - :response-time ms\n:body :query'));
    const config = new DocumentBuilder()
        .setTitle('Broker Api Documentation')
        .setDescription('Broker Api Documentation')
        .setVersion('1.0')
        .addBearerAuth({ type: 'http', name: 'token', in: 'header' }, 'access_token')
        .addServer(`http://localhost:${PORT}/`, "Broker local server")
        .build();
    const document = SwaggerModule.createDocument(app, config);
    const customOptions: SwaggerCustomOptions = {
        swaggerOptions: {
        persistAuthorization: true,

        }
    };
    SwaggerModule.setup('docs', app, document, customOptions);

    

    app.useWebSocketAdapter(new IoAdapter(app));
    await app.listen(PORT);
    Logger.log(`Application is running on: ${PORT}`);

}
bootstrap();
