import 'reflect-metadata';
import { NestFactory } from '@nestjs/core';
import { Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { apiReference } from '@scalar/nestjs-api-reference';
import { cleanupOpenApiDoc } from 'nestjs-zod';
import helmet from 'helmet';
import { AppModule } from './app.module';
import { AllExceptionsFilter } from './common/filters/all-exceptions.filter';
import { wrapOpenApiResponses } from './openapi/wrap-openapi';

async function bootstrap() {
  // rawBody: true → req.rawBody 保留原始 bytes,push HMAC 验签需要(parsed JSON 字段顺序不稳)
  const app = await NestFactory.create(AppModule, { bufferLogs: true, rawBody: true });

  app.use(helmet({ contentSecurityPolicy: false }));

  const corsOrigins = app.get(ConfigService).getOrThrow<{ origins: string[] }>('cors').origins;
  app.enableCors({
    origin: corsOrigins.length > 0 ? corsOrigins : true,
    credentials: false,
    methods: ['GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'],
    allowedHeaders: ['Authorization', 'Content-Type', 'Accept'],
  });

  app.setGlobalPrefix('pac/v1', {
    exclude: [
      'health',
      'api/docs',
      'api/openapi.json',
      // Bull Board UI(@bull-board/nestjs 自己挂 Express handler,不走 Nest 路由前缀)
      'admin/queues',
      'admin/queues/*path',
    ],
  });

  app.useGlobalFilters(new AllExceptionsFilter());

  const config = new DocumentBuilder()
    .setTitle('PAC API')
    .setDescription(
      'Patient Analyze Center — three-pool framework (facts in, plans out, agents inside).',
    )
    .setVersion('0.1.0')
    .addBearerAuth(
      { type: 'http', scheme: 'bearer', bearerFormat: 'JWT', name: 'Authorization', in: 'header' },
      'accessToken',
    )
    .build();
  const document = wrapOpenApiResponses(
    cleanupOpenApiDoc(SwaggerModule.createDocument(app, config)),
  );

  app.use('/api/openapi.json', (_req: unknown, res: { json: (b: unknown) => void }) =>
    res.json(document),
  );
  app.use(
    '/api/docs',
    apiReference({
      content: document,
      theme: 'purple',
      layout: 'modern',
    }),
  );

  const port = Number(process.env.PORT ?? 3001);
  await app.listen(port, '0.0.0.0');
  Logger.log(`PAC service listening on http://localhost:${port}`, 'Bootstrap');
  Logger.log(`API reference: http://localhost:${port}/api/docs`, 'Bootstrap');
}

bootstrap().catch((err) => {
  console.error('Failed to bootstrap', err);
  process.exit(1);
});
