import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { json } from 'express';
import { AppModule } from './app.module';
import { HttpExceptionFilter } from './common/filters/http-exception.filter';
import { TransformInterceptor } from './common/interceptors/transform.interceptor';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, { bodyParser: false });

  // Replace Express's JSON parser with one that stringifies BigInt.
  // Express's default `json()` throws "Do not know how to serialize a BigInt".
  app.use(
    json({
      limit: '2mb',
      reviver: (_key: string, value: unknown) => {
        // If a numeric string would overflow the JS number range we keep
        // it as a string; the JWT strategy / services expect bigints.
        if (typeof value === 'string' && /^-?\d{16,}$/.test(value)) {
          // Leave as string — services parse with BigInt().
          return value;
        }
        return value;
      },
    }),
  );

  // CORS
  app.enableCors({
    origin: ['http://localhost:5173', 'http://localhost:3000'],
    credentials: true,
  });

  // Global pipes
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
      transform: true,
      forbidNonWhitelisted: true,
    }),
  );

  // Global filters and interceptors
  app.useGlobalFilters(new HttpExceptionFilter());
  app.useGlobalInterceptors(new TransformInterceptor());

  // Swagger
  const config = new DocumentBuilder()
    .setTitle('InkReach Product Center API')
    .setDescription('Backend API for InkReach Product Center')
    .setVersion('1.0')
    .addBearerAuth()
    .build();

  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('api/docs', app, document);

  const port = process.env.PORT ?? 3001;
  await app.listen(port);
  console.log(`🚀 Application is running on: http://localhost:${port}`);
  console.log(`📚 Swagger documentation: http://localhost:${port}/api/docs`);
}

// Make JSON.stringify aware of BigInt so outgoing responses containing
// primary keys (`BigInt` columns) don't blow up. BigInts are serialized
// as their decimal string — clients should parse them with BigInt().
(BigInt.prototype as unknown as { toJSON: () => string }).toJSON = function () {
  return this.toString();
};

bootstrap();