import 'reflect-metadata';

import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { writeFileSync } from 'fs';
import { join } from 'path';
import { AppModule } from './app.module';
import { AuthenticationGuard } from './domain/auth/AuthenticationGuard';
import { AuthorizationGuard } from './domain/auth/AuthorizationGuard';
import { FeatureAvailabilityGuard } from './domain/policy/FeatureAvailabilityGuard';
import { getGenerateOpenapi } from './env';

async function bootstrap() {
  const generateOpenapi = getGenerateOpenapi();
  
  console.log('🚀 Starting GridPilot API...');
  
  const app = await NestFactory.create(AppModule, {
    logger: ['error', 'warn', 'log'], // Clean logging
    abortOnError: false,
  });

  // CORS for website integration
  app.enableCors({
    credentials: true,
    origin: (origin, callback) => {
      callback(null, origin || false);
    },
  });

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

  try {
    const authGuard = app.get(AuthenticationGuard);
    const authzGuard = app.get(AuthorizationGuard);
    const featureGuard = app.get(FeatureAvailabilityGuard);
    app.useGlobalGuards(authGuard, authzGuard, featureGuard);
  } catch (error) {
    console.error('Failed to register guards:', error);
    throw error;
  }

  // Swagger
  const config = new DocumentBuilder()
    .setTitle('GridPilot API')
    .setDescription('GridPilot API documentation')
    .setVersion('1.0')
    .addTag('dashboard', 'Dashboard endpoints')
    .addTag('races', 'Race management endpoints')
    .addTag('leagues', 'League management endpoints')
    .addTag('teams', 'Team management endpoints')
    .addTag('drivers', 'Driver management endpoints')
    .addTag('sponsors', 'Sponsor management endpoints')
    .addTag('payments', 'Payment and billing endpoints')
    .addTag('media', 'Media and file management endpoints')
    .addTag('analytics', 'Analytics and reporting endpoints')
    .build();

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

  // OpenAPI export
  if (generateOpenapi) {
    const outputPath = join(__dirname, '../openapi.json');
    writeFileSync(outputPath, JSON.stringify(document, null, 2));
    console.log(`✅ OpenAPI spec generated at: ${outputPath}`);
    await app.close();
    process.exit(0);
  }

  // Start server
  try {
    const port = process.env.PORT || 3000;
    await app.listen(port);
    console.log(`✅ API Server started successfully on port ${port}`);
    console.log(`📚 Swagger docs: http://localhost:${port}/api/docs`);
  } catch (error: unknown) {
    console.error('❌ Failed to start API server:', error instanceof Error ? error.message : 'Unknown error');
    process.exit(1);
  }
}

// Handle uncaught errors
process.on('uncaughtException', (error) => {
  console.error('🚨 Uncaught Exception:', error.stack ?? error.message);
  process.exit(1);
});

process.on('unhandledRejection', (reason: unknown) => {
  if (reason instanceof Error) {
    console.error('🚨 Unhandled Rejection:', reason.stack ?? reason.message);
  } else {
    console.error('🚨 Unhandled Rejection:', reason);
  }
  process.exit(1);
});

bootstrap();
