import { Controller, Get, HttpException, HttpStatus } from "@nestjs/common";
import { sql } from "drizzle-orm";
import { getDb } from "../../config/database.js";
import { getRedis } from "../../config/redis.js";
import { getJwtKeyPair } from "../../config/jwt.js";

const SERVICE_NAME = "iam";

interface DependencyCheck {
  name: string;
  status: "ok" | "error";
  error?: string;
}

/**
 * 健康检查端点。
 *
 * - GET /healthz：liveness，仅返回进程存活，不检查依赖
 * - GET /readyz：readiness，检查 5 依赖（DB/Redis/Kafka/gRPC/JWKS），失败返回 503
 */
@Controller()
export class HealthController {
  @Get("healthz")
  liveness(): { status: string; service: string; timestamp: string } {
    return {
      status: "ok",
      service: SERVICE_NAME,
      timestamp: new Date().toISOString(),
    };
  }

  @Get("readyz")
  async readiness(): Promise<{
    status: string;
    service: string;
    timestamp: string;
    dependencies: DependencyCheck[];
  }> {
    const checks: DependencyCheck[] = [];

    // 1. DB
    checks.push(await this.checkDb());

    // 2. Redis
    checks.push(await this.checkRedis());

    // 3. Kafka（检查 producer 连接状态——通过 ping）
    checks.push(await this.checkKafka());

    // 4. JWKS（检查密钥文件已加载）
    checks.push(this.checkJwks());

    // 5. gRPC（本进程内启动，进程存活即 gRPC 存活）
    checks.push({ name: "grpc", status: "ok" });

    const allOk = checks.every((c) => c.status === "ok");
    if (!allOk) {
      throw new HttpException(
        {
          status: "error",
          service: SERVICE_NAME,
          timestamp: new Date().toISOString(),
          dependencies: checks,
        },
        HttpStatus.SERVICE_UNAVAILABLE,
      );
    }

    return {
      status: "ok",
      service: SERVICE_NAME,
      timestamp: new Date().toISOString(),
      dependencies: checks,
    };
  }

  private async checkDb(): Promise<DependencyCheck> {
    try {
      const db = getDb();
      await db.execute(sql`SELECT 1`);
      return { name: "database", status: "ok" };
    } catch (error) {
      return {
        name: "database",
        status: "error",
        error: error instanceof Error ? error.message : String(error),
      };
    }
  }

  private async checkRedis(): Promise<DependencyCheck> {
    try {
      const redis = getRedis();
      const pong = await redis.ping();
      if (pong !== "PONG") {
        return { name: "redis", status: "error", error: `Unexpected: ${pong}` };
      }
      return { name: "redis", status: "ok" };
    } catch (error) {
      return {
        name: "redis",
        status: "error",
        error: error instanceof Error ? error.message : String(error),
      };
    }
  }

  private async checkKafka(): Promise<DependencyCheck> {
    try {
      // Kafka producer 连接状态由 AppModule.onModuleInit 建立
      // 这里仅检查 producer 实例是否可用
      const { getKafkaProducer } = await import("../../config/kafka.js");
      const producer = getKafkaProducer();
      void producer; // 实例存在即视为可用
      return { name: "kafka", status: "ok" };
    } catch (error) {
      return {
        name: "kafka",
        status: "error",
        error: error instanceof Error ? error.message : String(error),
      };
    }
  }

  private checkJwks(): DependencyCheck {
    try {
      getJwtKeyPair();
      return { name: "jwks", status: "ok" };
    } catch (error) {
      return {
        name: "jwks",
        status: "error",
        error: error instanceof Error ? error.message : String(error),
      };
    }
  }
}
