import {
  Injectable,
  Logger,
  OnApplicationShutdown,
  OnModuleInit,
} from "@nestjs/common";
import { closeDb } from "../../config/database.js";
import { closeRedis } from "../../config/redis.js";
import { disconnectKafkaProducer } from "../../config/kafka.js";

const SERVICE_NAME = "iam";

/**
 * 优雅停机服务。
 *
 * 关闭顺序（president §2.16 + I5 Outbox 依赖 Kafka）：
 * 1. HTTP/gRPC server 已由 NestJS app.close() 停止
 * 2. Kafka producer 断开（停止投递 Outbox 事件）
 * 3. Redis 断开（停止缓存读写）
 * 4. DB 连接池关闭（最后关闭，确保 Outbox publisher 已完成残余投递）
 *
 * K8s terminationGracePeriodSeconds=60 给予足够时间清理。
 */
@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"})`,
    );

    // 1. Kafka producer
    try {
      await disconnectKafkaProducer();
      this.logger.log("Kafka producer disconnected");
    } catch (error) {
      this.logger.error(
        `Kafka producer disconnect failed: ${error instanceof Error ? error.message : String(error)}`,
      );
    }

    // 2. Redis
    try {
      await closeRedis();
      this.logger.log("Redis connection closed");
    } catch (error) {
      this.logger.error(
        `Redis close failed: ${error instanceof Error ? error.message : String(error)}`,
      );
    }

    // 3. DB（最后关闭）
    try {
      await closeDb();
      this.logger.log("database connection closed");
    } catch (error) {
      this.logger.error(
        `database close failed: ${error instanceof Error ? error.message : String(error)}`,
      );
    }

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