import { NestFactory } from "@nestjs/core";
import { ValidationPipe, Logger as NestLogger } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger";
import { AppModule } from "./app.module";
import helmet from "helmet";
import * as express from "express";
import { Logger, LoggerErrorInterceptor } from "nestjs-pino";
import { SanitizeInterceptor } from "./common/interceptors/sanitize.interceptor";

// BigInt serialization polyfill — Prisma returns BigInt for mstUtc etc.
(BigInt.prototype as unknown as { toJSON: () => string }).toJSON = function () {
  return this.toString();
};

async function bootstrap() {
  const logger = new NestLogger("Bootstrap");

  logger.log("🔄 Starting application...");

  const app = await NestFactory.create(AppModule, { bufferLogs: false });

  // Use Pino Logger
  app.useLogger(app.get(Logger));
  app.useGlobalInterceptors(
    new LoggerErrorInterceptor(),
    new SanitizeInterceptor(),
  );

  // Security Headers
  app.use(helmet());

  // Request payload size limit
  app.use(express.json({ limit: "1mb" }));
  app.use(express.urlencoded({ extended: true, limit: "1mb" }));

  // Graceful Shutdown (Prisma & Docker)
  app.enableShutdownHooks();

  // Get config service
  const configService = app.get(ConfigService);
  const port = configService.get<number>("PORT", 3005);
  const nodeEnv = configService.get("NODE_ENV", "development");

  // Enable CORS
  app.enableCors({
    origin:
      nodeEnv === "production"
        ? [
            "https://ui-suggestbet.bilgich.com",
            "https://suggestbet.bilgich.com",
            "https://iddaai.com",
            "https://www.iddaai.com",
            "http://localhost:6195",
          ]
        : true,
    credentials: true,
  });

  // Global prefix
  app.setGlobalPrefix("api");

  // Validation pipe (Strict)
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
      transform: true,
      forbidNonWhitelisted: true,
      transformOptions: {
        enableImplicitConversion: true,
      },
    }),
  );

  // Swagger setup — hidden in production
  if (nodeEnv !== "production") {
    const swaggerConfig = new DocumentBuilder()
      .setTitle("Suggest-Bet API")
      .setDescription(
        "AI-driven sports betting prediction engine with smart coupon generation",
      )
      .setVersion("1.0")
      .addBearerAuth()
      .addTag("Auth", "Authentication endpoints")
      .addTag("Users", "User management endpoints")
      .addTag("Admin", "Admin management endpoints")
      .addTag("Health", "Health check endpoints")
      .addTag("Matches", "Match listing and detail endpoints")
      .addTag("Leagues", "League, country, and team discovery endpoints")
      .addTag("Analysis", "AI analysis and analysis history endpoints")
      .addTag("Coupon", "Coupon generation and coupon management endpoints")
      .addTag("Predictions", "Prediction and smart-coupon endpoints")
      .build();

    logger.log("Initializing Swagger...");
    const document = SwaggerModule.createDocument(app, swaggerConfig);
    SwaggerModule.setup("api/docs", app, document, {
      swaggerOptions: {
        persistAuthorization: true,
      },
    });
    logger.log("Swagger initialized");
  }

  logger.log(`Attempting to listen on port ${port}...`);
  await app.listen(port, "0.0.0.0");

  logger.log("═══════════════════════════════════════════════════════════");
  logger.log(`🚀 Server is running on: http://localhost:${port}/api`);
  logger.log(`📚 Swagger documentation: http://localhost:${port}/api/docs`);
  logger.log(`💚 Health check: http://localhost:${port}/api/health`);
  logger.log(`🌍 Environment: ${nodeEnv.toUpperCase()}`);
  logger.log("═══════════════════════════════════════════════════════════");

  if (nodeEnv === "development") {
    logger.warn("⚠️  Running in development mode");
  }
}

void bootstrap();
