import './tracing'

import { pinoLoggerConfig } from '@backend/logging'
import helmet from '@fastify/helmet'
import { ValidationPipe } from '@nestjs/common'
import { NestFactory } from '@nestjs/core'
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify'
import { IoAdapter } from '@nestjs/platform-socket.io'
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'
import { writeFileSync } from 'node:fs'
import { Logger, PinoLogger } from 'nestjs-pino'
import { join } from 'node:path'
import { StorageDriver, initializeTransactionalContext } from 'typeorm-transactional'
import * as packageInfo from '../package.json'
import { AppModule } from './app/app.module'

const globalPrefix = 'api'

const logger = new Logger(new PinoLogger({ pinoHttp: pinoLoggerConfig }), {})

async function bootstrap() {
	initializeTransactionalContext({ storageDriver: StorageDriver.AUTO })

	const app = await NestFactory.create<NestFastifyApplication>(
		AppModule,
		new FastifyAdapter({ disableRequestLogging: true, logger: false }),
		{ bufferLogs: true, logger },
	)

	app.setGlobalPrefix(globalPrefix)

	const config = new DocumentBuilder()
		.setTitle('KADiCon API')
		.setVersion(packageInfo.version)
		.addBearerAuth()
		.addBasicAuth()
		.build()

	const document = SwaggerModule.createDocument(app, config)
	SwaggerModule.setup(globalPrefix, app, document)

	if (process.argv.includes('--openapi')) {
		const outputPath = join(__dirname, './openapi.json')

		writeFileSync(outputPath, JSON.stringify(document, null, 2))
		console.log(`✅ OpenAPI spec written to ${outputPath}`)

		// eslint-disable-next-line unicorn-x/no-process-exit
		process.exit(0)
	}

	app.useLogger(app.get(Logger))

	await app.register(helmet)
	app.enableCors({ origin: '*', methods: '*' })

	app.useGlobalPipes(
		new ValidationPipe({
			transform: true,
			transformOptions: {
				enableImplicitConversion: true,
			},
		}),
	)

	app.useWebSocketAdapter(new IoAdapter(app))

	const port = process.env.PORT || 3000
	await app.listen(port, '0.0.0.0')
	const url = await app.getUrl()
	logger.log(`🚀 Application is running on: ${url}/${globalPrefix}`)
}

bootstrap()
