import { Controller, Get, HttpException, HttpStatus } from "@nestjs/common";
import { sql } from "drizzle-orm";
import { getDb } from "../../config/database.js";
import { getNeo4jSession } from "../../config/neo4j.js";
import { isKafkaProducerConnected } from "../../config/kafka.js";
import { env } from "../../config/env.js";

const SERVICE_NAME = "content";

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

interface ReadinessResponse {
  status: "ok" | "error";
  service: string;
  timestamp: string;
  dependencies: DependencyCheck[];
}

@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<ReadinessResponse> {
    const dependencies: DependencyCheck[] = [];

    // 1. DB check
    try {
      await getDb().execute(sql`SELECT 1`);
      dependencies.push({ name: "mysql", status: "ok" });
    } catch (err) {
      dependencies.push({
        name: "mysql",
        status: "error",
        error: err instanceof Error ? err.message : String(err),
      });
    }

    // 2. Neo4j check (optional — only if configured)
    if (env.NEO4J_URL && env.NEO4J_PASSWORD) {
      const session = getNeo4jSession();
      if (!session) {
        dependencies.push({
          name: "neo4j",
          status: "error",
          error: "driver not initialized",
        });
      } else {
        try {
          await session.executeRead((tx) => tx.run("RETURN 1"));
          dependencies.push({ name: "neo4j", status: "ok" });
        } catch (err) {
          dependencies.push({
            name: "neo4j",
            status: "error",
            error: err instanceof Error ? err.message : String(err),
          });
        } finally {
          await session.close();
        }
      }
    } else {
      dependencies.push({
        name: "neo4j",
        status: "ok",
        error: "not configured (optional)",
      });
    }

    // 3. Kafka check (non-blocking — producer may be disconnected if broker unavailable)
    if (isKafkaProducerConnected()) {
      dependencies.push({ name: "kafka", status: "ok" });
    } else {
      dependencies.push({
        name: "kafka",
        status: "error",
        error: "producer not connected",
      });
    }

    const allOk = dependencies.every((d) => d.status === "ok");
    const status = allOk ? "ok" : "error";

    if (!allOk) {
      throw new HttpException(
        {
          status,
          service: SERVICE_NAME,
          timestamp: new Date().toISOString(),
          dependencies,
        } satisfies ReadinessResponse,
        HttpStatus.SERVICE_UNAVAILABLE,
      );
    }

    return {
      status,
      service: SERVICE_NAME,
      timestamp: new Date().toISOString(),
      dependencies,
    } satisfies ReadinessResponse;
  }
}
