import {
  Injectable,
  Logger,
  OnApplicationShutdown,
  OnModuleInit,
} from "@nestjs/common";
import { closeDb } from "../../config/database.js";
import { closeEs } from "../../config/elasticsearch.js";

const SERVICE_NAME = "msg";

/**
 * 优雅停机服务。
 *
 * 信号处理由 NestJS 在 `app.listen` 之前调用 `app.enableShutdownHooks()`
 * 触发（SIGTERM / SIGINT），NestJS 会依次调用 OnApplicationShutdown 钩子。
 *
 * 关闭顺序：ES → Drizzle。先关搜索索引避免新数据丢失，再关 DB。
 */
@Injectable()
export class LifecycleService implements OnModuleInit, OnApplicationShutdown {
  private readonly logger = new Logger(LifecycleService.name);

  onModuleInit(): void {
    this.logger.log(`service ${SERVICE_NAME} module initialized`);
  }

  async onApplicationShutdown(signal?: string): Promise<void> {
    this.logger.log(
      `service ${SERVICE_NAME} shutting down (signal=${signal ?? "unknown"})`,
    );

    await this.safeDisconnect("elasticsearch", () => closeEs());
    await this.safeDisconnect("drizzle", () => closeDb());

    this.logger.log(`service ${SERVICE_NAME} shutdown complete`);
  }

  private async safeDisconnect(
    name: string,
    fn: () => Promise<void>,
  ): Promise<void> {
    try {
      await fn();
      this.logger.log(`${name} closed`);
    } catch (error) {
      this.logger.error(
        `${name} close failed: ${error instanceof Error ? error.message : String(error)}`,
      );
    }
  }
}
