import "reflect-metadata";
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module.js";
import { GlobalErrorFilter } from "./shared/errors/global-error.filter.js";
import { initTracer, shutdownTracer } from "./shared/observability/tracer.js";
import { env } from "./config/env.js";
import { logger } from "./shared/observability/logger.js";
import { checkEsConnection } from "./config/elasticsearch.js";
import { grpcMicroserviceOptions } from "./config/grpc.js";
import { metricsRegistry } from "./shared/observability/metrics.js";
import type { Request, Response } from "express";

/**
 * msg 服务启动入口。
 *
 * 仲裁依据：
 * - M1：gRPC 50056 启用（connectMicroservice）
 * - HTTP REST 3007 + gRPC 50056 双协议入口
 * - enableShutdownHooks()：NestJS 自动处理 SIGTERM/SIGINT → onApplicationShutdown
 *
 * 启动流程：
 * 1. initTracers()：OpenTelemetry 链路追踪
 * 2. checkEsConnection()：ES 探活（降级安全，不阻断启动）
 * 3. NestFactory.create(AppModule)：创建 app，触发 onModuleInit
 *    - LifecycleService.onModuleInit：connectKafka + outboxPublisher.start
 *    - KafkaConsumerService.onModuleInit：connectKafka + consumer.run
 * 4. connectMicroservice(grpcMicroserviceOptions)：注册 gRPC 服务
 * 5. startAllMicroservices()：启动 gRPC 50056
 * 6. listen(PORT)：启动 HTTP REST 3007
 */
async function bootstrap(): Promise<void> {
  initTracer();

  // ES 探活：未配置或失败时进入降级模式，不阻断启动。
  await checkEsConnection();

  const app = await NestFactory.create(AppModule, {
    logger: ["log", "error", "warn"],
  });

  app.useGlobalFilters(new GlobalErrorFilter());
  app.enableShutdownHooks();

  // 注册 gRPC 微服务（50056）
  app.connectMicroservice(grpcMicroserviceOptions);

  // Prometheus 指标端点：不鉴权，供 Prometheus 抓取。
  app.getHttpAdapter().get("/metrics", async (_req: Request, res: Response) => {
    res.set("Content-Type", metricsRegistry.contentType);
    res.end(await metricsRegistry.metrics());
  });

  // 启动 gRPC 微服务 + HTTP 服务
  await app.startAllMicroservices();
  await app.listen(env.PORT);

  logger.info(
    { httpPort: env.PORT, grpcPort: env.GRPC_PORT },
    "Msg service started (HTTP + gRPC)",
  );

  // 兜底信号处理：enableShutdownHooks 已处理 SIGTERM/SIGINT，
  // 此处仅确保进程退出（防止悬挂连接阻塞退出）。
  const shutdown = async (signal: string): Promise<void> => {
    logger.info({ signal }, "Shutting down gracefully...");
    await app.close();
    await shutdownTracer();
    process.exit(0);
  };
  process.on("SIGTERM", () => void shutdown("SIGTERM"));
  process.on("SIGINT", () => void shutdown("SIGINT"));
}

void bootstrap().catch((err: unknown) => {
  logger.error({ err }, "Failed to start msg service");
  process.exit(1);
});
